-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
3145f01
commit 00d786d
Showing
12 changed files
with
905 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
converse.o | ||
bin | ||
coverage.* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
language: go | ||
|
||
go: | ||
- 1.13.x | ||
|
||
# Only clone the most recent commit. | ||
git: | ||
depth: 1 | ||
|
||
script: | ||
- make test && bash <(curl -s https://codecov.io/bash) | ||
- make | ||
|
||
deploy: | ||
provider: releases | ||
api_key: $GITHUB_TOKEN | ||
file_glob: true | ||
file: bin/* | ||
skip_cleanup: true | ||
draft: true | ||
on: | ||
tags: true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
MIT License | ||
|
||
Copyright (c) 2019 Ricky Pike | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
EXECUTABLE=bin/pam_opie.so | ||
GOSRCS=authenticate.go pamcgo.go | ||
|
||
$(EXECUTABLE): $(GOSRCS) converse.o | ||
go build -o $(EXECUTABLE) --buildmode=c-shared $(GOSRCS) | ||
rm -f bin/pam_opie.h | ||
|
||
converse.o: converse/converse.c | ||
gcc -c converse/converse.c | ||
|
||
test: | ||
go test -race -coverprofile=coverage.txt -covermode=atomic authenticate.go authenticate_test.go | ||
go tool cover -html=coverage.txt -o coverage.html | ||
|
||
clean: | ||
rm -rf bin converse.o coverage.* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,214 @@ | ||
|
||
# PAM OPIE Module | ||
|
||
[](https://travis-ci.com/arcanericky/pamopie) | ||
[](https://codecov.io/gh/arcanericky/pamopie) | ||
[](http://makeapullrequest.com) | ||
|
||
A PAM OPIE module, but written in Go! _S/KEY authentication like it's 1996_ | ||
|
||
## Quick Start for Debian and SSH | ||
|
||
1. Install the `pam_opie.so` module | ||
|
||
``` | ||
$ cp pam_opie.so /lib/x86_64-linux-gnu/security | ||
``` | ||
|
||
2. Enable the module by adding the following line to `/etc/pam.d/sshd`, above the line reading `@include common-auth` | ||
|
||
``` | ||
auth [success=done cred_unavail=ignore auth_err=die] pam_opie.so config=/etc/opie.json | ||
``` | ||
|
||
3. Enable SSH Challenge Responses in `/etc/ssh/sshd_config` with the line | ||
|
||
``` | ||
ChallengeResponseAuthentication yes | ||
``` | ||
|
||
4. Restart the SSH server | ||
|
||
``` | ||
$ systemctl restart sshd | ||
``` | ||
|
||
5. Configure an OPIE user | ||
|
||
``` | ||
cat > /etc/opie.json <<EOF | ||
{ | ||
"users": [ | ||
{ | ||
"name": "exampleuser", | ||
"passphrase": "examplepassphrase" | ||
} | ||
] | ||
} | ||
EOF | ||
``` | ||
|
||
6. Set configuration file permissions | ||
|
||
``` | ||
$ chmod 600 /etc/opie.json | ||
``` | ||
|
||
7. Get the OPIE prompt | ||
|
||
``` | ||
$ ssh exampleuser@localhost | ||
otp-md5 796 3dxgew ext | ||
Password: | ||
``` | ||
|
||
8. Generate and enter the OPIE challenge response into the above prompt by using [an opiekey utility](https://github.com/arcanericky/opiekey) | ||
|
||
``` | ||
$ opiekey 796 3dxgew examplepassphrase | ||
LIME WRIT CHOU LOVE CUE BURL | ||
``` | ||
|
||
### This OPIE Implementation vs Traditional OPIE | ||
|
||
This OPIE implementation is not drop-in compatible with traditional OPIE implementations. Key differences are: | ||
|
||
#### Limited challenge response entry | ||
|
||
Only MD5 and word (no hex) responses are currently supported. | ||
|
||
#### No utility for the user to change their passphrase | ||
|
||
User configuration must be done by a user that has permissions to the OPIE configuration file. | ||
|
||
#### The configuration file does not contain state | ||
|
||
There is no sequence number used for counting down. Sequence numbers are randomly generated when the login prompt is given. | ||
|
||
#### Challenge seed is random | ||
|
||
It does not follow the traditional format. It is random (but limited to alphanumeric characters) and the length is configurable. | ||
|
||
#### A json formatted configuration file | ||
|
||
The traditional format is line based, per user, and maintains state by counting down the sequence number. Arguably, editing the json format may be more complicated, but it is a standardized format that makes it easy to enforce structure. | ||
|
||
These differences allow for a simpler code base by eliminating race conditions which can happen with traditional OPIE when users change their configuration (two users, or even the same user changing the configuration at the same time), and when two OPIE configured users (different users or even the same user) login at the same time, thus counting down the sequence number. | ||
|
||
### Installation | ||
|
||
These instructions are only an example for use on a Debian-based system and enabling this OPIE module for logins via SSH. | ||
|
||
Install the PAM OPIE module in the default PAM module directory. This is distribution specific. For Debian, this is `/lib/x86_64-linux-gnu/security`. Other locations might be `/usr/lib/security` or `/lib/security`. | ||
``` | ||
$ cp pam_opie.so /lib/x86_64-linux-gnu/security | ||
``` | ||
|
||
Enable Challenge/Response Authentication for the SSH server by enabling the line `ChallengeResponseAuthentication yes` in the `sshd_config` file. For Debian, this file is at `/etc/ssh/sshd_config`. Restart the SSH server after this modification. For Debian this is done with `systemctl restart sshd`. | ||
|
||
Configure PAM to use the OPIE module by adding it to one of the PAM config files. These files are generally in `/etc/pam.d`. Another location might be `/etc/pam.conf`. To configure this on a Debian system for the SSH server, edit `/etc/pam.d/sshd` and place the following line anywhere before `@include common-auth`. PAM configuration can get complicated and I'm no expert at it, but this is what works for me. Note there is no such thing as a PAM service that must be restarted. The following line is a good one to start with: | ||
|
||
``` | ||
auth [success=done cred_unavail=ignore auth_err=die] pam_opie.so config=/etc/opie.json | ||
``` | ||
|
||
The configuration line has a section with `config=/etc/opie.json`. This configures the PAM OPIE module to use `/etc/opie.json` for configuration. This file can be named anything or placed anywhere as long as it has closed permissions (read/write / 0600 only by owner) and configured properly with this config line. | ||
|
||
Note that most traditional OPIE configurations are stored at `/etc/opiekeys`. This OPIE implementation uses a json configuration file and does not follow the traditional, line-based format. | ||
|
||
### OPIE Configuration File | ||
|
||
The configuration file consists of two main sections. The `defaults` and the `users`. To enable OPIE functionality, at least a default or user `passphrase` and at least one `user` must be configured, making a minimal configuration file being: | ||
|
||
``` | ||
{ | ||
"users": [ | ||
{ | ||
"name": "exampleuser", | ||
"passphrase": "examplepassphrase" | ||
} | ||
] | ||
} | ||
``` | ||
|
||
If not specified in the configuration file, the `maxseq` is defaulted to `499`, `retries` to `1` and `seedLen` to `6`. These fields can be specified in the `defaults` section and are applied to all users. Another example: | ||
|
||
``` | ||
{ | ||
"defaults": | ||
{ | ||
"maxseq": 999, | ||
"passphrase": "examplepassphrase", | ||
"retries": 2, | ||
"seedlen": 7 | ||
}, | ||
"users": [ | ||
{ | ||
"name": "exampleuser" | ||
} | ||
] | ||
} | ||
``` | ||
|
||
However, if a user entry contains these fields, it will override those in the `defaults`. For example: | ||
|
||
``` | ||
{ | ||
"defaults": { | ||
"maxseq": 999, | ||
"passphrase": "examplepassphrase", | ||
"retries": 2, | ||
"seedlen": 7 | ||
}, | ||
"users": [ | ||
{ | ||
"name": "exampleuser", | ||
"maxseq": 1313, | ||
"passphrase": "mypersonalpassphrase", | ||
"retries": 3, | ||
"seedlen": 9 | ||
} | ||
] | ||
} | ||
``` | ||
|
||
Not using a `defaults` section is also a valid usage. For example: | ||
|
||
``` | ||
{ | ||
"users": [ | ||
{ | ||
"name": "exampleuser", | ||
"maxseq": 1313, | ||
"passphrase": "mypersonalpassphrase", | ||
"retries": 3, | ||
"seedlen": 9 | ||
} | ||
] | ||
} | ||
``` | ||
|
||
High level configuration errors are logged using syslog in `/var/log/auth.log`. Using `jq` may be useful for validating the json format using a command such as `cat /etc/opie.conf | jq '.'` | ||
|
||
### Validation and Testing | ||
|
||
Once configured as above for Debian and SSH, logins for OPIE-enabled users should yield an OPIE challenge. For example: | ||
|
||
``` | ||
$ ssh exampleuser@localhost | ||
otp-md5 796 3dxgew ext | ||
Password: | ||
``` | ||
|
||
The key elements of the OPIE challenge above are the sequence number `796` and the seed of `3dxgew`. Generate the challenge response using an [opiekey utility](https://github.com/arcanericky/opiekey) and entering the sequence number, seed, and passphrase. For example: | ||
|
||
``` | ||
$ opiekey 796 3dxgew examplepassphrase | ||
LIME WRIT CHOU LOVE CUE BURL | ||
``` | ||
|
||
Entering the generated challenge response above (`LIME WRIT CHOU LOVE CUE BURL`) using copy/paste or by hand should yield a successful login. | ||
|
||
### Inspiration | ||
|
||
I've wanted to take on a project that uses [Go cgo](https://golang.org/cmd/cgo/) and this project which creates a shared object that is called from existing C code, where the shared object makes calls back into C satisfies my curiosity to make these calls in both directions. OPIE is also implemented on a few servers for my professional job, but the traditional OPIE implementation is less than ideal for our usage. This implementation contains some experimental variations to resolve some of those shortcomings and being written mostly in Go, is much easier to maintain than the original C implementation. |
Oops, something went wrong.