Skip to content

Commit

Permalink
feat: Rewrite Windows components in Rust (#26)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: The file location and interface of the Windows component are updated, though it was not intended to be used by end users.

Co-authored-by: Takaya Saeki <abc.tkys+pub@gmail.com>
  • Loading branch information
BlackHoleFox and nullpo-head authored Dec 4, 2021
1 parent 0fd2c6d commit d87ad12
Show file tree
Hide file tree
Showing 29 changed files with 446 additions and 883 deletions.
20 changes: 8 additions & 12 deletions .github/workflows/cicd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,41 +58,37 @@ jobs:
path: build/pam_wsl_hello.so
if-no-files-found: error

build-windows-binaries:
name: "Build Windows binaries"
build-windows-binary:
name: "Build Windows binary"

runs-on: windows-latest

steps:
- uses: actions/checkout@v2

- name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v1.0.2

- name: Build
run: make clean all
working-directory: win_components
run: make clean build/WindowsHelloBridge.exe

- uses: actions/upload-artifact@v2
name: Upload artifacts
with:
name: "Windows Binaries"
path: win_components/build/
name: "Windows Binary"
path: build/WindowsHelloBridge.exe
if-no-files-found: error

release:
name: "Release"

runs-on: ubuntu-latest

needs: [build-pam-module, build-windows-binaries]
needs: [build-pam-module, build-windows-binary]

steps:
- uses: actions/checkout@v2

- uses: actions/download-artifact@v2
with:
name: "Windows Binaries"
name: "Windows Binary"
path: build

- uses: actions/download-artifact@v2
Expand All @@ -106,7 +102,7 @@ jobs:
uses: TriPSs/conventional-changelog-action@v3
with:
github-token: ${{ secrets.github_token }}
version-file: Cargo.toml
version-file: ./wsl_hello_pam/Cargo.toml,./win_hello_bridge/Cargo.toml
version-path: package.version
skip-on-empty: false
git-user-name: "github-actions[bot]"
Expand Down
73 changes: 72 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 9 additions & 17 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,17 +1,9 @@
[package]
name = "wsl_hello_pam"
version = "1.4.0"
authors = ["Takaya Saeki <abc.tkys+pub@gmail.com>"]

[lib]
name = "pam_wsl_hello"
crate-type = ["dylib"]

[dependencies]
libc = "0.2.0"
openssl = "0.10.29"
toml = "0.4"
uuid = { version = "0.5", features = ["v4"] }

[profile.release]
lto = true
[workspace]

members = [
"win_hello_bridge",
"wsl_hello_pam",
]

[profile.release]
lto = true
18 changes: 10 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
RELEASE := release

WIN_CARGO="cargo.exe"

.PHONY: all clean cleanall cleanrelease install release lint

all: build/pam_wsl_hello.so\
build/WindowsHelloAuthenticator/WindowsHelloAuthenticator.exe\
build/WindowsHelloKeyCredentialCreator/WindowsHelloKeyCredentialCreator.exe
all: build/pam_wsl_hello.so build/WindowsHelloBridge.exe

build/pam_wsl_hello.so: | build
cargo build --release
# Build the PAM lib from Linux
cargo build --release -p wsl_hello_pam
strip target/release/libpam_wsl_hello.so
cp ./target/release/libpam_wsl_hello.so build/pam_wsl_hello.so

build/WindowsHelloAuthenticator/WindowsHelloAuthenticator.exe build/WindowsHelloKeyCredentialCreator/WindowsHelloKeyCredentialCreator.exe: | build
$(MAKE) -C win_components all
cp -R win_components/build/* build/
build/WindowsHelloBridge.exe: | build
# Build the authenticator from Windows
$(WIN_CARGO) build -p win_hello_bridge --release
strip target/release/WindowsHelloBridge.exe
cp ./target/release/WindowsHelloBridge.exe ./build

build:
mkdir -p build
Expand All @@ -22,7 +25,6 @@ clean:
cargo clean

cleanall: clean
$(MAKE) -C win_components clean

cleanrelease: cleanall
rm -rf build
Expand Down
18 changes: 5 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ biometric login of [Windows Hello](https://www.microsoft.com/en-us/windows/windo
This PAM module allows you to authenticate `sudo` via face recognition, fingerprint authentication, and of couse machine-local PIN.
It runs in both WSL and WSL 2.

The Linux PAM module is written in Rust, and Windows CLI apps are written in C#.
Both the Linux PAM module and Windows CLI app are written in Rust.
Please use it at your own risk. There is no warranty.

![demo](https://github.com/nullpo-head/WSL-Hello-sudo/blob/master/demo.gif)
Expand All @@ -31,7 +31,7 @@ $ ./install.sh
Although you don't have to care about the detailed installation process,
`install.sh` does following things.

1. Copy small Windows CLI apps that launch Windows Hello to `C:\Users\your_account\pam_wsl_hello` (default location)
1. Copy a small Windows CLI app that launches Windows Hello to `C:\Users\your_account\pam_wsl_hello` (default location)
2. Install a PAM module to your WSL system.
3. Create config files in `/etc/pam_wsl_hello/`
4. Create a pam-configs entry in `/usr/share/pam-configs/` for automatic PAM configuration
Expand Down Expand Up @@ -90,23 +90,16 @@ auth sufficient pam_wsl_hello.so

## Build

The Linux PAM module of "WSL Hello sudo" is written in Rust, and the Windows CLI apps are written in C#.
So, `cargo` and Visual Studio are required to build it.
Both the Linux PAM module and the Windows CLI apps of "WSL Hello sudo" are written in Rust.
So, only `cargo` is required to build it.

Before building "WSL Hello sudo", add the path to `MSBuild.exe` to `PATH` environment variable of __`bash` on WSL__, not Windows.
If you build Windows CLI apps with your Visual Studio GUI, you can ignore that.
In my environment, MSBuild lives in `/mnt/c/Program Files (x86)/Microsoft Visual Studio/2019/Community/MSBuild/Current/Bin/`

To build "WSL Hello sudo", just run `make`.
To build "WSL Hello sudo", make sure you're in WSL and then just run `make`.

```ShellSession
$ git clone https://github.com/nullpo-head/WSL-Hello-sudo.git
$ cd WSL-Hello-sudo
$ make
```
It invokes `cargo` and `MSBuild.exe` properly.

> Whether you're using `bash` or Windows, the repository must be in the Windows filesystem, otherwise `MSBuild.exe` won't work.

## Internals

Expand All @@ -121,4 +114,3 @@ So, the PAM module authenticates the given Linux user by the following process.
3. Windows Hello makes a signature of the given input by the private key of the current Windows user
4. The companion Windows app returns the signature
5. The PAM module verifies the signature by the public key of the Windows user who corresponds to the given Linux user.

45 changes: 32 additions & 13 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ if [ "$(whoami)" = "root" ]; then
exit 1
fi
if [ ! -e build/pam_wsl_hello.so ] || \
[ ! -e build/WindowsHelloAuthenticator/WindowsHelloAuthenticator.exe ] || \
[ ! -e build/WindowsHelloKeyCredentialCreator/WindowsHelloKeyCredentialCreator.exe ]; then
[ ! -e build/WindowsHelloBridge.exe ]; then
echo "No built binary was found. Build first before installing."
exit 1
fi
Expand All @@ -60,26 +59,40 @@ if [[ ! -e "${MNT}" ]]; then
echo -n ": "
read -r MNT
fi

WINUSER=$("${MNT}/Windows/System32/cmd.exe" /C "echo | set /p dummy=%username%") # Hacky. Get Windows's user name without new line
DEF_PAM_WSL_HELLO_WINPATH="${MNT}/Users/$WINUSER/pam_wsl_hello"
echo "Input the install location for Windows Hello authentication components."
echo "They are Windows .exe files and required to be in a valid Windows directory"
DEF_PAM_WSL_HELLO_WINPATH="${MNT}/Users/$WINUSER/AppData/Local/Programs/wsl-hello-sudo"
OLD_DEF_PAM_WSL_HELLO_WINPATH="${MNT}/Users/$WINUSER/pam_wsl_hello"

echo "Input the install location for Windows Hello authentication component."
echo "It is a Windows .exe file and required to be in a valid Windows directory"
echo -n "Default [${DEF_PAM_WSL_HELLO_WINPATH}] :"
read -r PAM_WSL_HELLO_WINPATH

if [ -z "$PAM_WSL_HELLO_WINPATH" ]; then
PAM_WSL_HELLO_WINPATH=$DEF_PAM_WSL_HELLO_WINPATH
fi

if [ ! -e "$PAM_WSL_HELLO_WINPATH" ]; then
if prompt_yn "'$PAM_WSL_HELLO_WINPATH' does not exist. Create it? [Y/n]" "y"; then
set -x
mkdir -p "$PAM_WSL_HELLO_WINPATH"
fi
fi

MAYBE_OLD_KEY_PATH="$OLD_DEF_PAM_WSL_HELLO_WINPATH/pam_wsl_hello_$USER.pem"
KEY_PATH="$PAM_WSL_HELLO_WINPATH/pam_wsl_hello_$USER.pem"
if [ -f "$MAYBE_OLD_KEY_PATH" ]; then
echo "Migrating existing key identity"
mv "$MAYBE_OLD_KEY_PATH" "$KEY_PATH"
rm -r "$OLD_DEF_PAM_WSL_HELLO_WINPATH"
fi

set +x
echo_stage "Installing Windows components of WSL-Hello-sudo..."
echo_stage "Installing Windows component of WSL-Hello-sudo..."
set -x
cp -r build/{WindowsHelloAuthenticator,WindowsHelloKeyCredentialCreator} "$PAM_WSL_HELLO_WINPATH/"
find "$PAM_WSL_HELLO_WINPATH/" -name "*.exe" -print0 | xargs -0 chmod +x
cp build/WindowsHelloBridge.exe "$PAM_WSL_HELLO_WINPATH/"
chmod +x "$PAM_WSL_HELLO_WINPATH/WindowsHelloBridge.exe"

set +x
echo_stage "Installing PAM module to the Linux system..."
Expand Down Expand Up @@ -134,24 +147,30 @@ fi
echo_stage "Creating the config files of WSL-Hello-sudo..."
set -x
sudo mkdir -p /etc/pam_wsl_hello/
PAM_CONFIG_FILENAME="/etc/pam_wsl_hello/config"
AUTHENTICATOR_PATH="authenticator_path = \"$PAM_WSL_HELLO_WINPATH/WindowsHelloBridge.exe\""

set +x
if [ ! -e "/etc/pam_wsl_hello/config" ] || prompt_yn "'/etc/pam_wsl_hello/config' already exists. Overwrite it? [y/N]" "n" ; then
if [ ! -e "$PAM_CONFIG_FILENAME" ] || prompt_yn "'$PAM_CONFIG_FILENAME' already exists. Overwrite it? [y/N]" "n" ; then
set -x
sudo touch /etc/pam_wsl_hello/config
sudo echo "authenticator_path = \"$PAM_WSL_HELLO_WINPATH/WindowsHelloAuthenticator/WindowsHelloAuthenticator.exe\"" | sudo tee /etc/pam_wsl_hello/config
sudo echo "$AUTHENTICATOR_PATH" | sudo tee "$PAM_CONFIG_FILENAME"
sudo echo "win_mnt = \"$MNT\"" | sudo tee -a /etc/pam_wsl_hello/config
elif grep -q "WindowsHelloAuthenticator" "$PAM_CONFIG_FILENAME" ; then
echo "Migrating PAM config to v2.0"
sudo sed -i "1s;authenticator_path.*;$AUTHENTICATOR_PATH;" "$PAM_CONFIG_FILENAME"
else
echo "Skipping creation of '/etc/pam_wsl_hello/config'..."
fi
set +x
echo "Please authenticate yourself now to create a credential for '$USER' and '$WINUSER' pair."
KEY_ALREADY_EXIST_ERR=170
KEY_ALREADY_EXIST_ERR=171
set -x
pushd "$PAM_WSL_HELLO_WINPATH"
WindowsHelloKeyCredentialCreator/WindowsHelloKeyCredentialCreator.exe "pam_wsl_hello_$USER" || test $? = $KEY_ALREADY_EXIST_ERR
./WindowsHelloBridge.exe creator "pam_wsl_hello_$USER" || test $? = $KEY_ALREADY_EXIST_ERR
sudo mkdir -p /etc/pam_wsl_hello/public_keys
popd
sudo cp "$PAM_WSL_HELLO_WINPATH/pam_wsl_hello_$USER.pem" /etc/pam_wsl_hello/public_keys/
sudo cp "$KEY_PATH" /etc/pam_wsl_hello/public_keys/

set +x
echo_stage "Creating uninstall.sh..."
Expand Down
Loading

0 comments on commit d87ad12

Please sign in to comment.