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 ...

gpf at FreeBSD.org gpf at FreeBSD.org
Sun May 13 14:39:44 UTC 2012


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 at 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 at 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 ***


More information about the svn-soc-all mailing list