Password function

This commit is contained in:
Bandie 2018-04-01 01:53:41 +02:00
parent 721f63774c
commit b31cc5948b
Signed by: Bandie
GPG Key ID: C1E133BC65A822DD
19 changed files with 773 additions and 254 deletions

View File

@ -1,3 +1,8 @@
PREFIX = /usr/local/bin
PPASSPATH = /var/lib/pam_panic
PPASSFILE = $(PPASSPATH)/auth
POSSIBLE_PAMDIRS = /lib/x86_64-linux-gnu/security /lib/security
PAMDIR = $(shell make detect_pamdir)
MANDIR = /usr/share/man
@ -7,10 +12,11 @@ all:
@which poweroff >/dev/null
@which cryptsetup >/dev/null
mkdir -p build obj
make -C src
make -C src -e "PPASSFILE = $(PPASSFILE)"
@printf "Done!\n"
clean:
rm build/pam_panic.so
rm build/pam_panic_pw
rm obj/pam_panic.o
rmdir build obj
@printf "Done!\n"
@ -18,15 +24,24 @@ clean:
detect_pamdir:
@for d in $(POSSIBLE_PAMDIRS); do if [ ! -d $${d} ]; then continue; else printf "$${d}\n"; fi; done
purge:
rm /var/lib/pam_panic/*
rmdir /var/lib/pam_panic
@printf "Done!\n"
uninstall:
PAMDIR=$(PAMDIR); rm $${PAMDIR}/pam_panic.so
rm /usr/share/man/*/pam_panic.8.gz
rm /usr/share/man/*/pam_panic_pw.1.gz
rm $(PREFIX)/pam_panic_pw
@printf "Done!\n"
install:
PAMDIR=$(PAMDIR); if [ -z $${PAMDIR} ]; then printf "Error: PAM's shared object directory was not detected. If you know where it is, please add to POSSIBLE_PAMDIRS and make a pull request.\n"&& exit 1; else cp build/pam_panic.so $${PAMDIR}/pam_panic.so; fi
if [ ! -d $(MANDIR) ]; then printf "Error: Where is the manpage directory?\n" && exit 1; else make install -C man -e "MANDIR = $(MANDIR)"; fi
mkdir -p $(PPASSPATH)
cp build/pam_panic_pw $(PREFIX)/pam_panic_pw
@printf "Done!\n"
test:
@printf "We only can test it in production.\n"
@printf "We only can test it in production, yet.\n"

View File

@ -4,9 +4,18 @@
## Purpose
pam\_panic is a PAM module that protects sensitive data and provices a panic function for emergency situations.
## How it works
You can choose one of two options:
### Using two removable media
There are two removable media which work as keys: the auth key and the panic key. The auth key will let you pass to the password prompt whereas the panic key, if provided, will securely erase the LUKS header, rendering the data unreadable.
### Using two passwords previous your own password
There are two passwords you are able to set: the key password and the panic password. The key password will let you pass to the original password prompt whereas the panic password, if provided, will securely erase the LUKS header, rendering the data unreadable.
## Installation
You will need GCC or similar, as well as the PAM headers. Some distributions package the PAM headers as `libpam0g-dev`.
@ -20,6 +29,7 @@ sudo make install
Note: the paths of the `reboot`, `poweroff`, and `cryptsetup` commands are passed to the module at compile-time.
## Preparation
In that case you want to use removable media:
You'll need two GPT-formatted removable storage devices, and said devices must have at least one partition. Here's an example `fdisk` session, showing how this might be accomplished:
```
@ -45,17 +55,24 @@ Command (m for help): w
You'll find the UUID of your partition in `/dev/disk/by-partuuid/`. You can find out which device is which typing `ls -l /dev/disk/by-partuuid/` in your favourite shell.
## Configuration
To configure the module, add the following to the appropriate PAM configuration file(s): (see pam.conf(5) for details on these files)
To configure the module, add the following to the appropriate PAM configuration file(s): (see pam.conf(5) for details on these files).
### Using the removable media:
```
auth requisite pam_panic.so auth=<UUID> reject=<UUID> reboot serious=<UUID>
account requisite pam_panic.so
```
### Using the two passwords:
```
auth requisite pam_panic.so password reboot serious=<UUID>
account requisite pam_panic.so
```
See `man 8 pam_panic` for more.
## TODO
- [Manpage translations](https://github.com/Bandie/pam_panic/issues?q=is%3Aissue+is%3Aopen+label%3Alocalization)
- Integrate [panic password](https://github.com/Bandie/pam_panic/issues/7)

View File

@ -1,2 +1,11 @@
install:
.PHONY: man1 man8
man1:
for f in `find . -name pam_panic_pw.1 | sed 's/\/pam_panic_pw.1//'`; do gzip -9 -c $${f}/pam_panic_pw.1 > $(MANDIR)/$${f}/pam_panic_pw.1.gz; done
man8:
for f in `find . -name pam_panic.8 | sed 's/\/pam_panic.8//'`; do gzip -9 -c $${f}/pam_panic.8 > $(MANDIR)/$${f}/pam_panic.8.gz; done
install:
make man1
make man8

View File

@ -0,0 +1,89 @@
'\" t
.\" Title: pam_panic_pw
.\" Author: [see the "AUTHORS" section]
.\" Date: 2018-03-31
.\" Manual: PAM Panic Manual
.\" Source: PAM Panic Manual
.\" Language: German
.\"
.TH "PAM_PANIC_PW" "8" "2018-03-31" "PAM Panic Handbuch" "PAM Panic Handbuch"
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.\" disable hyphenation
.nh
.\" disable justification (adjust text to left margin only)
.ad l
.\" -----------------------------------------------------------------
.\" * MAIN CONTENT STARTS HERE *
.\" -----------------------------------------------------------------
.SH "NAME"
pam_panic_pw \- Setzen der Passw\(:orter f\(:ur das \fBpam_panic\fR(8) PAM Modul\&.
.SH "\(:UBERSICHT"
.HP \w'\fBpam_panic_pw\fR\ 'u
\fBpam_panic_pw\fR
.SH "BESCHREIBUNG"
.PP
Es setzt die Passw\(:orter f\(:ur das \fBpam_panic\fR(8) PAM Modul\&.
.PP
Dabei gibt es das "Key password" und das "Panic password"\&.
Das "Key password" dient zur normalen Authentifizierung
w\(:ahrend das "Panic password" die Panikfunktion ausf\(:uhrt\&.
.SH "R\(:UCKGABEWERTE"
.PP
0
.RS 4
Passw\(:orter erfolgreich gesetzt\&.
.RE
.PP
1
.RS 4
Keine Berechtigung\&.
.RE
.PP
2
.RS 4
Die Passwortdatei konnte nicht ge\(:offnet werden\&.
.RE
.SH "DATEIEN"
.PP
/usr/local/bin/pam_panic_pw
.RS 4
Programm zum Setzen und Ver\(:andern der Passw\(:orter\&.
.RE
.PP
/var/lib/pam_panic/auth
.RS 4
Die Passwortdatei\&.
.RE
.SH "BUGS"
.PP
Fehlerberichte (m\(:oglichst auf Englisch) und Codeverbesserungen k\(:onnen hier eingereicht werden: https://github.com/Bandie/pam_panic
.SH "SIEHE AUCH"
.PP
\fBpam_panic\fR(8),
\fBcryptsetup\fR(8),
\fBpam\&.conf\fR(5),
\fBpam\fR(8)\&.
.SH "AUTOREN"
.PD 0
.PP
Dieses pam_panic PAM Modul wurde durch Bandie <bandie@chaospott\&.de> entwickelt\&.

View File

@ -1,12 +1,12 @@
'\" t
.\" Title: pam_panic
.\" Author: [see the "AUTHORS" section]
.\" Date: 2018-03-26
.\" Date: 2018-03-31
.\" Manual: PAM Panic Manual
.\" Source: PAM Panic Manual
.\" Language: German
.\"
.TH "PAM_PANIC" "8" "2018-03-26" "PAM Panic Manual" "PAM Panic Manual"
.TH "PAM_PANIC" "8" "2018-03-31" "PAM Panic Handbuch" "PAM Panic Handbuch"
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.\" -----------------------------------------------------------------
@ -21,28 +21,62 @@
.\" -----------------------------------------------------------------
.SH "NAME"
pam_panic \- PAM module zur Authentifizierung durch Wechseldatentr\(:agern mit Panik-Funktion
pam_panic \- PAM-Modul mit Panik-Funktion zum Sch\(:utzen von wichtigen Daten in Notsituationen
.SH "\(:UBERSICHT"
.HP \w'\fBpam_panic\&.so\fR\ 'u
\fBpam_panic\&.so\fR [allow=\fIUUID(GPT)\fR] [reject=\fIUUID(GPT)\fR] [reboot] [poweroff] [serious=\fIUUID\fR]
\fBpam_panic\&.so\fR [password] [allow=\fIUUID(GPT)\fR] [reject=\fIUUID(GPT)\fR] [reboot] [poweroff] [serious=\fIUUID\fR]
.SH "BESCHREIBUNG"
.PP
Das pam_panic PAM module wurde mit dem Hintergedanken entwickelt, Personen mit wichtigen Daten zu sch\(:utzen.\&. Es bietet eine Panik-Function\&.
Das pam_panic PAM Modul wurde mit dem Hintergedanken entwickelt, Personen mit wichtigen Daten zu sch\(:utzen\&. Es bietet eine Panik-Funktion\&.
.PP
Es gibt zwei M\(:oglichkeiten der Verwendung:
.PD 0
.PP
Erste M\(:oglichkeit:
.RS 2
Man verwendet zwei Wecheldatentr\(:ager, die als Schl\(:ussel dienen\&.
Hierbei funktioniert eines als Authentifizierungsschl\(:ussel und eines als Panikschl\(:ussel\&.
Der Panikschl\(:ussel ruft die Panik-Funktion auf, die, sofern die Option \fBserious\fR aktiviert wurde, "\fBcryptsetup luksErase [UUID]\fR" ausf\(:uhrt\&.
Dieses wird dann den luksHeader zerst\(:oren\&.
Das hei\(sst, dass die Daten auf den in den Optionen angegebenen Datentr\(:ager f\(:ur niemanden mehr lesbar sein werden\&.
Der Panikschl\(:ussel f\(:uhrt die \fIPanikfunktion\fR aus\&.
.PD 0
.PP
Siehe dazu die Optionen \fBallow\fR und \fBreject\fR\&.
.RE
.PP
Zweite M\(:oglichkeit:
.RS 2
Man verwendet zwei Passw\(:orter, die als Schl\(:ussel dienen\&.
Dabei wird ein Schl\(:usselpasswort (Key password) und ein Panikpasswort (Panic password) festgelegt\&.
Das Panikpasswort wird hierbei die \fIPanikfunktion\fR aufrufen\&.
.PD 0
.PP
Siehe dazu die Option \fBpassword\fR\&.
.RE
.PD 1
.PP
Die Panikfunktion:
.RS 2
Das Verhalten der Panikfunktion wird durch die Argumente \fBreboot\fR, \fBpoweroff\fR und/oder \fBserious\fR definiert\&.
.RE
.SH "OPTIONEN"
.PP
\fBallow=\fR\fB\fIUUID(GPT)\fR\fR (erforderlich)
\fBpassword\fR
.RS 4
Diese Option aktiviert die Passwortfunktion mit einem Panikpasswort und einem Schl\(:usselpasswort. Wenn \fBallow\fR und \fBreject\fR gesetzt sind, wird diese Option ignoriert.
.PD 0
.PP
.PD 1
Um die Passw\(:orter zu setzen steht das Programm \fBpam_panic_pw\fR(1) zur Verf\(:ugung.
.RE
.PP
\fBallow=\fR\fB\fIUUID(GPT)\fR\fR
.RS 4
Diese Ger\(:ate-UUID wird zur Authentifizierung benutzt (Authentifierungsschl\(:ussel)\&.
.PD 0
@ -55,7 +89,7 @@ Weitere Informationen im Abschnitt \fBWIE BESTIMME ICH MEINE UUIDS\fR\&.
.RE
.PP
\fBreject=\fR\fB\fIUUID(GPT)\fR\fR (erforderlich)
\fBreject=\fR\fB\fIUUID(GPT)\fR\fR
.RS 4
Diese Ger\(:ate-UUID wird \fBreboot\fR, \fBpoweroff\fR und/oder die Panik-Funktion \fBserious\fR, sofern als Argument angegeben, aufrufen\& (Panikschl\(:ussel).
.PD 0
@ -86,7 +120,12 @@ Aus Sicherheitsgr\(:unden wird von dieser Option abgeraten\&.
\fBserious=\fR\fB\fIUUID\fR\fR
.RS 4
Die Ger\(:ate-UUID, bei dem der luksHeaders zerst\(:ort werden w\(:urde, sobald der Wecheldatentr\(:ager mit der UUID des Arguments \fBreject=UUID(GPT)\fR eingelegt wurde\&.
Die Ger\(:ate-UUID, dessen luksHeaders zerst\(:ort werden w\(:urde, sobald der Wecheldatentr\(:ager mit der UUID des Arguments \fBreject=UUID(GPT)\fR eingelegt wurde\&.
Das hei\(sst, dass die Daten auf den in den Optionen angegebenen Datentr\(:ager f\(:ur niemanden mehr lesbar sein werden\&.
.PD 0
.PP
Intern wird das Programm "\fBcryptsetup luksErase [UUID]\fR" ausgef\(:uhrt\&.
.PD 1
.PP
(Eine Erinnerung daran, ein luksHeader-Backup zu machen bevor diese Funktion benutzt wird.\&.)
.RE
@ -104,6 +143,12 @@ auth requisite pam_panic.so auth=<UUID> reject=<UUID> reboot serious=<U
.PP
account requisite pam_panic.so
.RE
Oder auch:
.RS 4
auth requisite pam_panic.so password reboot serious=<UUID>
.PP
account requisite pam_panic.so
.RE
.PD 1
@ -117,7 +162,7 @@ Um nachvollziehen zu k\(:onnen, welcher Wecheldatentr\(:ager welches ist, ist es
.PP
PAM_SUCCESS
.RS 4
Zugriff wurde gew\(:ahrt.\&.
Zugriff wurde gew\(:ahrt\&.
.RE
.PP
PAM_IGNORE
@ -138,9 +183,9 @@ Der Wecheldatentr\(:ager wurde nicht erkannt\&.
Shared object-Datei, die f\(:ur alles zust\(:andig ist\&.
.RE
.PP
/usr/share/man/*/man8/pam_panic\&.8\&.gz
/usr/local/bin/pam_panic_pw
.RS 4
Die Manpages\&.
Programm zum Setzen und Ver\(:andern der Passw\(:orter\&.
.RE
@ -151,6 +196,7 @@ Fehlerberichte (m\(:oglichst auf Englisch) und Codeverbesserungen k\(:onnen hier
.SH "SIEHE AUCH"
.PP
\fBpam_panic_pw\fR(1),
\fBcryptsetup\fR(8),
\fBpam\&.conf\fR(5),
\fBpam\fR(8)\&.

92
man/man1/pam_panic_pw.1 Normal file
View File

@ -0,0 +1,92 @@
'\" t
.\" Title: pam_panic_pw
.\" Author: [see the "AUTHORS" section]
.\" Date: 2018-03-31
.\" Manual: PAM Panic Manual
.\" Source: PAM Panic Manual
.\" Language: English
.\"
.TH "PAM_PANIC_PW" "8" "2018-03-31" "PAM Panic Manual" "PAM Panic Manual"
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.\" disable hyphenation
.nh
.\" disable justification (adjust text to left margin only)
.ad l
.\" -----------------------------------------------------------------
.\" * MAIN CONTENT STARTS HERE *
.\" -----------------------------------------------------------------
.SH "NAME"
pam_panic_pw \- Set and change the passwords for the \fBpam_panic\fR(8) PAM module\&.
.SH "SYNOPSIS"
.HP \w'\fBpam_panic_pw\fR\ 'u
\fBpam_panic_pw\fR
.SH "DESCRIPTION"
.PP
It sets the passwords for the \fBpam_panic\fR(8) PAM module\&.
.PP
There are two passwords: The "Key password" and the "Panic password"\&.
The "Key password" is used for the normal authentication
whereas the "Panic password" will execute the panic function\&.
.SH "RETURN VALUES"
.PP
0
.RS 4
Passwords set successfully\&.
.RE
.PP
1
.RS 4
Access denied\&.
.RE
.PP
2
.RS 4
Could not open the password file\&.
.RE
.SH "FILES"
.PP
/usr/local/bin/pam_panic_pw
.RS 4
Program to set and change the passwords\&.
.RE
.PP
/var/lib/pam_panic/auth
.RS 4
The password file\&.
.RE
.SH "BUGS"
.PP
Fehlerberichte (m\(:oglichst auf Englisch) und Codeverbesserungen k\(:onnen hier eingereicht werden: https://github.com/Bandie/pam_panic
.SH "SEE ALSO"
.PP
\fBpam_panic\fR(8),
\fBcryptsetup\fR(8),
\fBpam\&.conf\fR(5),
\fBpam\fR(8)\&.
.SH "AUTHORS"
.PD 0
.PP
pam_panic was written by Bandie <bandie@chaospott\&.de>\&.
.PP
This man page has been revised by Jordy Dickinson <jordy\&.dickinson@icloud\&.com>

View File

@ -22,23 +22,53 @@
.SH "NAME"
pam_panic \- PAM module for access control using removable media (with panic function)
pam_panic \- PAM module with panic function to protect sensitive data in emergency situations
.SH "SYNOPSIS"
.HP \w'\fBpam_panic\&.so\fR\ 'u
\fBpam_panic\&.so\fR [allow=\fIUUID(GPT)\fR] [reject=\fIUUID(GPT)\fR] [reboot] [poweroff] [serious=\fIUUID\fR]
\fBpam_panic\&.so\fR [password] [allow=\fIUUID(GPT)\fR] [reject=\fIUUID(GPT)\fR] [reboot] [poweroff] [serious=\fIUUID\fR]
.SH "DESCRIPTION"
.PP
The pam_panic PAM module protects sensitive data and provides a panic function for emergency situations\&.
.PP
There are two removable media which work as keys: the auth key and the panic key\&. The auth key will let you pass to the password prompt whereas the panic key, if provided, will securely erase the LUKS header, rendering the data unreadable\&.
There are two possible options in how to use this PAM module:
.PD 0
.PP
First possible option:
.RS 2
There are two removable media which work as keys: the auth key and the panic key\&.
The auth key will let you pass to the password prompt whereas the panic key will execute the panic function\&.
.RE
Second possible option:
.RS 2
There are two passwords: the key password and the panic password\&. The key password will let you pass to the original password prompt whereas the panic password will execute the panic function\&.
.RE
.PD 1
.PP
The panic function:
.RS 2
Its behaviour is defined through the arguments \fBreboot\fR, \fBpoweroff\fR and/or \fBserious\fR\&.
.RE
.SH "OPTIONS"
.PP
\fBallow=\fR\fB\fIUUID(GPT)\fR\fR (required)
\fBpassword\fR
.RS 4
Activates the password function having a panic and key password\&.
If the options \fBallow\fR and \fBreject\fR are provided this option will be ignored\&.
.PD 0
.PP
To set the passwords the program \fBpam_panic_pw\fR(1) is provided\&.
.RE
.PD 1
.PP
\fBallow=\fR\fB\fIUUID(GPT)\fR\fR
.RS 4
The UUID of the device to be used for authentication (the auth key)\&.
.PD 0
@ -51,7 +81,7 @@ See \fBHOW TO DETERMINE MY UUIDS\fR for details\&.
.RE
.PP
\fBreject=\fR\fB\fIUUID(GPT)\fR\fR (required)
\fBreject=\fR\fB\fIUUID(GPT)\fR\fR
.RS 4
The UUID of the device to be used in emergencies. The presence of this device will trigger \fBreboot\fR, \fBpoweroff\fR and/or the panic function, depending on whether \fBreboot\fR, \fBpoweroff\fR, and/or \fBserious\fR are specified.
.PD 0
@ -82,6 +112,7 @@ This option is discouraged for security reasons\&.
\fBserious=\fR\fB\fIUUID\fR\fR
.RS 4
The UUID of the device containing the LUKS header to erase upon encountering the device specified with \fBreject\fR\&.
Erasing the LUKS header will render the data unreadable\&.
.PP
NOTE: You should make a backup of the LUKS header before using this function\&.
.RE
@ -99,6 +130,12 @@ auth requisite pam_panic\&.so auth=<UUID> reject=<UUID> reboot serious=
.PP
account requisite pam_panic\&.so
.RE
Or:
.RS 4
auth requisite pam_panic.so password reboot serious=<UUID>
.PP
account requisite pam_panic.so
.RE
.PD 1
@ -132,6 +169,11 @@ The removable media was not detected\&.
.RS 4
This PAM module\&.
.RE
.PP
/usr/local/bin/pam_panic_pw
.RS 4
Program to set and change the passwords\&.
.RE
.SH "BUGS"
@ -141,7 +183,10 @@ Please report bugs and send pull requests to <https://github\&.com/Bandie/pam_pa
.SH "SEE ALSO"
.PP
\fBcryptsetup\fR(8), \fBpam\fR(8), \fBpam\&.conf\fR(5)
\fBpam_panic_pw\fR(1),
\fBcryptsetup\fR(8),
\fBpam\fR(8),
\fBpam\&.conf\fR(5)
.SH "AUTHORS"

View File

@ -1,9 +1,3 @@
CFLAGS = --std=c99 -O2 -fPIC -DPOWEROFF=\"`which poweroff`\" -DREBOOT=\"`which reboot`\" -DCRYPTSETUP=\"`which cryptsetup`\"
LDFLAGS = -x --shared
all:
mkdir -p ../obj
mkdir -p ../build
cc $(CFLAGS) -c pam_panic.c -o ../obj/pam_panic.o
ld $(LDFLAGS) -o ../build/pam_panic.so ../obj/pam_panic.o
make -C pam_panic -e "PPASSFILE = $(PPASSFILE)"
make -C pam_panic_pw -e "PPASSFILE = $(PPASSFILE)"

View File

@ -1,220 +0,0 @@
/*
FILENAME : pam_panic.c
DESCRIPTION : The pam_panic PAM module shall protect people who have value data on their computer. It provides a panic function.
AUTHOR : Bandie
DATE : 2018-03-27T02:34:08+02:00
LICENSE : GNU-GPLv3
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <regex.h>
#include <string.h>
#include <security/pam_modules.h>
#include <security/pam_ext.h>
#include <syslog.h>
#ifdef REBOOT
#ifdef POWEROFF
#ifdef CRYPTSETUP
#define ASK "Please enter your secret key to decrypt the firewall and access the mainframe. "
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char *argv[])
{
char *resp;
char *allowed_arg = malloc(128 * sizeof(char));
char *rejected_arg = malloc(128 * sizeof(char));
char *serious_arg = malloc(128 * sizeof(char));
char *allowed_temp = NULL;
char *rejected_temp = NULL;
char *serious_temp = NULL;
char *allowed = malloc(60 * sizeof(char));
char *rejected = malloc(60 * sizeof(char));
char *serious_dev = malloc(60 * sizeof(char));
int8_t serious = 0;
int8_t reboot = 0;
int8_t poweroff = 0;
// Regex for checking arguments
char *pattern = "^[A-Fa-f0-9]\\{8\\}\\-[A-Fa-f0-9]\\{4\\}\\-[A-Fa-f0-9]\\{4\\}\\-[A-Fa-f0-9]\\{4\\}\\-[A-Fa-f0-9]\\{12\\}$";
regex_t regex;
if(regcomp(&regex, pattern, 0)){
pam_syslog(pamh, LOG_CRIT, "ERROR: Problem with regcomp.");
return (PAM_IGNORE);
}
// Check number of arguments
if(argc<2){
pam_syslog(pamh, LOG_ERR, "Missing arguments.");
return (PAM_IGNORE);
}
// Argument handling
for(int i=0; i<argc; i++){
if(strstr(argv[i], "allow") != NULL){
strncpy(allowed_arg, argv[i], 128);
allowed_temp = strtok(allowed_arg, "=");
allowed_temp = strtok(NULL, "=");
}
if(strstr(argv[i], "reject") != NULL){
strncpy(rejected_arg, argv[i], 128);
rejected_temp = strtok(rejected_arg, "=");
rejected_temp = strtok(NULL, "=");
}
if(strstr(argv[i], "reboot") != NULL){
reboot = 1;
}
if(strstr(argv[i], "poweroff") != NULL){
poweroff = 1;
}
if(strstr(argv[i], "serious") != NULL){
strncpy(serious_arg, argv[i], 128);
serious_temp = strtok(serious_arg, "=");
serious_temp = strtok(NULL, "=");
serious = 1;
}
}
// Poweroff wins.
if(reboot && poweroff)
reboot = 0;
// Checking arguments
if(
allowed_temp == NULL
|| rejected_temp == NULL
|| regexec(&regex, allowed_temp, 0, NULL, 0) == REG_NOMATCH
|| regexec(&regex, rejected_temp, 0, NULL, 0) == REG_NOMATCH
|| (serious && serious_temp == NULL)
) {
pam_syslog(pamh, LOG_ERR, "Argument invalid. Note that allow and reject must have a valid GPT UUID.");
return (PAM_IGNORE);
}
// Construct variables from arguments
sprintf(rejected, "/dev/disk/by-partuuid/%s", rejected_temp);
sprintf(allowed, "/dev/disk/by-partuuid/%s", allowed_temp);
if(serious)
sprintf(serious_dev, "/dev/disk/by-partuuid/%s", serious_temp);
// Free not needed vars
free(rejected_arg);
free(allowed_arg);
free(serious_arg);
// Check if panic key exist
if(serious && access(serious_dev, F_OK) == -1){
pam_syslog(pamh, LOG_ALERT, "ALERT for argument \"serious\": Device doesn't exist.\n");
return (PAM_IGNORE);
}
// Prompt for (auth|panic) key
int8_t counter = 0;
while(access(allowed, F_OK) == -1 && access(rejected, F_OK) == -1){
pam_prompt(pamh, PAM_PROMPT_ECHO_OFF, &resp, ASK);
if(++counter >= 3){
pam_syslog(pamh, LOG_NOTICE, "Couldn't identify any keys. 3 tries.");
return (PAM_MAXTRIES);
}
}
// Auth key? OK!
if(access(allowed, F_OK) != -1)
return (PAM_SUCCESS);
// Panic key? PANIC!!1
if(access(rejected, F_OK) != -1){
if(serious){
int ser_stat;
int yes[2];
pipe(yes);
if(fork() == 0){
close(yes[1]);
dup2(yes[0], 0);
execlp(CRYPTSETUP, CRYPTSETUP, "luksErase", serious_dev, NULL);
}else {
close(yes[0]);
write(yes[1], "YES\n", 4);
close(yes[1]);
wait(&ser_stat);
}
}
if(reboot)
execlp(REBOOT, REBOOT, NULL);
if(poweroff)
execlp(POWEROFF, POWEROFF, NULL);
return (PAM_MAXTRIES);
}
return (PAM_MAXTRIES);
}
// Fuck all of this below.
PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char *argv[])
{
return (PAM_SUCCESS);
}
PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char *argv[])
{
return (PAM_SUCCESS);
}
PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char *argv[])
{
return (PAM_SUCCESS);
}
PAM_EXTERN int pam_sm_close_session(pam_handle_t *pamh, int flags, int argc, const char *argv[])
{
return (PAM_SUCCESS);
}
PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char *argv[])
{
return (PAM_SERVICE_ERR);
}
#endif
#endif
#endif

9
src/pam_panic/Makefile Normal file
View File

@ -0,0 +1,9 @@
CFLAGS = --std=gnu11 -O2 -fPIC -DPOWEROFF=\"`which poweroff`\" -DREBOOT=\"`which reboot`\" -DCRYPTSETUP=\"`which cryptsetup`\" -DPPASSFILE=\"$(PPASSFILE)\"
LDFLAGS = -x --shared -lcrypt
all:
mkdir -p ../../obj
mkdir -p ../../build
cc $(CFLAGS) -c pam_panic.c -o ../../obj/pam_panic.o
ld $(LDFLAGS) -o ../../build/pam_panic.so ../../obj/pam_panic.o

193
src/pam_panic/pam_panic.c Normal file
View File

@ -0,0 +1,193 @@
/*
FILENAME : pam_panic.c
DESCRIPTION : The pam_panic PAM module shall protect people who have value data on their computer. It provides a panic function.
AUTHOR : Bandie
DATE : 2018-03-27T02:34:08+02:00
LICENSE : GNU-GPLv3
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <regex.h>
#include <string.h>
#include <security/pam_modules.h>
#include <security/pam_ext.h>
#include <syslog.h>
#include "pam_panic_reject.h"
#include "pam_panic_authdevice.h"
#include "pam_panic_password.h"
#ifdef REBOOT
#ifdef POWEROFF
#ifdef CRYPTSETUP
void argSplit(char **some_arg, char **some_temp, const char *arg){
strncpy(*some_arg, arg, 128);
*some_temp = strtok(*some_arg, "=");
*some_temp = strtok(NULL, "=");
}
void constrPath(char **dst, char **src){
sprintf(*dst, "/dev/disk/by-partuuid/%s", *src);
}
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char *argv[]){
// Devices
char *allowed_arg = malloc(128 * sizeof(char));
char *rejected_arg = malloc(128 * sizeof(char));
char *serious_arg = malloc(128 * sizeof(char));
char *allowed_temp = NULL;
char *rejected_temp = NULL;
char *serious_temp = NULL;
char *allowed = malloc(60 * sizeof(char));
char *rejected = malloc(60 * sizeof(char));
char *serious_dev = malloc(60 * sizeof(char));
// Switches
int8_t bSerious = 0;
int8_t bReboot = 0;
int8_t bPoweroff = 0;
int8_t bPassword = 0;
// Regex for checking arguments
char *pattern = "^[A-Fa-f0-9]\\{8\\}\\-[A-Fa-f0-9]\\{4\\}\\-[A-Fa-f0-9]\\{4\\}\\-[A-Fa-f0-9]\\{4\\}\\-[A-Fa-f0-9]\\{12\\}$";
regex_t regex;
if(regcomp(&regex, pattern, 0)){
pam_syslog(pamh, LOG_CRIT, "ERROR: Problem with regcomp.");
return (PAM_IGNORE);
}
// Argument handling
for(int i=0; i<argc; i++){
if(strstr(argv[i], "allow") != NULL)
argSplit(&allowed_arg, &allowed_temp, argv[i]);
if(strstr(argv[i], "reject") != NULL)
argSplit(&rejected_arg, &rejected_temp, argv[i]);
if(strstr(argv[i], "reboot") != NULL)
bReboot = 1;
if(strstr(argv[i], "poweroff") != NULL)
bPoweroff = 1;
if(strstr(argv[i], "password") != NULL){
bPassword = 1;
}
if(strstr(argv[i], "serious") != NULL){
argSplit(&serious_arg, &serious_temp, argv[i]);
bSerious = 1;
}
}
// Checking arguments
if(
(allowed_temp == NULL && !bPassword)
|| (rejected_temp == NULL && !bPassword)
|| (allowed_temp != NULL && regexec(&regex, allowed_temp, 0, NULL, 0) == REG_NOMATCH)
|| (rejected_temp != NULL && regexec(&regex, rejected_temp, 0, NULL, 0) == REG_NOMATCH)
|| (bSerious && serious_temp == NULL)
) {
pam_syslog(pamh, LOG_ERR, "Arguments invalid. Note that allow and reject must have a valid GPT UUID.");
return (PAM_IGNORE);
}
// Poweroff wins.
if(bReboot && bPoweroff)
bReboot = 0;
// Devices will win
if(bPassword && allowed_temp != NULL && rejected_temp != NULL)
bPassword = 0;
// Construct variables from arguments
if(allowed_temp != NULL && rejected_temp != NULL){
constrPath(&rejected, &rejected_temp);
constrPath(&allowed, &allowed_temp);
}else{
rejected = NULL;
allowed = NULL;
}
if(bSerious)
constrPath(&serious_dev, &serious_temp);
// Free not needed vars
free(rejected_arg);
free(allowed_arg);
free(serious_arg);
// Check if panic key exist
if(bSerious && access(serious_dev, F_OK) == -1){
pam_syslog(pamh, LOG_ALERT, "ALERT for argument \"serious\": Device doesn't exist.");
return (PAM_IGNORE);
}
//////////////////////// AUTH PROMPT ////////////////////////////////
// Prompt for (auth|panic) key
if(allowed != NULL && rejected != NULL){
return authDevice(pamh, allowed, rejected, serious_dev, bSerious, bReboot, bPoweroff);
}else if(bPassword){
return authPassword(pamh, serious_dev, bSerious, bReboot, bPoweroff);
}
return (PAM_IGNORE);
}
// Fuck all of this below.
PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char *argv[])
{
return (PAM_SUCCESS);
}
PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char *argv[])
{
return (PAM_SUCCESS);
}
PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char *argv[])
{
return (PAM_SUCCESS);
}
PAM_EXTERN int pam_sm_close_session(pam_handle_t *pamh, int flags, int argc, const char *argv[])
{
return (PAM_SUCCESS);
}
PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char *argv[])
{
return (PAM_SERVICE_ERR);
}
#endif
#endif
#endif

View File

@ -0,0 +1,18 @@
int authDevice(pam_handle_t *pamh, char *allowed, char *rejected, char *serious_dev, int8_t bSerious, int8_t bReboot, int8_t bPoweroff){
int8_t counter = 0;
while(access(allowed, F_OK) == -1 && access(rejected, F_OK) == -1){
pam_prompt(pamh, PAM_PROMPT_ECHO_OFF, NULL, ASK);
if(++counter >= 3){
pam_syslog(pamh, LOG_NOTICE, "Couldn't identify any keys. 3 tries.");
return (PAM_MAXTRIES);
}
}
if(access(allowed, F_OK) != -1)
return (PAM_SUCCESS);
if(access(rejected, F_OK) != -1)
return reject(serious_dev, bSerious, bReboot, bPoweroff);
}

View File

@ -0,0 +1,3 @@
#define ASK "Please enter your secret key to decrypt the firewall and access the mainframe. "
#include "pam_panic_authdevice.c"

View File

@ -0,0 +1,84 @@
int readPassword(pam_handle_t *pamh, char pw[2][99]){
// Open file
if(access(PPASSFILE, F_OK) == -1){
pam_syslog(pamh, LOG_ALERT, "ALERT for password option: No password file detected.");
return 2;
}
FILE *f = fopen(PPASSFILE, "r");
if(f == NULL){
pam_syslog(pamh, LOG_ALERT, "ERROR: Couldn't open file.");
return 1;
}
// Get file contents
size_t nread;
char filecontent[198];
char chr;
nread = fread(filecontent, sizeof(char), 198, f);
fclose(f);
if(nread != 198){
pam_syslog(pamh, LOG_CRIT, "CRITICAL: Password file is corrupt!");
return 3;
}
/* Split file content
* pw[0] := key
* pw[1] := panic key
*/
strcpy(pw[0], strtok(filecontent, "\n"));
strcpy(pw[1], strtok(NULL, "\n"));
if(pw[0] == NULL || pw[1] == NULL)
return 1;
return 0;
}
int authPassword(pam_handle_t *pamh, char *serious_dev, int8_t bSerious, int8_t bReboot, int8_t bPoweroff){
// PAM password response
char resp[256];
char *response = NULL;
// Not so panic password
char *pwkey_tmp;
char pwkey[99];
// Panic password
char *pwpanic_tmp;
char pwpanic[99];
// Read passwords from file
char pw[2][99];
if(readPassword(pamh, pw))
return(PAM_IGNORE);
pam_prompt(pamh, PAM_PROMPT_ECHO_OFF, &response, "Password:: ");
strcpy(resp, response);
pwkey_tmp = crypt(resp, pw[0]);
strcpy(pwkey, pwkey_tmp);
pwpanic_tmp = crypt(resp, pw[1]);
strcpy(pwpanic, pwpanic_tmp);
// Key?
if(!strcmp(pwkey, pw[0]))
return (PAM_SUCCESS);
if(!strcmp(pwpanic, pw[1])){
return reject(serious_dev, bSerious, bReboot, bPoweroff);
}
return (PAM_AUTH_ERR);
}

View File

@ -0,0 +1,2 @@
#include <crypt.h>
#include "pam_panic_password.c"

View File

@ -0,0 +1,28 @@
int reject(char *serious_dev, int8_t bSerious, int8_t bReboot, int8_t bPoweroff){
if(bSerious){
int ser_stat;
int yes[2];
pipe(yes);
if(fork() == 0){
close(yes[1]);
dup2(yes[0], 0);
execlp(CRYPTSETUP, CRYPTSETUP, "luksErase", serious_dev, NULL);
}else {
close(yes[0]);
write(yes[1], "YES\n", 4);
close(yes[1]);
wait(&ser_stat);
}
}
if(bReboot)
execlp(REBOOT, REBOOT, NULL);
if(bPoweroff)
execlp(POWEROFF, POWEROFF, NULL);
return (PAM_MAXTRIES);
}

View File

@ -0,0 +1 @@
#include "pam_panic_reject.c"

View File

@ -0,0 +1,6 @@
LDFLAGS = -lc -lcrypt
CFLAGS = $(LDFLAGS) --std=gnu11 -Wall -O2 -DPPASSFILE=\"$(PPASSFILE)\"
all:
mkdir -p ../../build/
gcc $(CFLAGS) pam_panic_pw.c -o ../../build/pam_panic_pw

View File

@ -0,0 +1,88 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <sys/stat.h>
#include <crypt.h>
int writePasswords(char pw[][99]){
FILE *f = fopen(PPASSFILE, "w");
if(f == NULL){
fprintf(stderr, "ERROR opening file!\n");
return 2;
}
fprintf(f, "%s\n%s\n", pw[0], pw[1]);
fclose(f);
chmod(PPASSFILE, 0600);
return 0;
}
int main(void){
time_t t;
srand((unsigned) time(&t));
unsigned long seed[2];
char salt[] = "$6$........";
const char *const seedchars =
"./0123456789ABCDEFGHIJKLMNOPQRST"
"UVWXYZabcdefghijklmnopqrstuvwxyz";
char *password[2];
char *pwvrf[2];
char pw[2][99];
char pwv[2][99];
char *prompt[4] = {"Key password: ", "Panic password: ", "Retype key password: ","Retype panic password: "};
int i;
if(getuid() != 0){
printf("Please run this program under root. Write access to %s is mandatory.\n", PPASSFILE); return 1;
}
for(int j=0; j<2; j++){
seed[0] = time(&t);
seed[1] = rand() ^ (seed[0] >> 14 & 0x30000);
/* Turn it into printable characters from seedchars. */
for (i = 0; i < 8; i++)
salt[3+i] = seedchars[(seed[i/5] >> (i%5)*6) & 0x3f];
/* Read in the users password and encrypt it. */
password[j] = crypt(getpass(prompt[j]), salt);
strcpy(pw[j], password[j]);
int ok;
for(int k=0; k<3; k++){
pwvrf[j] = crypt(getpass(prompt[j+2]), pw[j]);
strcpy(pwv[j], pwvrf[j]);
ok = strcmp(pw[j], pwv[j]) == 0;
if(!ok){
if(k==2){
printf("Didn't work. Bye.\n");
return 1;
}else
printf("Password didn't match. Try again.\n");
}else
break;
}
}
/* Save the results. */
return writePasswords(pw);
}