diff --git a/Makefile b/Makefile index 3949dd0..843d023 100644 --- a/Makefile +++ b/Makefile @@ -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" diff --git a/README.md b/README.md index 238d276..caff42c 100644 --- a/README.md +++ b/README.md @@ -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= reject= reboot serious= account requisite pam_panic.so ``` +### Using the two passwords: +``` +auth requisite pam_panic.so password reboot serious= +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) diff --git a/man/Makefile b/man/Makefile index cbe8307..9d7e2f4 100644 --- a/man/Makefile +++ b/man/Makefile @@ -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 diff --git a/man/de/man1/pam_panic_pw.1 b/man/de/man1/pam_panic_pw.1 new file mode 100644 index 0000000..5917d88 --- /dev/null +++ b/man/de/man1/pam_panic_pw.1 @@ -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 entwickelt\&. diff --git a/man/de/man8/pam_panic.8 b/man/de/man8/pam_panic.8 index 2ec7d5f..fc78ff9 100644 --- a/man/de/man8/pam_panic.8 +++ b/man/de/man8/pam_panic.8 @@ -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= reject= reboot serious= +.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)\&. diff --git a/man/man1/pam_panic_pw.1 b/man/man1/pam_panic_pw.1 new file mode 100644 index 0000000..919df16 --- /dev/null +++ b/man/man1/pam_panic_pw.1 @@ -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 \&. +.PP +This man page has been revised by Jordy Dickinson + diff --git a/man/man8/pam_panic.8 b/man/man8/pam_panic.8 index 27621c7..3b7426e 100644 --- a/man/man8/pam_panic.8 +++ b/man/man8/pam_panic.8 @@ -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= reject= reboot serious= .PP account requisite pam_panic\&.so .RE +Or: +.RS 4 +auth requisite pam_panic.so password reboot serious= +.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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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(®ex, 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= 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 diff --git a/src/pam_panic/Makefile b/src/pam_panic/Makefile new file mode 100644 index 0000000..2e42014 --- /dev/null +++ b/src/pam_panic/Makefile @@ -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 + diff --git a/src/pam_panic/pam_panic.c b/src/pam_panic/pam_panic.c new file mode 100644 index 0000000..69314b2 --- /dev/null +++ b/src/pam_panic/pam_panic.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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(®ex, pattern, 0)){ + pam_syslog(pamh, LOG_CRIT, "ERROR: Problem with regcomp."); + return (PAM_IGNORE); + } + + + // Argument handling + for(int i=0; i= 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); + +} diff --git a/src/pam_panic/pam_panic_authdevice.h b/src/pam_panic/pam_panic_authdevice.h new file mode 100644 index 0000000..8d63852 --- /dev/null +++ b/src/pam_panic/pam_panic_authdevice.h @@ -0,0 +1,3 @@ +#define ASK "Please enter your secret key to decrypt the firewall and access the mainframe. " + +#include "pam_panic_authdevice.c" diff --git a/src/pam_panic/pam_panic_password.c b/src/pam_panic/pam_panic_password.c new file mode 100644 index 0000000..c56aefd --- /dev/null +++ b/src/pam_panic/pam_panic_password.c @@ -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); +} diff --git a/src/pam_panic/pam_panic_password.h b/src/pam_panic/pam_panic_password.h new file mode 100644 index 0000000..1b0a49e --- /dev/null +++ b/src/pam_panic/pam_panic_password.h @@ -0,0 +1,2 @@ +#include +#include "pam_panic_password.c" diff --git a/src/pam_panic/pam_panic_reject.c b/src/pam_panic/pam_panic_reject.c new file mode 100644 index 0000000..6214075 --- /dev/null +++ b/src/pam_panic/pam_panic_reject.c @@ -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); +} + diff --git a/src/pam_panic/pam_panic_reject.h b/src/pam_panic/pam_panic_reject.h new file mode 100644 index 0000000..38fcd25 --- /dev/null +++ b/src/pam_panic/pam_panic_reject.h @@ -0,0 +1 @@ +#include "pam_panic_reject.c" diff --git a/src/pam_panic_pw/Makefile b/src/pam_panic_pw/Makefile new file mode 100644 index 0000000..2d507d5 --- /dev/null +++ b/src/pam_panic_pw/Makefile @@ -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 diff --git a/src/pam_panic_pw/pam_panic_pw.c b/src/pam_panic_pw/pam_panic_pw.c new file mode 100644 index 0000000..9425ad5 --- /dev/null +++ b/src/pam_panic_pw/pam_panic_pw.c @@ -0,0 +1,88 @@ + + + +#include +#include +#include +#include +#include +#include +#include + + +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 user’s 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); +}