Date: Sun, 13 May 2012 14:39:41 +0000 From: gpf@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r235719 - in soc2012/gpf/pefs_kmod: . lib lib/libpam lib/libpam/modules lib/libpam/modules/pam_pefs sbin sbin/pefs sys sys/crypto sys/crypto/hmac sys/crypto/rijndael sys/crypto/sha2 ... Message-ID: <20120513143941.B5913106566B@hub.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: gpf Date: Sun May 13 14:39:41 2012 New Revision: 235719 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=235719 Log: merging pefs.kmod to my branch Added: soc2012/gpf/pefs_kmod/ soc2012/gpf/pefs_kmod/Makefile soc2012/gpf/pefs_kmod/README soc2012/gpf/pefs_kmod/lib/ soc2012/gpf/pefs_kmod/lib/libpam/ soc2012/gpf/pefs_kmod/lib/libpam/modules/ soc2012/gpf/pefs_kmod/lib/libpam/modules/Makefile.inc soc2012/gpf/pefs_kmod/lib/libpam/modules/pam_pefs/ soc2012/gpf/pefs_kmod/lib/libpam/modules/pam_pefs/Makefile soc2012/gpf/pefs_kmod/lib/libpam/modules/pam_pefs/pam_pefs.8 soc2012/gpf/pefs_kmod/lib/libpam/modules/pam_pefs/pam_pefs.c soc2012/gpf/pefs_kmod/sbin/ soc2012/gpf/pefs_kmod/sbin/pefs/ soc2012/gpf/pefs_kmod/sbin/pefs/Makefile soc2012/gpf/pefs_kmod/sbin/pefs/pefs.8 soc2012/gpf/pefs_kmod/sbin/pefs/pefs_ctl.c soc2012/gpf/pefs_kmod/sbin/pefs/pefs_ctl.h soc2012/gpf/pefs_kmod/sbin/pefs/pefs_key.c soc2012/gpf/pefs_kmod/sbin/pefs/pefs_keychain.c soc2012/gpf/pefs_kmod/sbin/pefs/pefs_keychain.h soc2012/gpf/pefs_kmod/sbin/pefs/pefs_subr.c soc2012/gpf/pefs_kmod/sys/ soc2012/gpf/pefs_kmod/sys/crypto/ soc2012/gpf/pefs_kmod/sys/crypto/hmac/ soc2012/gpf/pefs_kmod/sys/crypto/hmac/hmac_sha512.c soc2012/gpf/pefs_kmod/sys/crypto/hmac/hmac_sha512.h soc2012/gpf/pefs_kmod/sys/crypto/rijndael/ soc2012/gpf/pefs_kmod/sys/crypto/rijndael/rijndael-alg-fst.c soc2012/gpf/pefs_kmod/sys/crypto/rijndael/rijndael-api-fst.c soc2012/gpf/pefs_kmod/sys/crypto/rijndael/rijndael-api-fst.h soc2012/gpf/pefs_kmod/sys/crypto/rijndael/rijndael-api.c soc2012/gpf/pefs_kmod/sys/crypto/rijndael/rijndael.h soc2012/gpf/pefs_kmod/sys/crypto/rijndael/rijndael_local.h soc2012/gpf/pefs_kmod/sys/crypto/sha2/ soc2012/gpf/pefs_kmod/sys/crypto/sha2/sha2.c soc2012/gpf/pefs_kmod/sys/crypto/sha2/sha2.h soc2012/gpf/pefs_kmod/sys/fs/ soc2012/gpf/pefs_kmod/sys/fs/pefs/ soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs.h soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs_aesni.c soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs_aesni.h soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs_crypto.c soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs_crypto.h soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs_dircache.c soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs_dircache.h soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs_subr.c soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs_vfsops.c soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs_vnops.c soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs_xbase64.c soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs_xts.c soc2012/gpf/pefs_kmod/sys/fs/pefs/vmac.c soc2012/gpf/pefs_kmod/sys/fs/pefs/vmac.h soc2012/gpf/pefs_kmod/sys/geom/ soc2012/gpf/pefs_kmod/sys/geom/eli/ soc2012/gpf/pefs_kmod/sys/geom/eli/pkcs5v2.c soc2012/gpf/pefs_kmod/sys/geom/eli/pkcs5v2.h soc2012/gpf/pefs_kmod/sys/modules/ soc2012/gpf/pefs_kmod/sys/modules/pefs/ soc2012/gpf/pefs_kmod/sys/modules/pefs/Makefile Added: soc2012/gpf/pefs_kmod/Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ soc2012/gpf/pefs_kmod/Makefile Sun May 13 14:39:41 2012 (r235719) @@ -0,0 +1,7 @@ +SUBDIR= sys/modules/pefs \ + sbin/pefs + +# Should be built from sources tree +SUBDIR+= lib/libpam/modules/pam_pefs + +.include <bsd.subdir.mk> Added: soc2012/gpf/pefs_kmod/README ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ soc2012/gpf/pefs_kmod/README Sun May 13 14:39:41 2012 (r235719) @@ -0,0 +1,32 @@ +PEFS is a kernel level stacked cryptographic filesystem for FreeBSD. + +The following is a list of its most important features: + +* Kernel level file system, no user level daemons needed. Transparently runs + on top of existing file systems. + +* Random per file tweak value used for encryption, which guaranties different + cipher texts for the same encrypted files. + +* Saves metadata only in encrypted file name, but not in file itself. + +* Supports arbitrary number of keys per file system, default directory key, + mixing files encrypted with different keys in same directory. + +* Allows defining key chains, can be used to add/delete several keys by + specifying only master key. + +* Uses modern cryptographic algorithms: AES and Camellia in XTS mode, + PKCS#5v2 and HKDF for key generation. + +FreeBSD wiki page: http://wiki.freebsd.org/PEFS +blog: http://glebkurtsou.blogspot.com/search/label/pefs + + +Installation instructions: + +# git clone git://github.com/glk/pefs.git pefs +# cd pefs +# make obj all +# make install +# make clean Added: soc2012/gpf/pefs_kmod/lib/libpam/modules/Makefile.inc ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ soc2012/gpf/pefs_kmod/lib/libpam/modules/Makefile.inc Sun May 13 14:39:41 2012 (r235719) @@ -0,0 +1,4 @@ +# Include Makefiles from $SRCDIR + +.include </usr/src/lib/libpam/modules/Makefile.inc> + Added: soc2012/gpf/pefs_kmod/lib/libpam/modules/pam_pefs/Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ soc2012/gpf/pefs_kmod/lib/libpam/modules/pam_pefs/Makefile Sun May 13 14:39:41 2012 (r235719) @@ -0,0 +1,24 @@ +# PAM module for pefs +# $FreeBSD$ + +SYS= ${.CURDIR}/../../../../sys +PEFSDIR= ${.CURDIR}/../../../../sbin/pefs + +LIB= pam_pefs +MAN= pam_pefs.8 +SRCS= pam_pefs.c +SRCS+= pefs_key.c pefs_keychain.c pefs_subr.c +SRCS+= hmac_sha512.c pkcs5v2.c sha2.c +SRCS+= rijndael-api.c rijndael-api-fst.c rijndael-alg-fst.c + +CFLAGS+= -I${PEFSDIR} +CFLAGS+= -I${SYS} + +DPADD= ${LIBUTIL} +LDADD= -lutil + +.include <bsd.lib.mk> + +.PATH: ${PEFSDIR} +.PATH: ${SYS}/geom/eli +.PATH: ${SYS}/crypto/hmac ${SYS}/crypto/sha2 ${SYS}/crypto/rijndael Added: soc2012/gpf/pefs_kmod/lib/libpam/modules/pam_pefs/pam_pefs.8 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ soc2012/gpf/pefs_kmod/lib/libpam/modules/pam_pefs/pam_pefs.8 Sun May 13 14:39:41 2012 (r235719) @@ -0,0 +1,147 @@ +.\" Copyright (c) 2001 Mark R V Murray +.\" Copyright (c) 2001-2003 Networks Associates Technology, Inc. +.\" Copyright (c) 2009 Gleb Kurtsou +.\" All rights reserved. +.\" +.\" This software was developed for the FreeBSD Project by ThinkSec AS and +.\" NAI Labs, the Security Research Division of Network Associates, Inc. +.\" under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the +.\" DARPA CHATS research program. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. The name of the author may not be used to endorse or promote +.\" products derived from this software without specific prior written +.\" permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd December 1, 2009 +.Dt PAM_PEFS 8 +.Os +.Sh NAME +.Nm pam_pefs +.Nd pefs PAM module +.Sh SYNOPSIS +.Op Ar service-name +.Ar module-type +.Ar control-flag +.Pa pam_pefs +.Op Ar options +.Sh DESCRIPTION +The +pefs +authentication service module for PAM, +.Nm +provides functionality for two PAM categories: +authentication +and session management. +In terms of the +.Ar module-type +parameter, they are the +.Dq Li auth +and +.Dq Li session +features. +.Pp +Module expects pefs file system to be mounted on user home directory +and fails otherwise. +.Ss Pefs Authentication Module +The +pefs +authentication component +provides a function to verify the identity of a user +.Pq Fn pam_sm_authenticate , +by prompting the user for a passphrase and verifying that it exists in +pefs key chain database. +.Pp +The following options may be passed to the authentication module: +.Bl -tag -width ".Cm use_first_pass" +.It Cm use_first_pass +If the authentication module +is not the first in the stack, +and a previous module +obtained the user's password, +that password is used +to authenticate the user. +If this fails, +the authentication module returns failure +without prompting the user for a password. +This option has no effect +if the authentication module +is the first in the stack, +or if no previous modules +obtained the user's password. +.It Cm try_first_pass +This option is similar to the +.Cm use_first_pass +option, +except that if the previously obtained password fails, +the user is prompted for another password. +.It Cm ignore_missing +Accept any passphrase provided by the user. +This option is used not to authenticate user, but to preserve keys that +should be added to pefs file system by session management module. +Option is incompatible with +.Cm try_first_pass +option and should be used with +.Cm use_first_pass +option. +.It Cm delkeys +Remove keys at the end of last session. +Module tracks the number of concurrent sessions, removing all keys from +file system when session count reaches zero. +.El +.Ss Pefs Session Management Module +The +pefs +session management component +provides functions to initiate +.Pq Fn pam_sm_open_session +and terminate +.Pq Fn pam_sm_close_session +sessions. +The +.Fn pam_sm_open_session +function adds key or key chain decrypted during the authentication phase +to the pefs file system mounted on user home directory. +.Sh FILES +.Bl -tag -width ".Pa $HOME/.pefs.conf" -compact +.It Pa $HOME/.pefs.conf +pefs configuration file +.It Pa $HOME/.pefs.db +pefs key chain database file +.El +.Sh SEE ALSO +.Xr pam.conf 5 , +.Xr pam 8 +.Xr pefs 8 +.Sh AUTHORS +The +.Nm +module was written by +.An -nosplit +.An "Gleb Kurtsou" Aq gk@FreeBSD.org . +.Sh BUGS +.Fn pam_sm_close_session +function +doesn't delete keys added during by +.Fn pam_sm_open_session . Added: soc2012/gpf/pefs_kmod/lib/libpam/modules/pam_pefs/pam_pefs.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ soc2012/gpf/pefs_kmod/lib/libpam/modules/pam_pefs/pam_pefs.c Sun May 13 14:39:41 2012 (r235719) @@ -0,0 +1,526 @@ +/*- + * Copyright (c) 2003 Networks Associates Technology, Inc. + * Copyright (c) 2009 Gleb Kurtsou + * All rights reserved. + * + * This software was developed for the FreeBSD Project by ThinkSec AS and + * NAI Labs, the Security Research Division of Network Associates, Inc. + * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the + * DARPA CHATS research program. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/ioctl.h> +#include <sys/wait.h> +#include <sys/stat.h> + +#include <errno.h> +#include <fcntl.h> +#include <libgen.h> +#include <libutil.h> +#include <paths.h> +#include <pwd.h> +#include <signal.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <unistd.h> + +#define PAM_SM_AUTH +#define PAM_SM_SESSION + +#include <security/pam_appl.h> +#include <security/pam_modules.h> +#include <security/pam_mod_misc.h> +#include <security/openpam.h> + +#include <fs/pefs/pefs.h> + +#include "pefs_ctl.h" +#include "pefs_keychain.h" + +#define PEFS_OPT_IGNORE_MISSING "ignore_missing" +#define PEFS_OPT_DELKEYS "delkeys" + +#define PAM_PEFS_KEYS "pam_pefs_keys" + +#define PEFS_SESSION_DIR "/var/run/pefs" +#define PEFS_SESSION_DIR_MODE 0700 +#define PEFS_SESSION_FILE_MODE 0600 +#define PEFS_SESSION_FILE_FLAGS \ + (O_RDWR | O_NONBLOCK | O_CREAT | O_EXLOCK) + +static int pam_pefs_debug; + +void +pefs_warn(const char *fmt, ...) +{ + static const char *label = "pam_pefs: "; + char buf[BUFSIZ]; + va_list ap; + + if (pam_pefs_debug == 0) + return; + + va_start(ap, fmt); + if (strlen(fmt) + sizeof(label) >= sizeof(buf)) { + vsyslog(LOG_DEBUG, fmt, ap); + } else { + strlcpy(buf, label, sizeof(buf)); + strlcat(buf, fmt, sizeof(buf)); + vsyslog(LOG_DEBUG, buf, ap); + } + va_end(ap); +} + +static int +flopen_retry(const char *filename) +{ + int fd, try; + + for (try = 1; try <= 1024; try *= 2) { + fd = flopen(filename, PEFS_SESSION_FILE_FLAGS, + PEFS_SESSION_FILE_MODE); + if (fd != -1) + return (fd); + else if (errno != EWOULDBLOCK) + return (-1); + // Exponential back-off up to 1 second + usleep(try * 1000000 / 1024); + } + errno = ETIMEDOUT; + return (-1); +} + +static int +pefs_session_count_incr(const char *user, bool incr) +{ + struct stat sb; + struct timespec tp_uptime, tp_now; + ssize_t offset; + int fd, total = 0; + char filename[MAXPATHLEN], buf[16]; + const char *errstr; + + snprintf(filename, sizeof(filename), "%s/%s", PEFS_SESSION_DIR, user); + + if (lstat(PEFS_SESSION_DIR, &sb) == -1) { + if (errno != ENOENT) { + pefs_warn("unable to access session directory %s: %s", + PEFS_SESSION_DIR, strerror(errno)); + return (-1); + } + if (mkdir(PEFS_SESSION_DIR, PEFS_SESSION_DIR_MODE) == -1) { + pefs_warn("unable to create session directory %s: %s", + PEFS_SESSION_DIR, strerror(errno)); + return (-1); + } + } else if (!S_ISDIR(sb.st_mode)) { + pefs_warn("%s is not a directory", PEFS_SESSION_DIR); + return (-1); + } + + if ((fd = flopen_retry(filename)) == -1) { + pefs_warn("unable to create session counter file %s: %s", + filename, strerror(errno)); + return (-1); + } + + if ((offset = pread(fd, buf, sizeof(buf) - 1, 0)) == -1) { + pefs_warn("unable to read from the session counter file %s: %s", + filename, strerror(errno)); + close(fd); + return (-1); + } + buf[offset] = '\0'; + if (offset != 0) { + total = strtonum(buf, 0, INT_MAX, &errstr); + if (errstr != NULL) + pefs_warn("corrupted session counter file: %s: %s", + filename, errstr); + } + + /* + * Determine if this is the first increment of the session file. + * + * It is considered the first increment if the session file has not + * been modified since the last boot time. + */ + if (incr && total > 0) { + if (fstat(fd, &sb) == -1) { + pefs_warn("unable to access session counter file %s: %s", + filename, strerror(errno)); + close(fd); + return (-1); + } + /* + * Check is messy and will fail if wall clock isn't monotonical + * (e.g. because of ntp, DST, leap seconds) + */ + clock_gettime(CLOCK_REALTIME_FAST, &tp_now); + clock_gettime(CLOCK_UPTIME_FAST, &tp_uptime); + if (sb.st_mtime < tp_now.tv_sec - tp_uptime.tv_sec) { + pefs_warn("stale session counter file: %s", + filename); + total = 0; + } + } + + lseek(fd, 0L, SEEK_SET); + ftruncate(fd, 0L); + + total += incr ? 1 : -1; + if (total < 0) { + pefs_warn("corrupted session counter file: %s", + filename); + total = 0; + } else + pefs_warn("%s: session count %d", user, total); + + buf[0] = '\0'; + snprintf(buf, sizeof(buf), "%d", total); + pwrite(fd, buf, strlen(buf), 0); + close(fd); + + return (total); +} + +static int +pam_pefs_checkfs(const char *homedir) +{ + char fsroot[MAXPATHLEN]; + int error; + + error = pefs_getfsroot(homedir, 0, fsroot, sizeof(fsroot)); + if (error != 0) { + pefs_warn("file system is not mounted: %s", homedir); + return (PAM_USER_UNKNOWN); + } if (strcmp(fsroot, homedir) != 0) { + pefs_warn("file system is not mounted on home dir: %s", fsroot); + return (PAM_USER_UNKNOWN); + } + + return (PAM_SUCCESS); +} + +/* + * Perform key lookup in ~/.pefs; + * returns PAM_AUTH_ERR if and only if key wasn't found in database. + */ +static int +pam_pefs_getkeys(struct pefs_keychain_head *kch, + const char *homedir, const char *passphrase, int chainflags) +{ + struct pefs_xkey k; + struct pefs_keyparam kp; + int error; + + pefs_keyparam_create(&kp); + pefs_keyparam_init(&kp, homedir); + + error = pefs_key_generate(&k, passphrase, &kp); + if (error != 0) + return (PAM_SERVICE_ERR); + + error = pefs_keychain_get(kch, homedir, chainflags, &k); + bzero(&k, sizeof(k)); + if (error != 0) + return (error == PEFS_ERR_NOENT ? PAM_AUTH_ERR : + PAM_SERVICE_ERR); + + return (PAM_SUCCESS); +} + +static int +pam_pefs_addkeys(const char *homedir, struct pefs_keychain_head *kch) +{ + struct pefs_keychain *kc; + int fd; + + fd = open(homedir, O_RDONLY); + if (fd == -1) { + pefs_warn("cannot open homedir %s: %s", + homedir, strerror(errno)); + return (PAM_USER_UNKNOWN); + } + + TAILQ_FOREACH(kc, kch, kc_entry) { + if (ioctl(fd, PEFS_ADDKEY, &kc->kc_key) == -1) { + pefs_warn("cannot add key: %s: %s", + homedir, strerror(errno)); + break; + } + } + close(fd); + + return (PAM_SUCCESS); +} + +static int +pam_pefs_delkeys(const char *homedir) +{ + struct pefs_xkey k; + int fd; + + fd = open(homedir, O_RDONLY); + if (fd == -1) { + pefs_warn("cannot open homedir %s: %s", + homedir, strerror(errno)); + return (PAM_USER_UNKNOWN); + } + + bzero(&k, sizeof(k)); + while (1) { + if (ioctl(fd, PEFS_GETKEY, &k) == -1) + break; + + if (ioctl(fd, PEFS_DELKEY, &k) == -1) { + pefs_warn("cannot del key: %s: %s", + homedir, strerror(errno)); + k.pxk_index++; + } + } + close(fd); + + return (PAM_SUCCESS); +} + +static void +pam_pefs_freekeys(pam_handle_t *pamh __unused, void *data, int pam_err __unused) +{ + struct pefs_keychain_head *kch = data; + + pefs_keychain_free(kch); + free(kch); +} + +PAM_EXTERN int +pam_sm_authenticate(pam_handle_t *pamh, int flags __unused, + int argc __unused, const char *argv[] __unused) +{ + struct pefs_keychain_head *kch; + struct passwd *pwd; + const char *passphrase, *user; + const void *item; + int pam_err, canretry, chainflags; + + /* Get user name and home directory */ + pam_err = pam_get_user(pamh, &user, NULL); + if (pam_err != PAM_SUCCESS) + return (pam_err); + pwd = getpwnam(user); + if (pwd == NULL) + return (PAM_USER_UNKNOWN); + if (pwd->pw_dir == NULL) + return (PAM_AUTH_ERR); + + pam_pefs_debug = (openpam_get_option(pamh, PAM_OPT_DEBUG) != NULL); + + chainflags = PEFS_KEYCHAIN_USE; + if (openpam_get_option(pamh, PEFS_OPT_IGNORE_MISSING) != NULL) + chainflags = PEFS_KEYCHAIN_IGNORE_MISSING; + + canretry = (pam_get_item(pamh, PAM_AUTHTOK, &item) == PAM_SUCCESS && + item != NULL && chainflags != PEFS_KEYCHAIN_IGNORE_MISSING); + + pam_err = openpam_borrow_cred(pamh, pwd); + if (pam_err != PAM_SUCCESS) + return (pam_err); + + /* + * Check to see if the passwd db is available, avoids asking for + * password if we cannot even validate it. + */ + pam_err = pam_pefs_checkfs(pwd->pw_dir); + openpam_restore_cred(pamh); + if (pam_err != PAM_SUCCESS) + return (pam_err); + + +retry: + /* Get passphrase */ + pam_err = pam_get_authtok(pamh, PAM_AUTHTOK, + &passphrase, NULL); + if (pam_err != PAM_SUCCESS) + return (pam_err); + + if (*passphrase != '\0') { + kch = calloc(1, sizeof(*kch)); + if (kch == NULL) + return (PAM_SYSTEM_ERR); + + /* Switch to user credentials */ + pam_err = openpam_borrow_cred(pamh, pwd); + if (pam_err != PAM_SUCCESS) + return (pam_err); + + pam_err = pam_pefs_getkeys(kch, pwd->pw_dir, passphrase, + chainflags); + if (pam_err == PAM_SUCCESS) + pam_set_data(pamh, PAM_PEFS_KEYS, kch, + pam_pefs_freekeys); + else + free(kch); + + /* Switch back to arbitrator credentials */ + openpam_restore_cred(pamh); + } else + pam_err = PAM_AUTH_ERR; + + /* + * If we tried an old token and didn't get anything, and + * try_first_pass was specified, try again after prompting the + * user for a new passphrase. + */ + if (pam_err == PAM_AUTH_ERR && canretry != 0 && + openpam_get_option(pamh, "try_first_pass") != NULL) { + pam_set_item(pamh, PAM_AUTHTOK, NULL); + canretry = 0; + goto retry; + } + + return (pam_err); +} + +PAM_EXTERN int +pam_sm_setcred(pam_handle_t *pamh __unused, int flags __unused, + int argc __unused, const char *argv[] __unused) +{ + + return (PAM_SUCCESS); +} + +PAM_EXTERN int +pam_sm_open_session(pam_handle_t *pamh, int flags __unused, + int argc __unused, const char *argv[] __unused) +{ + struct pefs_keychain_head *kch = NULL; + struct passwd *pwd; + const char *user; + int pam_err, opt_delkeys; + + pam_err = pam_get_user(pamh, &user, NULL); + if (pam_err != PAM_SUCCESS) + return (pam_err); + pwd = getpwnam(user); + if (pwd == NULL) + return (PAM_USER_UNKNOWN); + if (pwd->pw_dir == NULL) + return (PAM_SYSTEM_ERR); + + pam_pefs_debug = (openpam_get_option(pamh, PAM_OPT_DEBUG) != NULL); + opt_delkeys = (openpam_get_option(pamh, PEFS_OPT_DELKEYS) != NULL); + + pam_err = pam_get_data(pamh, PAM_PEFS_KEYS, + (const void **)(void *)&kch); + if (pam_err != PAM_SUCCESS || kch == NULL || TAILQ_EMPTY(kch)) { + pam_err = PAM_SUCCESS; + opt_delkeys = 0; + goto out; + } + + /* Switch to user credentials */ + pam_err = openpam_borrow_cred(pamh, pwd); + if (pam_err != PAM_SUCCESS) + goto out; + + pam_err = pam_pefs_checkfs(pwd->pw_dir); + if (pam_err != PAM_SUCCESS) { + openpam_restore_cred(pamh); + pam_err = PAM_SUCCESS; + opt_delkeys = 0; + goto out; + } + + pam_err = pam_pefs_addkeys(pwd->pw_dir, kch); + + /* Switch back to arbitrator credentials */ + openpam_restore_cred(pamh); + +out: + /* Remove keys from memory */ + if (kch != NULL) + pefs_keychain_free(kch); + + /* Increment login count */ + if (pam_err == PAM_SUCCESS && opt_delkeys) + pefs_session_count_incr(user, true); + + return (pam_err); +} + +PAM_EXTERN int +pam_sm_close_session(pam_handle_t *pamh, int flags __unused, + int argc __unused, const char *argv[] __unused) +{ + struct passwd *pwd; + const char *user; + int pam_err, opt_delkeys; + + pam_err = pam_get_user(pamh, &user, NULL); + if (pam_err != PAM_SUCCESS) + return (pam_err); + + pwd = getpwnam(user); + if (pwd == NULL) + return (PAM_USER_UNKNOWN); + if (pwd->pw_dir == NULL) + return (PAM_SYSTEM_ERR); + + pam_pefs_debug = (openpam_get_option(pamh, PAM_OPT_DEBUG) != NULL); + opt_delkeys = (openpam_get_option(pamh, PEFS_OPT_DELKEYS) != NULL); + if (!opt_delkeys) + return PAM_SUCCESS; + + pam_err = openpam_borrow_cred(pamh, pwd); + if (pam_err != PAM_SUCCESS) + return (pam_err); + pam_err = pam_pefs_checkfs(pwd->pw_dir); + openpam_restore_cred(pamh); + if (pam_err != PAM_SUCCESS) + return (PAM_SUCCESS); + + /* Decrease login count and remove keys if at zero */ + pam_err = PAM_SUCCESS; + if (pefs_session_count_incr(user, false) == 0) { + pam_err = openpam_borrow_cred(pamh, pwd); + if (pam_err != PAM_SUCCESS) + return (pam_err); + pam_err = pam_pefs_delkeys(pwd->pw_dir); + openpam_restore_cred(pamh); + } + + return (pam_err); +} + +PAM_MODULE_ENTRY("pam_pefs"); Added: soc2012/gpf/pefs_kmod/sbin/pefs/Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ soc2012/gpf/pefs_kmod/sbin/pefs/Makefile Sun May 13 14:39:41 2012 (r235719) @@ -0,0 +1,24 @@ +# $FreeBSD$ + +SYS= ${.CURDIR}/../../sys +.PATH: ${SYS}/geom/eli +.PATH: ${SYS}/crypto/hmac ${SYS}/crypto/rijndael ${SYS}/crypto/sha2 + +PROG= pefs +SRCS= pefs_ctl.c pefs_key.c pefs_keychain.c pefs_subr.c +SRCS+= hmac_sha512.c sha2.c +SRCS+= rijndael-api.c rijndael-api-fst.c rijndael-alg-fst.c +SRCS+= pkcs5v2.c + +MAN= pefs.8 + +CFLAGS+=-I${SYS} +WARNS?= 6 +DEBUG_FLAGS+= -g + +DPADD= ${LIBUTIL} +LDADD= -lutil + +BINDIR?= /sbin + +.include <bsd.prog.mk> Added: soc2012/gpf/pefs_kmod/sbin/pefs/pefs.8 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ soc2012/gpf/pefs_kmod/sbin/pefs/pefs.8 Sun May 13 14:39:41 2012 (r235719) @@ -0,0 +1,441 @@ +.\" Copyright (c) 2005-2008 Pawel Jakub Dawidek <pjd@FreeBSD.org> +.\" Copyright (c) 2009 Gleb Kurtsou +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd December 1, 2009 +.Dt PEFS 8 +.Os +.Sh NAME +.Nm pefs +.Nd configure pefs file systems +.Sh SYNOPSIS +.Nm +.Cm mount +.Op Fl o Ar options +.Op Ar from filesystem +.Nm +.Cm unmount +.Op Fl fv +.Ar filesystem +.Pp +.Nm +.Cm addkey +.Op Fl cCpv +.Op Fl a Ar alg +.Op Fl i Ar iterations +.Op Fl k Ar keyfile +.Ar filesystem +.Nm +.Cm delkey +.Op Fl cCpv +.Op Fl i Ar iterations +.Op Fl k Ar keyfile +.Ar filesystem +.Nm +.Cm flushkeys +.Ar filesystem +.Nm +.Cm getkey +.Op Fl t +.Ar file +.Nm +.Cm setkey +.Op Fl cCpvx +.Op Fl a Ar alg +.Op Fl i Ar iterations +.Op Fl k Ar keyfile +.Ar directory +.Nm +.Cm showkeys +.Op Fl t +.Ar filesystem +.Pp +.Nm +.Cm addchain +.Op Fl fpPvZ +.Op Fl a Ar alg +.Op Fl i Ar iterations +.Op Fl k Ar keyfile +.Op Fl A Ar alg +.Op Fl I Ar iterations +.Op Fl K Ar keyfile +.Ar filesystem +.Nm +.Cm delchain +.Op Fl fFpv +.Op Fl i Ar iterations +.Op Fl k Ar keyfile +.Ar filesystem +.Nm +.Cm randomchain +.Op Fl fv +.Op Fl i Ar iterations +.Op Fl k Ar keyfile +.Ar filesystem +.Nm +.Cm showchains +.Op Fl fp +.Op Fl i Ar iterations +.Op Fl k Ar keyfile +.Ar filesystem +.Pp +.Nm +.Cm showalgs +.Sh DESCRIPTION +The +.Nm +utility is the user interface for configuring stacked cryptographic file system. +.Pp +The following is a list of the most important file system features: +.Bl -bullet -offset indent -compact +.It +Kernel level file system, no user level daemons needed. +Transparently runs on top of existing file systems. +.It +Random per file tweak value used for encryption, which guaranties different +cipher texts for the same encrypted files. +.It +Saves metadata only in encrypted file name, but not in file itself. +.It +Supports arbitrary number of keys per file system, default directory key, +mixing files encrypted with different keys in same directory. +.It +Allows defining key chains, can be used to add/delete several keys by +specifying only master key. +.It +Uses modern cryptographic algorithms: AES and Camellia in XTS mode, +PKCS#5v2 and HKDF for key generation. +.El +.Pp +First argument of +.Nm +utility indicates the command to be performed (see the +.Sx COMMAND OPTIONS +section for information on options): +.Bl -tag -width indent +.It Cm mount +Mount file system. +Encryption keys should be specified separately after mounting the file system. +If no agrumnt specified prints all mounted +.Nm +file systems. +See +.Xr mount 8 +for more information. +.It Cm unmount Ar filesystem +Unmount +.Ar filesystem . +.Fl f +and +.Fl v +options can be specified to force unmount or enable verbose mode respectively. +See +.Xr umount 8 +for more information. +.It Cm addkey Ar filesystem +Add key to the +.Ar filesystem +.It Cm delkey Ar filesystem +Delete key from +.Ar filesystem . +Command doesn't accept +.Fl a Ar alg +argument because the key fingerprint generated from the key doesn't depend on +encryption algorithm. +.It Cm getkey Ar file +Print fingerprint of the key used by +.Ar file . +.It Cm flushkeys Ar filesystem +Delete all keys from +.Ar filesystem . +After the command all opened files would become unavailable. +.It Cm setkey Ar directory +Change default key for the +.Ar directory . +Default key is used as a new key for files and directories created in the +.Ar directory . +Technically just a rename takes place on underlaying file system. +Keys for entries in the +.Ar directory +are not changed and no data is re-encrypted with new key. +.Fl x +option can be used to add a new key to file system if it isn't found. +.It Cm showkeys Ar filesystem +Print fingerprints if all active keys. +.It Cm addchain Ar filesystem +Add a new key chain element. +Element consists of parent and child keys. +Parent key is defined by +.Fl a , Fl i +and +.Fl p +options and child key by equivalent +.Fl A , Fl I +and +.Fl P +options. +Element consisting only of a parent key can be constructed by specifying +.Fl Z +option. +.Fl f +option disables file system type checks making manipulation on key chains +possible without mounting +.Nm +file system. +See +.Sx KEY CHAINS +section for more information. +.It Cm delchain Ar filesystem +Delete key chain element defined by parent key. *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20120513143941.B5913106566B>