[cifs-utils] Update to latest upstream patches

Jeff Layton jlayton at fedoraproject.org
Fri Dec 13 13:29:48 UTC 2013


commit 143499a82cb32ab7cb96c98a89b773334405d55d
Author: Jeff Layton <jlayton at redhat.com>
Date:   Fri Dec 13 08:28:09 2013 -0500

    Update to latest upstream patches
    
    - fix link of libwbclient
    - add pam_cifscreds module and manpage
    
    Signed-off-by: Jeff Layton <jlayton at redhat.com>

 0001-autoconf-fix-link-of-libwbclient.patch        |   36 +
 ...reate-PAM-module-to-insert-credentials-at.patch |  862 ++++++++++++++++++++
 ...ix-up-some-whitespace-typos-and-build-war.patch |  197 +++++
 0004-manpage-add-pam_cifscreds.8-man-page.patch    |  332 ++++++++
 cifs-utils.spec                                    |   21 +-
 5 files changed, 1445 insertions(+), 3 deletions(-)
---
diff --git a/0001-autoconf-fix-link-of-libwbclient.patch b/0001-autoconf-fix-link-of-libwbclient.patch
new file mode 100644
index 0000000..eb0d0d7
--- /dev/null
+++ b/0001-autoconf-fix-link-of-libwbclient.patch
@@ -0,0 +1,36 @@
+From 2152ccc3d61e5248c70360020a0aa279a24f852c Mon Sep 17 00:00:00 2001
+From: Jeff Layton <jlayton at samba.org>
+Date: Sat, 7 Dec 2013 08:54:59 -0500
+Subject: [cifs-utils PATCH] autoconf: fix link of libwbclient
+
+It's currently getting added to $LIBS and being linked into places that
+we don't need it.
+
+Signed-off-by: Jeff Layton <jlayton at samba.org>
+---
+ aclocal/idmap.m4 | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/aclocal/idmap.m4 b/aclocal/idmap.m4
+index c5727f6..3ccdae3 100644
+--- a/aclocal/idmap.m4
++++ b/aclocal/idmap.m4
+@@ -21,6 +21,7 @@ fi
+ 
+ if test $enable_cifsacl != "no" -o $enable_cifsacl != "no"; then
+ 	ac_wbc_save_LDFLAGS="$LDFLAGS"
++	ac_wbc_save_LIBS="$LIBS"
+ 	LDFLAGS="$LDFLAGS $WBCLIENT_LIBS"
+ 	AC_CHECK_LIB(wbclient, wbcSidsToUnixIds, , [
+ 				if test "$enable_cifsidmap" = "yes"; then
+@@ -37,6 +38,7 @@ if test $enable_cifsacl != "no" -o $enable_cifsacl != "no"; then
+ 				fi
+ 			])
+ 	LDFLAGS=$ac_wbc_save_LDFLAGS
++	LIBS=$ac_wbc_save_LIBS
+ fi
+ 
+ if test $enable_cifsacl != "no"; then
+-- 
+1.8.4.2
+
diff --git a/0002-cifscreds-create-PAM-module-to-insert-credentials-at.patch b/0002-cifscreds-create-PAM-module-to-insert-credentials-at.patch
new file mode 100644
index 0000000..106e3b5
--- /dev/null
+++ b/0002-cifscreds-create-PAM-module-to-insert-credentials-at.patch
@@ -0,0 +1,862 @@
+From cbbcd6e71c0a58e79236670463b9eb3f00347021 Mon Sep 17 00:00:00 2001
+From: Orion Poplawski <orion at nwra.com>
+Date: Wed, 13 Nov 2013 13:53:30 -0700
+Subject: [cifs-utils PATCH] cifscreds: create PAM module to insert credentials
+ at login
+
+Split out some of the cifscreds key handling routines into a separate
+file, and then link that in to both cifscreds and the new PAM module.
+
+Fix up autoconf to handle building this automatically.
+
+Signed-off-by: Orion Poplawski <orion at nwra.com>
+---
+ Makefile.am     |  11 +-
+ cifscreds.c     |  49 +----
+ cifskey.c       |  52 ++++++
+ cifskey.h       |  47 +++++
+ configure.ac    |  24 ++-
+ pam_cifscreds.c | 550 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 6 files changed, 681 insertions(+), 52 deletions(-)
+ create mode 100644 cifskey.c
+ create mode 100644 cifskey.h
+ create mode 100644 pam_cifscreds.c
+
+diff --git a/Makefile.am b/Makefile.am
+index 6407520..6e86cd3 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -34,7 +34,7 @@ endif
+ 
+ if CONFIG_CIFSCREDS
+ bin_PROGRAMS += cifscreds
+-cifscreds_SOURCES = cifscreds.c resolve_host.c util.c
++cifscreds_SOURCES = cifscreds.c cifskey.c resolve_host.c util.c
+ cifscreds_LDADD = -lkeyutils
+ man_MANS += cifscreds.1
+ endif
+@@ -91,4 +91,13 @@ idmapwb.8: idmapwb.8.in
+ 
+ endif
+ 
++if CONFIG_PAM
++pamdir = $(libdir)/security
++
++pam_PROGRAMS = pam_cifscreds.so
++
++pam_cifscreds.so: pam_cifscreds.c cifskey.c resolve_host.c util.c
++	$(CC) $(CFLAGS) $(AM_CFLAGS) $(LDFLAGS) -shared -fpic -o $@ $+ -lpam -lkeyutils
++endif
++
+ SUBDIRS = contrib
+diff --git a/cifscreds.c b/cifscreds.c
+index 60be4e5..fa05dc8 100644
+--- a/cifscreds.c
++++ b/cifscreds.c
+@@ -29,35 +29,16 @@
+ #include <keyutils.h>
+ #include <getopt.h>
+ #include <errno.h>
++#include "cifskey.h"
+ #include "mount.h"
+ #include "resolve_host.h"
+ #include "util.h"
+ 
+ #define THIS_PROGRAM_NAME "cifscreds"
+-#define KEY_PREFIX	  "cifs"
+ 
+ /* max length of appropriate command */
+ #define MAX_COMMAND_SIZE 32
+ 
+-/* max length of username, password and domain name */
+-#define MAX_USERNAME_SIZE 32
+-#define MOUNT_PASSWD_SIZE 128
+-#define MAX_DOMAIN_SIZE 64
+-
+-/*
+- * disallowed characters for user and domain names. See:
+- * http://technet.microsoft.com/en-us/library/bb726984.aspx
+- * http://support.microsoft.com/kb/909264
+- */
+-#define USER_DISALLOWED_CHARS "\\/\"[]:|<>+=;,?*"
+-#define DOMAIN_DISALLOWED_CHARS "\\/:*?\"<>|"
+-
+-/* destination keyring */
+-#define DEST_KEYRING KEY_SPEC_SESSION_KEYRING
+-#define CIFS_KEY_TYPE  "logon"
+-#define CIFS_KEY_PERMS (KEY_POS_VIEW|KEY_POS_WRITE|KEY_POS_SEARCH| \
+-			KEY_USR_VIEW|KEY_USR_WRITE|KEY_USR_SEARCH)
+-
+ struct cmdarg {
+ 	char		*host;
+ 	char		*user;
+@@ -106,17 +87,6 @@ usage(void)
+ 	return EXIT_FAILURE;
+ }
+ 
+-/* search a specific key in keyring */
+-static key_serial_t
+-key_search(const char *addr, char keytype)
+-{
+-	char desc[INET6_ADDRSTRLEN + sizeof(KEY_PREFIX) + 4];
+-
+-	sprintf(desc, "%s:%c:%s", KEY_PREFIX, keytype, addr);
+-
+-	return keyctl_search(DEST_KEYRING, CIFS_KEY_TYPE, desc, 0);
+-}
+-
+ /* search all program's keys in keyring */
+ static key_serial_t key_search_all(void)
+ {
+@@ -170,23 +140,6 @@ key_search_all_out:
+ 	return ret;
+ }
+ 
+-/* add or update a specific key to keyring */
+-static key_serial_t
+-key_add(const char *addr, const char *user, const char *pass, char keytype)
+-{
+-	int len;
+-	char desc[INET6_ADDRSTRLEN + sizeof(KEY_PREFIX) + 4];
+-	char val[MOUNT_PASSWD_SIZE +  MAX_USERNAME_SIZE + 2];
+-
+-	/* set key description */
+-	sprintf(desc, "%s:%c:%s", KEY_PREFIX, keytype, addr);
+-
+-	/* set payload contents */
+-	len = sprintf(val, "%s:%s", user, pass);
+-
+-	return add_key(CIFS_KEY_TYPE, desc, val, len + 1, DEST_KEYRING);
+-}
+-
+ /* add command handler */
+ static int cifscreds_add(struct cmdarg *arg)
+ {
+diff --git a/cifskey.c b/cifskey.c
+new file mode 100644
+index 0000000..7716c42
+--- /dev/null
++++ b/cifskey.c
+@@ -0,0 +1,52 @@
++/*
++ * Credentials stashing routines for Linux CIFS VFS (virtual filesystem)
++ * Copyright (C) 2010 Jeff Layton (jlayton at samba.org)
++ * Copyright (C) 2010 Igor Druzhinin (jaxbrigs at gmail.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 3 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <sys/types.h>
++#include <keyutils.h>
++#include <stdio.h>
++#include "cifskey.h"
++#include "resolve_host.h"
++
++/* search a specific key in keyring */
++key_serial_t
++key_search(const char *addr, char keytype)
++{
++	char desc[INET6_ADDRSTRLEN + sizeof(KEY_PREFIX) + 4];
++
++	sprintf(desc, "%s:%c:%s", KEY_PREFIX, keytype, addr);
++
++	return keyctl_search(DEST_KEYRING, CIFS_KEY_TYPE, desc, 0);
++}
++
++/* add or update a specific key to keyring */
++key_serial_t
++key_add(const char *addr, const char *user, const char *pass, char keytype)
++{
++	int len;
++	char desc[INET6_ADDRSTRLEN + sizeof(KEY_PREFIX) + 4];
++	char val[MOUNT_PASSWD_SIZE +  MAX_USERNAME_SIZE + 2];
++
++	/* set key description */
++	sprintf(desc, "%s:%c:%s", KEY_PREFIX, keytype, addr);
++
++	/* set payload contents */
++	len = sprintf(val, "%s:%s", user, pass);
++
++	return add_key(CIFS_KEY_TYPE, desc, val, len + 1, DEST_KEYRING);
++}
+diff --git a/cifskey.h b/cifskey.h
+new file mode 100644
+index 0000000..ed0c469
+--- /dev/null
++++ b/cifskey.h
+@@ -0,0 +1,47 @@
++/*
++ * Credentials stashing utility for Linux CIFS VFS (virtual filesystem) definitions
++ * Copyright (C) 2010 Jeff Layton (jlayton at samba.org)
++ * Copyright (C) 2010 Igor Druzhinin (jaxbrigs at gmail.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 3 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef _CIFSKEY_H
++#define _CIFSKEY_H
++
++#define KEY_PREFIX	  "cifs"
++
++/* max length of username, password and domain name */
++#define MAX_USERNAME_SIZE 32
++#define MOUNT_PASSWD_SIZE 128
++#define MAX_DOMAIN_SIZE 64
++
++/*
++ * disallowed characters for user and domain names. See:
++ * http://technet.microsoft.com/en-us/library/bb726984.aspx
++ * http://support.microsoft.com/kb/909264
++ */
++#define USER_DISALLOWED_CHARS "\\/\"[]:|<>+=;,?*"
++#define DOMAIN_DISALLOWED_CHARS "\\/:*?\"<>|"
++
++/* destination keyring */
++#define DEST_KEYRING KEY_SPEC_SESSION_KEYRING
++#define CIFS_KEY_TYPE  "logon"
++#define CIFS_KEY_PERMS (KEY_POS_VIEW|KEY_POS_WRITE|KEY_POS_SEARCH| \
++			KEY_USR_VIEW|KEY_USR_WRITE|KEY_USR_SEARCH)
++
++key_serial_t key_search(const char *addr, char keytype);
++key_serial_t key_add(const char *addr, const char *user, const char *pass, char keytype);
++
++#endif /* _CIFSKEY_H */
+diff --git a/configure.ac b/configure.ac
+index c5b2244..4a9cb6d 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -40,6 +40,11 @@ AC_ARG_ENABLE(cifsacl,
+ 	enable_cifsacl=$enableval,
+ 	enable_cifsacl="maybe")
+ 
++AC_ARG_ENABLE(pam,
++	[AS_HELP_STRING([--enable-pam],[Create cifscreds PAM module @<:@default=yes@:>@])],
++	enable_pam=$enableval,
++	enable_pam="maybe")
++
+ AC_ARG_ENABLE(systemd,
+ 	[AS_HELP_STRING([--enable-systemd],[Enable systemd specific behavior for mount.cifs @<:@default=yes@:>@])],
+ 	enable_systemd=$enableval,
+@@ -190,18 +195,30 @@ AC_TEST_WBCHL
+ # test for presence of WBC_ID_TYPE_BOTH enum value
+ AC_TEST_WBC_IDMAP_BOTH
+ 
+-if test $enable_cifscreds != "no"; then
++if test $enable_cifscreds != "no" -o $enable_pam != "no"; then
+ 	AC_CHECK_HEADERS([keyutils.h], , [
+ 
+-				if test $enable_cifscreds = "yes"; then
++				if test $enable_cifscreds = "yes" -o $enable_pam = "yes"; then
+ 					AC_MSG_ERROR([keyutils.h not found, consider installing keyutils-libs-devel.])
+ 				else
+-					AC_MSG_WARN([keyutils.h not found, consider installing keyutils-libs-devel. Disabling cifscreds.])
++					AC_MSG_WARN([keyutils.h not found, consider installing keyutils-libs-devel. Disabling cifscreds and cifscreds PAM module.])
+ 					enable_cifscreds="no"
++					enable_pam="no"
+ 				fi
+ 			])
+ fi
+ 
++if test $enable_pam != "no"; then
++	AC_CHECK_HEADERS([security/pam_appl.h], , [
++
++				if test $enable_pam = "yes"; then
++					AC_MSG_ERROR([security/pam_appl.h not found, consider installing keyutils-libs-devel.])
++				else
++					AC_MSG_WARN([security/pam_appl.h not found, consider installing pam-devel. Disabling cifscreds PAM module.])
++					enable_pam="no"
++				fi
++			])
++fi
+ 
+ # ugly, but I'm not sure how to check for functions in a library that's not in $LIBS
+ cu_saved_libs=$LIBS
+@@ -231,6 +248,7 @@ AM_CONDITIONAL(CONFIG_CIFSUPCALL, [test "$enable_cifsupcall" != "no"])
+ AM_CONDITIONAL(CONFIG_CIFSCREDS, [test "$enable_cifscreds" != "no"])
+ AM_CONDITIONAL(CONFIG_CIFSIDMAP, [test "$enable_cifsidmap" != "no"])
+ AM_CONDITIONAL(CONFIG_CIFSACL, [test "$enable_cifsacl" != "no"])
++AM_CONDITIONAL(CONFIG_PAM, [test "$enable_pam" != "no"])
+ AM_CONDITIONAL(CONFIG_PLUGIN, [test "$enable_cifsidmap" != "no" -o "$enable_cifsacl" != "no"])
+ 
+ LIBCAP_NG_PATH
+diff --git a/pam_cifscreds.c b/pam_cifscreds.c
+new file mode 100644
+index 0000000..1385146
+--- /dev/null
++++ b/pam_cifscreds.c
+@@ -0,0 +1,550 @@
++/*
++ * Copyright (C) 2013 Orion Poplawski <orion at cora.nwra.com>
++ *
++ * based on gkr-pam-module.c, Copyright (C) 2007 Stef Walter
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 3 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ */
++
++#ifdef HAVE_CONFIG_H
++#include "config.h"
++#endif /* HAVE_CONFIG_H */
++
++#include <assert.h>
++#include <errno.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <syslog.h>
++#include <sys/types.h>
++/*
++#include <signal.h>
++#include <unistd.h>
++#include <sys/wait.h>
++*/
++
++#include <keyutils.h>
++
++#include <security/pam_appl.h>
++#include <security/pam_modules.h>
++#include <security/pam_ext.h>
++
++#include "cifskey.h"
++#include "mount.h"
++#include "resolve_host.h"
++#include "util.h"
++
++/**
++ * Flags that can be passed to the PAM module
++ */
++enum {
++	ARG_DOMAIN	   = 1 << 0,	/** Set domain password */
++	ARG_DEBUG	   = 1 << 1	/** Print debug messages */
++};
++
++/**
++ * Parse the arguments passed to the PAM module.
++ *
++ * @param ph PAM handle
++ * @param argc number of arguments
++ * @param argv array of arguments
++ * @param kwalletopener kwalletopener argument, path to the kwalletopener binary
++ * @return ORed flags that have been parsed
++ */
++static uint parse_args (pam_handle_t *ph, int argc, const char **argv, const char **hostdomain)
++{
++	uint args = 0;
++	const void *svc;
++	int i;
++	const char *host = NULL;
++	const char *domain = NULL;
++
++	svc = NULL;
++	if (pam_get_item (ph, PAM_SERVICE, &svc) != PAM_SUCCESS) {
++		svc = NULL;
++	}
++
++	size_t host_len = strlen("host=");
++	size_t domain_len = strlen("domain=");
++
++	/* Parse the arguments */
++	for (i = 0; i < argc; i++) {
++		if (strncmp(argv[i], "host=", host_len) == 0) {
++			host = (argv[i]) + host_len;
++			if (*host == '\0') {
++				host = NULL;
++				pam_syslog(ph, LOG_ERR, ""
++					   "host= specification missing argument");
++			} else {
++				*hostdomain = host;
++			}
++		} else if (strncmp(argv[i], "domain=", domain_len) == 0) {
++			domain = (argv[i]) + domain_len;
++			if (*domain == '\0') {
++				domain = NULL;
++				pam_syslog(ph, LOG_ERR, ""
++					   "domain= specification missing argument");
++			} else {
++				*hostdomain = domain;
++				args |= ARG_DOMAIN;
++			}
++		} else if (strcmp(argv[i], "debug") == 0) {
++			args |= ARG_DEBUG;
++		} else {
++			pam_syslog(ph, LOG_ERR, "invalid option %s",
++				   argv[i]);
++		}
++	}
++
++	if (host && domain) {
++		pam_syslog(ph, LOG_ERR, "cannot specify both host= and "
++			   "domain= arguments");
++	}
++
++	return args;
++}
++
++static void
++free_password (char *password)
++{
++	volatile char *vp;
++	size_t len;
++
++	if (!password) {
++		return;
++	}
++
++	/* Defeats some optimizations */
++	len = strlen (password);
++	memset (password, 0xAA, len);
++	memset (password, 0xBB, len);
++
++	/* Defeats others */
++	vp = (volatile char*)password;
++	while (*vp) {
++		*(vp++) = 0xAA;
++	}
++
++	free (password);
++}
++
++static void
++cleanup_free_password (pam_handle_t *ph, void *data, int pam_end_status)
++{
++	free_password (data);
++}
++
++/**
++ * Set the cifs credentials
++ *
++ * @param ph PAM handle
++ * @param user
++ * @param password
++ * @param args ORed flags for this module
++ * @param hostdomain hostname or domainname
++ */
++static int cifscreds_pam_add(pam_handle_t *ph, const char *user, const char *password,
++			     uint args, const char *hostdomain)
++{
++	int ret = PAM_SUCCESS;
++	char addrstr[MAX_ADDR_LIST_LEN];
++	char *currentaddress, *nextaddress;
++	char keytype = ((args & ARG_DOMAIN) == ARG_DOMAIN) ? 'd' : 'a';
++
++	assert(user);
++	assert(password);
++	assert(hostdomain);
++
++	if (keytype == 'd') {
++		if (strpbrk(hostdomain, DOMAIN_DISALLOWED_CHARS)) {
++			pam_syslog(ph, LOG_ERR, "Domain name contains invalid characters");
++			return PAM_SERVICE_ERR;
++		}
++		strlcpy(addrstr, hostdomain, MAX_ADDR_LIST_LEN);
++	} else {
++		ret = resolve_host(hostdomain, addrstr);
++	}
++
++	switch (ret) {
++	case EX_USAGE:
++		pam_syslog(ph, LOG_ERR, "Could not resolve address for %s", hostdomain);
++		return PAM_SERVICE_ERR;
++
++	case EX_SYSERR:
++		pam_syslog(ph, LOG_ERR, "Problem parsing address list");
++		return PAM_SERVICE_ERR;
++	}
++
++	if (strpbrk(user, USER_DISALLOWED_CHARS)) {
++		pam_syslog(ph, LOG_ERR, "Incorrect username");
++		return PAM_SERVICE_ERR;
++	}
++
++	/* search for same credentials stashed for current host */
++	currentaddress = addrstr;
++	nextaddress = strchr(currentaddress, ',');
++	if (nextaddress)
++		*nextaddress++ = '\0';
++
++	while (currentaddress) {
++		if (key_search(currentaddress, keytype) > 0) {
++			pam_syslog(ph, LOG_WARNING, "You already have stashed credentials "
++				"for %s (%s)", currentaddress, hostdomain);
++
++			return PAM_SERVICE_ERR;
++		}
++
++		currentaddress = nextaddress;
++		if (currentaddress) {
++			*(currentaddress - 1) = ',';
++			nextaddress = strchr(currentaddress, ',');
++			if (nextaddress)
++				*nextaddress++ = '\0';
++		}
++	}
++
++	/* Set the password */
++	currentaddress = addrstr;
++	nextaddress = strchr(currentaddress, ',');
++	if (nextaddress)
++		*nextaddress++ = '\0';
++
++	while (currentaddress) {
++		key_serial_t key = key_add(currentaddress, user, password, keytype);
++		if (key <= 0) {
++			pam_syslog(ph, LOG_ERR, "error: Add credential key for %s",
++				currentaddress);
++		} else {
++			if ((args & ARG_DEBUG) == ARG_DEBUG) {
++				pam_syslog(ph, LOG_DEBUG, "credential key for \\\\%s\\%s added",
++					   currentaddress, user);
++			}
++			if (keyctl(KEYCTL_SETPERM, key, CIFS_KEY_PERMS) < 0) {
++				pam_syslog(ph, LOG_ERR,"error: Setting permissons "
++					"on key, attempt to delete...");
++
++				if (keyctl(KEYCTL_UNLINK, key, DEST_KEYRING) < 0) {
++					pam_syslog(ph, LOG_ERR, "error: Deleting key from "
++						"keyring for %s (%s)",
++						currentaddress, hostdomain);
++				}
++			}
++		}
++
++		currentaddress = nextaddress;
++		if (currentaddress) {
++			nextaddress = strchr(currentaddress, ',');
++			if (nextaddress)
++				*nextaddress++ = '\0';
++		}
++	}
++
++	return PAM_SUCCESS;
++}
++
++/**
++ * Update the cifs credentials
++ *
++ * @param ph PAM handle
++ * @param user
++ * @param password
++ * @param args ORed flags for this module
++ * @param hostdomain hostname or domainname
++ */
++static int cifscreds_pam_update(pam_handle_t *ph, const char *user, const char *password,
++				uint args, const char *hostdomain)
++{
++	int ret = PAM_SUCCESS;
++	char addrstr[MAX_ADDR_LIST_LEN];
++	char *currentaddress, *nextaddress;
++	char *addrs[16];
++	int id, count = 0;
++	char keytype = ((args & ARG_DOMAIN) == ARG_DOMAIN) ? 'd' : 'a';
++
++	assert(user);
++	assert(password);
++	assert(hostdomain);
++
++	if (keytype == 'd') {
++		if (strpbrk(hostdomain, DOMAIN_DISALLOWED_CHARS)) {
++			pam_syslog(ph, LOG_ERR, "Domain name contains invalid characters");
++			return PAM_SERVICE_ERR;
++		}
++		strlcpy(addrstr, hostdomain, MAX_ADDR_LIST_LEN);
++	} else {
++		ret = resolve_host(hostdomain, addrstr);
++	}
++
++	switch (ret) {
++	case EX_USAGE:
++		pam_syslog(ph, LOG_ERR, "Could not resolve address for %s", hostdomain);
++		return PAM_SERVICE_ERR;
++
++	case EX_SYSERR:
++		pam_syslog(ph, LOG_ERR, "Problem parsing address list");
++		return PAM_SERVICE_ERR;
++	}
++
++	if (strpbrk(user, USER_DISALLOWED_CHARS)) {
++		pam_syslog(ph, LOG_ERR, "Incorrect username");
++		return PAM_SERVICE_ERR;
++	}
++
++	/* search for necessary credentials stashed in session keyring */
++	currentaddress = addrstr;
++	nextaddress = strchr(currentaddress, ',');
++	if (nextaddress)
++		*nextaddress++ = '\0';
++
++	while (currentaddress) {
++		if (key_search(currentaddress, keytype) > 0) {
++			addrs[count] = currentaddress;
++			count++;
++		}
++
++		currentaddress = nextaddress;
++		if (currentaddress) {
++			nextaddress = strchr(currentaddress, ',');
++			if (nextaddress)
++				*nextaddress++ = '\0';
++		}
++	}
++
++	if (!count) {
++		pam_syslog(ph, LOG_ERR, "You have no same stached credentials for %s", hostdomain);
++		return PAM_SERVICE_ERR;
++	}
++
++	for (id = 0; id < count; id++) {
++		key_serial_t key = key_add(currentaddress, user, password, keytype);
++		if (key <= 0) {
++			pam_syslog(ph, LOG_ERR, "error: Update credential key for %s",
++				currentaddress);
++		}
++	}
++
++	return PAM_SUCCESS;
++}
++
++/**
++ * PAM function called during authentication.
++ *
++ * This function first tries to get a password from PAM. Afterwards two
++ * scenarios are possible:
++ *
++ * - A session is already available which usually means that the user is already
++ *	logged on and PAM has been used inside the screensaver. In that case, no need to 
++ *	do anything(?).
++ *
++ * - A session is not yet available. Store the password inside PAM data so
++ *	it can be retrieved during pam_open_session to set the credentials.
++ *
++ * @param ph PAM handle
++ * @param unused unused
++ * @param argc number of arguments for this PAM module
++ * @param argv array of arguments for this PAM module
++ * @return any of the PAM return values
++ */
++PAM_EXTERN int pam_sm_authenticate(pam_handle_t *ph, int unused, int argc, const char **argv)
++{
++	const char *hostdomain;
++	const char *user;
++	const char *password;
++	uint args;
++	int ret;
++
++	args = parse_args(ph, argc, argv, &hostdomain);
++	
++	/* Figure out and/or prompt for the user name */
++	ret = pam_get_user(ph, &user, NULL);
++	if (ret != PAM_SUCCESS || !user) {
++		pam_syslog(ph, LOG_ERR, "couldn't get the user name: %s",
++			   pam_strerror(ph, ret));
++		return PAM_SERVICE_ERR;
++	}
++
++	/* Lookup the password */
++	ret = pam_get_item(ph, PAM_AUTHTOK, (const void**)&password);
++	if (ret != PAM_SUCCESS || password == NULL) {
++		if (ret == PAM_SUCCESS) {
++			pam_syslog(ph, LOG_WARNING, "no password is available for user");
++		} else {
++			pam_syslog(ph, LOG_WARNING, "no password is available for user: %s",
++				   pam_strerror(ph, ret));
++		}
++		return PAM_SUCCESS;
++	}
++
++	/* set password as pam data and launch during open_session. */
++	if (pam_set_data(ph, "cifscreds_password", strdup(password), cleanup_free_password) != PAM_SUCCESS) {
++		pam_syslog(ph, LOG_ERR, "error storing password");
++		return PAM_AUTHTOK_RECOVER_ERR;
++	}
++
++	if ((args & ARG_DEBUG) == ARG_DEBUG) {
++		pam_syslog(ph, LOG_DEBUG, "password stored");
++	}
++
++	return PAM_SUCCESS;
++}
++
++/**
++ * PAM function called during opening the session.
++ *
++ * Retrieves the password stored during authentication from PAM data, then uses
++ * it set the cifs key.
++ *
++ * @param ph PAM handle
++ * @param flags currently unused, TODO: check for silent flag
++ * @param argc number of arguments for this PAM module
++ * @param argv array of arguments for this PAM module
++ * @return any of the PAM return values
++ */
++PAM_EXTERN int pam_sm_open_session(pam_handle_t *ph, int flags, int argc, const char **argv)
++{
++	const char *user = NULL;
++	const char *password = NULL;
++	const char *hostdomain = NULL;
++	uint args;
++	int retval;
++	key_serial_t	ses_key, uses_key;
++
++	args = parse_args(ph, argc, argv, &hostdomain);
++
++	/* Figure out the user name */
++	retval = pam_get_user(ph, &user, NULL);
++	if (retval != PAM_SUCCESS || !user) {
++		pam_syslog(ph, LOG_ERR, "couldn't get the user name: %s",
++			   pam_strerror(ph, retval));
++		return PAM_SERVICE_ERR;
++	}
++
++	/* retrieve the stored password */
++	if (pam_get_data(ph, "cifscreds_password", (const void**)&password) != PAM_SUCCESS) {
++		/*
++		 * No password, no worries, maybe this (PAM using) application
++		 * didn't do authentication, or is hopeless and wants to call
++		 * different PAM callbacks from different processes.
++		 *
++		 *
++		 */
++		password = NULL;
++		if ((args & ARG_DEBUG) == ARG_DEBUG) {
++			pam_syslog(ph, LOG_DEBUG, "no stored password found");
++		}
++		return PAM_SUCCESS;
++	}
++
++	/* make sure we have a host or domain name */
++	if (!hostdomain) {
++		pam_syslog(ph, LOG_ERR, "one of host= or domain= must be specified");
++		return PAM_SERVICE_ERR;
++	}
++
++	/* make sure there is a session keyring */
++	ses_key = keyctl_get_keyring_ID(KEY_SPEC_SESSION_KEYRING, 0);
++	if (ses_key == -1) {
++		if (errno == ENOKEY)
++			pam_syslog(ph, LOG_ERR, "you have no session keyring. "
++					"Consider using pam_keyinit to "
++					"install one.");
++		else
++			pam_syslog(ph, LOG_ERR, "unable to query session "
++					"keyring: %s", strerror(errno));
++	}
++
++	/* A problem querying the user-session keyring isn't fatal. */
++	uses_key = keyctl_get_keyring_ID(KEY_SPEC_USER_SESSION_KEYRING, 0);
++	if ((uses_key >= 0) && (ses_key == uses_key))
++		pam_syslog(ph, LOG_ERR, "you have no persistent session "
++				"keyring. cifscreds keys will not persist.");
++
++	return cifscreds_pam_add(ph, user, password, args, hostdomain);
++}
++
++/**
++ * This is called when the PAM session is closed.
++ *
++ * Currently it does nothing.  The session closing should remove the passwords
++ *
++ * @param ph PAM handle
++ * @param flags currently unused, TODO: check for silent flag
++ * @param argc number of arguments for this PAM module
++ * @param argv array of arguments for this PAM module
++ * @return PAM_SUCCESS
++ */
++PAM_EXTERN int pam_sm_close_session(pam_handle_t *ph, int flags, int argc, const char **argv)
++{
++	return PAM_SUCCESS;
++}
++
++/**
++ * This is called when pam_set_cred() is invoked.
++ *
++ * @param ph PAM handle
++ * @param flags currently unused, TODO: check for silent flag
++ * @param argc number of arguments for this PAM module
++ * @param argv array of arguments for this PAM module
++ * @return PAM_SUCCESS
++ */
++PAM_EXTERN int pam_sm_setcred(pam_handle_t *ph, int flags, int argc, const char **argv)
++{
++	return PAM_SUCCESS;
++}
++
++/**
++ * This is called when the user's password is changed
++ *
++ * @param ph PAM handle
++ * @param flags currently unused, TODO: check for silent flag
++ * @param argc number of arguments for this PAM module
++ * @param argv array of arguments for this PAM module
++ * @return PAM_SUCCESS
++ */
++PAM_EXTERN int
++pam_sm_chauthtok (pam_handle_t *ph, int flags, int argc, const char **argv)
++{
++	const char *hostdomain = NULL;
++	const char *user = NULL;
++	const char *password = NULL;
++	uint args;
++	int ret;
++	
++	args = parse_args(ph, argc, argv, &hostdomain);
++
++	if (flags & PAM_UPDATE_AUTHTOK) {
++		/* Figure out the user name */
++		ret = pam_get_user(ph, &user, NULL);
++		if (ret != PAM_SUCCESS) {
++			pam_syslog(ph, LOG_ERR, "couldn't get the user name: %s", 
++				pam_strerror (ph, ret));
++			return PAM_SERVICE_ERR;
++		}
++
++		ret = pam_get_item(ph, PAM_AUTHTOK, (const void**)&password);
++		if (ret != PAM_SUCCESS || password == NULL) {
++			if (ret == PAM_SUCCESS) {
++				pam_syslog(ph, LOG_WARNING, "no password is available for user");
++			} else {
++				pam_syslog(ph, LOG_WARNING, "no password is available for user: %s",
++					pam_strerror(ph, ret));
++			}
++			return PAM_AUTHTOK_RECOVER_ERR;
++		}
++	
++		return cifscreds_pam_update(ph, user, password, args, hostdomain);
++	}
++	else 
++		return PAM_IGNORE;
++}
+-- 
+1.8.4.2
+
diff --git a/0003-cifscreds-fix-up-some-whitespace-typos-and-build-war.patch b/0003-cifscreds-fix-up-some-whitespace-typos-and-build-war.patch
new file mode 100644
index 0000000..d0eb548
--- /dev/null
+++ b/0003-cifscreds-fix-up-some-whitespace-typos-and-build-war.patch
@@ -0,0 +1,197 @@
+From d12443fdd268e547412683d43dc03f266260f7c8 Mon Sep 17 00:00:00 2001
+From: Jeff Layton <jlayton at samba.org>
+Date: Sat, 7 Dec 2013 06:52:26 -0500
+Subject: [cifs-utils PATCH] cifscreds: fix up some whitespace, typos and build
+ warnings in pam_cifscreds.c
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+gcc -g -O2 -Wall -Wextra -D_FORTIFY_SOURCE=2 -fpie -pie -Wl,-z,relro,-z,now  -shared -fpic -o pam_cifscreds.so pam_cifscreds.c cifskey.c resolve_host.c util.c -lpam -lkeyutils
+pam_cifscreds.c: In function ‘cleanup_free_password’:
+pam_cifscreds.c:143:38: warning: unused parameter ‘ph’ [-Wunused-parameter]
+ cleanup_free_password (pam_handle_t *ph, void *data, int pam_end_status)
+                                      ^
+pam_cifscreds.c:143:58: warning: unused parameter ‘pam_end_status’ [-Wunused-parameter]
+ cleanup_free_password (pam_handle_t *ph, void *data, int pam_end_status)
+                                                          ^
+pam_cifscreds.c: In function ‘cifscreds_pam_update’:
+pam_cifscreds.c:271:8: warning: variable ‘addrs’ set but not used [-Wunused-but-set-variable]
+  char *addrs[16];
+        ^
+pam_cifscreds.c: In function ‘pam_sm_authenticate’:
+pam_cifscreds.c:359:58: warning: unused parameter ‘unused’ [-Wunused-parameter]
+ PAM_EXTERN int pam_sm_authenticate(pam_handle_t *ph, int unused, int argc, const char **argv)
+                                                          ^
+pam_cifscreds.c: In function ‘pam_sm_open_session’:
+pam_cifscreds.c:414:58: warning: unused parameter ‘flags’ [-Wunused-parameter]
+ PAM_EXTERN int pam_sm_open_session(pam_handle_t *ph, int flags, int argc, const char **argv)
+                                                          ^
+pam_cifscreds.c: In function ‘pam_sm_close_session’:
+pam_cifscreds.c:487:51: warning: unused parameter ‘ph’ [-Wunused-parameter]
+ PAM_EXTERN int pam_sm_close_session(pam_handle_t *ph, int flags, int argc, const char **argv)
+                                                   ^
+pam_cifscreds.c:487:59: warning: unused parameter ‘flags’ [-Wunused-parameter]
+ PAM_EXTERN int pam_sm_close_session(pam_handle_t *ph, int flags, int argc, const char **argv)
+                                                           ^
+pam_cifscreds.c:487:70: warning: unused parameter ‘argc’ [-Wunused-parameter]
+ PAM_EXTERN int pam_sm_close_session(pam_handle_t *ph, int flags, int argc, const char **argv)
+                                                                      ^
+pam_cifscreds.c:487:89: warning: unused parameter ‘argv’ [-Wunused-parameter]
+ PAM_EXTERN int pam_sm_close_session(pam_handle_t *ph, int flags, int argc, const char **argv)
+                                                                                         ^
+pam_cifscreds.c: In function ‘pam_sm_setcred’:
+pam_cifscreds.c:501:45: warning: unused parameter ‘ph’ [-Wunused-parameter]
+ PAM_EXTERN int pam_sm_setcred(pam_handle_t *ph, int flags, int argc, const char **argv)
+                                             ^
+pam_cifscreds.c:501:53: warning: unused parameter ‘flags’ [-Wunused-parameter]
+ PAM_EXTERN int pam_sm_setcred(pam_handle_t *ph, int flags, int argc, const char **argv)
+                                                     ^
+pam_cifscreds.c:501:64: warning: unused parameter ‘argc’ [-Wunused-parameter]
+ PAM_EXTERN int pam_sm_setcred(pam_handle_t *ph, int flags, int argc, const char **argv)
+                                                                ^
+pam_cifscreds.c:501:83: warning: unused parameter ‘argv’ [-Wunused-parameter]
+ PAM_EXTERN int pam_sm_setcred(pam_handle_t *ph, int flags, int argc, const char **argv)
+                                                                                   ^
+
+Signed-off-by: Jeff Layton <jlayton at samba.org>
+---
+ pam_cifscreds.c | 34 +++++++++++++++-------------------
+ 1 file changed, 15 insertions(+), 19 deletions(-)
+
+diff --git a/pam_cifscreds.c b/pam_cifscreds.c
+index 1385146..e0d8a55 100644
+--- a/pam_cifscreds.c
++++ b/pam_cifscreds.c
+@@ -140,7 +140,8 @@ free_password (char *password)
+ }
+ 
+ static void
+-cleanup_free_password (pam_handle_t *ph, void *data, int pam_end_status)
++cleanup_free_password (pam_handle_t *ph __attribute__((unused)), void *data,
++			int pam_end_status __attribute__((unused)))
+ {
+ 	free_password (data);
+ }
+@@ -268,7 +269,6 @@ static int cifscreds_pam_update(pam_handle_t *ph, const char *user, const char *
+ 	int ret = PAM_SUCCESS;
+ 	char addrstr[MAX_ADDR_LIST_LEN];
+ 	char *currentaddress, *nextaddress;
+-	char *addrs[16];
+ 	int id, count = 0;
+ 	char keytype = ((args & ARG_DOMAIN) == ARG_DOMAIN) ? 'd' : 'a';
+ 
+@@ -308,10 +308,8 @@ static int cifscreds_pam_update(pam_handle_t *ph, const char *user, const char *
+ 		*nextaddress++ = '\0';
+ 
+ 	while (currentaddress) {
+-		if (key_search(currentaddress, keytype) > 0) {
+-			addrs[count] = currentaddress;
++		if (key_search(currentaddress, keytype) > 0)
+ 			count++;
+-		}
+ 
+ 		currentaddress = nextaddress;
+ 		if (currentaddress) {
+@@ -322,7 +320,7 @@ static int cifscreds_pam_update(pam_handle_t *ph, const char *user, const char *
+ 	}
+ 
+ 	if (!count) {
+-		pam_syslog(ph, LOG_ERR, "You have no same stached credentials for %s", hostdomain);
++		pam_syslog(ph, LOG_ERR, "You have no same stashed credentials for %s", hostdomain);
+ 		return PAM_SERVICE_ERR;
+ 	}
+ 
+@@ -344,7 +342,7 @@ static int cifscreds_pam_update(pam_handle_t *ph, const char *user, const char *
+  * scenarios are possible:
+  *
+  * - A session is already available which usually means that the user is already
+- *	logged on and PAM has been used inside the screensaver. In that case, no need to 
++ *	logged on and PAM has been used inside the screensaver. In that case, no need to
+  *	do anything(?).
+  *
+  * - A session is not yet available. Store the password inside PAM data so
+@@ -356,7 +354,7 @@ static int cifscreds_pam_update(pam_handle_t *ph, const char *user, const char *
+  * @param argv array of arguments for this PAM module
+  * @return any of the PAM return values
+  */
+-PAM_EXTERN int pam_sm_authenticate(pam_handle_t *ph, int unused, int argc, const char **argv)
++PAM_EXTERN int pam_sm_authenticate(pam_handle_t *ph, int unused __attribute__((unused)), int argc, const char **argv)
+ {
+ 	const char *hostdomain;
+ 	const char *user;
+@@ -365,7 +363,7 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t *ph, int unused, int argc, const
+ 	int ret;
+ 
+ 	args = parse_args(ph, argc, argv, &hostdomain);
+-	
++
+ 	/* Figure out and/or prompt for the user name */
+ 	ret = pam_get_user(ph, &user, NULL);
+ 	if (ret != PAM_SUCCESS || !user) {
+@@ -411,7 +409,7 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t *ph, int unused, int argc, const
+  * @param argv array of arguments for this PAM module
+  * @return any of the PAM return values
+  */
+-PAM_EXTERN int pam_sm_open_session(pam_handle_t *ph, int flags, int argc, const char **argv)
++PAM_EXTERN int pam_sm_open_session(pam_handle_t *ph, int flags __attribute__((unused)), int argc, const char **argv)
+ {
+ 	const char *user = NULL;
+ 	const char *password = NULL;
+@@ -484,7 +482,7 @@ PAM_EXTERN int pam_sm_open_session(pam_handle_t *ph, int flags, int argc, const
+  * @param argv array of arguments for this PAM module
+  * @return PAM_SUCCESS
+  */
+-PAM_EXTERN int pam_sm_close_session(pam_handle_t *ph, int flags, int argc, const char **argv)
++PAM_EXTERN int pam_sm_close_session(pam_handle_t *ph __attribute__((unused)), int flags __attribute__((unused)), int argc __attribute__((unused)), const char **argv __attribute__((unused)))
+ {
+ 	return PAM_SUCCESS;
+ }
+@@ -498,7 +496,7 @@ PAM_EXTERN int pam_sm_close_session(pam_handle_t *ph, int flags, int argc, const
+  * @param argv array of arguments for this PAM module
+  * @return PAM_SUCCESS
+  */
+-PAM_EXTERN int pam_sm_setcred(pam_handle_t *ph, int flags, int argc, const char **argv)
++PAM_EXTERN int pam_sm_setcred(pam_handle_t *ph __attribute__((unused)), int flags __attribute__((unused)), int argc __attribute__((unused)), const char **argv __attribute__((unused)))
+ {
+ 	return PAM_SUCCESS;
+ }
+@@ -520,15 +518,14 @@ pam_sm_chauthtok (pam_handle_t *ph, int flags, int argc, const char **argv)
+ 	const char *password = NULL;
+ 	uint args;
+ 	int ret;
+-	
++
+ 	args = parse_args(ph, argc, argv, &hostdomain);
+ 
+ 	if (flags & PAM_UPDATE_AUTHTOK) {
+ 		/* Figure out the user name */
+ 		ret = pam_get_user(ph, &user, NULL);
+ 		if (ret != PAM_SUCCESS) {
+-			pam_syslog(ph, LOG_ERR, "couldn't get the user name: %s", 
+-				pam_strerror (ph, ret));
++			pam_syslog(ph, LOG_ERR, "couldn't get the user name: %s", pam_strerror (ph, ret));
+ 			return PAM_SERVICE_ERR;
+ 		}
+ 
+@@ -537,14 +534,13 @@ pam_sm_chauthtok (pam_handle_t *ph, int flags, int argc, const char **argv)
+ 			if (ret == PAM_SUCCESS) {
+ 				pam_syslog(ph, LOG_WARNING, "no password is available for user");
+ 			} else {
+-				pam_syslog(ph, LOG_WARNING, "no password is available for user: %s",
+-					pam_strerror(ph, ret));
++				pam_syslog(ph, LOG_WARNING, "no password is available for user: %s", pam_strerror(ph, ret));
+ 			}
+ 			return PAM_AUTHTOK_RECOVER_ERR;
+ 		}
+-	
++
+ 		return cifscreds_pam_update(ph, user, password, args, hostdomain);
+ 	}
+-	else 
++	else
+ 		return PAM_IGNORE;
+ }
+-- 
+1.8.4.2
+
diff --git a/0004-manpage-add-pam_cifscreds.8-man-page.patch b/0004-manpage-add-pam_cifscreds.8-man-page.patch
new file mode 100644
index 0000000..327a88f
--- /dev/null
+++ b/0004-manpage-add-pam_cifscreds.8-man-page.patch
@@ -0,0 +1,332 @@
+From ba68b6b98dee147478041c9bade6df3df176af62 Mon Sep 17 00:00:00 2001
+From: Orion Poplawski <orion at nwra.com>
+Date: Tue, 10 Dec 2013 14:09:26 -0700
+Subject: [cifs-utils PATCH] manpage: add pam_cifscreds.8 man page
+
+Signed-off-by: Orion Poplawski <orion at nwra.com>
+---
+ Makefile.am       |   1 +
+ pam_cifscreds.8   | 207 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ pam_cifscreds.pod |  84 ++++++++++++++++++++++
+ 3 files changed, 292 insertions(+)
+ create mode 100644 pam_cifscreds.8
+ create mode 100644 pam_cifscreds.pod
+
+diff --git a/Makefile.am b/Makefile.am
+index 6e86cd3..a3fb413 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -98,6 +98,7 @@ pam_PROGRAMS = pam_cifscreds.so
+ 
+ pam_cifscreds.so: pam_cifscreds.c cifskey.c resolve_host.c util.c
+ 	$(CC) $(CFLAGS) $(AM_CFLAGS) $(LDFLAGS) -shared -fpic -o $@ $+ -lpam -lkeyutils
++man_MANS += pam_cifscreds.8
+ endif
+ 
+ SUBDIRS = contrib
+diff --git a/pam_cifscreds.8 b/pam_cifscreds.8
+new file mode 100644
+index 0000000..619cc7c
+--- /dev/null
++++ b/pam_cifscreds.8
+@@ -0,0 +1,207 @@
++.\" Automatically generated by Pod::Man 2.27 (Pod::Simple 3.28)
++.\"
++.\" Standard preamble:
++.\" ========================================================================
++.de Sp \" Vertical space (when we can't use .PP)
++.if t .sp .5v
++.if n .sp
++..
++.de Vb \" Begin verbatim text
++.ft CW
++.nf
++.ne \\$1
++..
++.de Ve \" End verbatim text
++.ft R
++.fi
++..
++.\" Set up some character translations and predefined strings.  \*(-- will
++.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
++.\" double quote, and \*(R" will give a right double quote.  \*(C+ will
++.\" give a nicer C++.  Capital omega is used to do unbreakable dashes and
++.\" therefore won't be available.  \*(C` and \*(C' expand to `' in nroff,
++.\" nothing in troff, for use with C<>.
++.tr \(*W-
++.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
++.ie n \{\
++.    ds -- \(*W-
++.    ds PI pi
++.    if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
++.    if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo 12 pitch
++.    ds L" ""
++.    ds R" ""
++.    ds C` ""
++.    ds C' ""
++'br\}
++.el\{\
++.    ds -- \|\(em\|
++.    ds PI \(*p
++.    ds L" ``
++.    ds R" ''
++.    ds C`
++.    ds C'
++'br\}
++.\"
++.\" Escape single quotes in literal strings from groff's Unicode transform.
++.ie \n(.g .ds Aq \(aq
++.el       .ds Aq '
++.\"
++.\" If the F register is turned on, we'll generate index entries on stderr for
++.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
++.\" entries marked with X<> in POD.  Of course, you'll have to process the
++.\" output yourself in some meaningful fashion.
++.\"
++.\" Avoid warning from groff about undefined register 'F'.
++.de IX
++..
++.nr rF 0
++.if \n(.g .if rF .nr rF 1
++.if (\n(rF:(\n(.g==0)) \{
++.    if \nF \{
++.        de IX
++.        tm Index:\\$1\t\\n%\t"\\$2"
++..
++.        if !\nF==2 \{
++.            nr % 0
++.            nr F 2
++.        \}
++.    \}
++.\}
++.rr rF
++.\"
++.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
++.\" Fear.  Run.  Save yourself.  No user-serviceable parts.
++.    \" fudge factors for nroff and troff
++.if n \{\
++.    ds #H 0
++.    ds #V .8m
++.    ds #F .3m
++.    ds #[ \f1
++.    ds #] \fP
++.\}
++.if t \{\
++.    ds #H ((1u-(\\\\n(.fu%2u))*.13m)
++.    ds #V .6m
++.    ds #F 0
++.    ds #[ \&
++.    ds #] \&
++.\}
++.    \" simple accents for nroff and troff
++.if n \{\
++.    ds ' \&
++.    ds ` \&
++.    ds ^ \&
++.    ds , \&
++.    ds ~ ~
++.    ds /
++.\}
++.if t \{\
++.    ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
++.    ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
++.    ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
++.    ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
++.    ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
++.    ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
++.\}
++.    \" troff and (daisy-wheel) nroff accents
++.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
++.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
++.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
++.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
++.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
++.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
++.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
++.ds ae a\h'-(\w'a'u*4/10)'e
++.ds Ae A\h'-(\w'A'u*4/10)'E
++.    \" corrections for vroff
++.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
++.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
++.    \" for low resolution devices (crt and lpr)
++.if \n(.H>23 .if \n(.V>19 \
++\{\
++.    ds : e
++.    ds 8 ss
++.    ds o a
++.    ds d- d\h'-1'\(ga
++.    ds D- D\h'-1'\(hy
++.    ds th \o'bp'
++.    ds Th \o'LP'
++.    ds ae ae
++.    ds Ae AE
++.\}
++.rm #[ #] #H #V #F C
++.\" ========================================================================
++.\"
++.IX Title "PAM_CIFSCREDS 8"
++.TH PAM_CIFSCREDS 8 "2013-12-13" "" ""
++.\" For nroff, turn off justification.  Always turn off hyphenation; it makes
++.\" way too many mistakes in technical documents.
++.if n .ad l
++.nh
++.SH "NAME"
++pam_cifscreds \- PAM module to manage NTLM credentials in kernel keyring
++.SH "SYNOPSIS"
++.IX Header "SYNOPSIS"
++Edit the \s-1PAM\s0 configuration files for the systems that you want to
++automatically register \s-1NTLM\s0 credentials for, e.g. /etc/pam.d/login,
++and modify as follows:
++.PP
++.Vb 5
++\&        ...
++\&        auth       substack     system\-auth
++\&    +++ auth       optional     pam_cifscreds.so
++\&        auth       include      postlogin
++\&        ...
++\&
++\&        ...
++\&        session    include      system\-auth
++\&    +++ session    optional     pam_cifscreds.so domain=DOMAIN
++\&        session    include      postlogin
++\&        ...
++.Ve
++.PP
++Change \s-1DOMAIN\s0 to the name of you Windows domain, or use host= as
++described below.
++.SH "DESCRIPTION"
++.IX Header "DESCRIPTION"
++The \fBpam_cifscreds\fR \s-1PAM\s0 module is a tool for automatically adding
++credentials (username and password) for the purpose of establishing
++sessions in multiuser mounts.
++.PP
++When a cifs filesystem is mounted with the \*(L"multiuser\*(R" option, and does
++not use krb5 authentication, it needs to be able to get the credentials
++for each user from somewhere. The \fBpam_cifscreds\fR module can be used
++to provide these credentials to the kernel automatically at login.
++.PP
++In the session section of the \s-1PAM\s0 configuration file, the module can
++either an \s-1NT\s0 domain name or a list of hostname or addresses.
++.SH "OPTIONS"
++.IX Header "OPTIONS"
++\&\fBpam_cifscreds\fR supports a couple options which can be set in the \s-1PAM\s0
++configuration files.  You must have one (and only one) of domain= or
++host=.
++.IP "\fBdebug\fR" 4
++.IX Item "debug"
++Turns on some extra debug logging.
++.IP "\fBdomain\fR=<\s-1NT\s0 domain name>" 4
++.IX Item "domain=<NT domain name>"
++Credentials will be added for the specified \s-1NT\s0 domain name.
++.IP "\fBhost\fR=<hostname or \s-1IP\s0 address>[,...]" 4
++.IX Item "host=<hostname or IP address>[,...]"
++Credentials will be added for the specified hostnames or \s-1IP\s0 addresses.
++.SH "NOTES"
++.IX Header "NOTES"
++The pam_cifscreds \s-1PAM\s0 module requires a kernel built with support for
++the \fBlogin\fR key type. That key type was added in v3.3 in mainline Linux
++kernels.
++.PP
++Since \fBpam_cifscreds\fR adds keys to the session keyring, it is highly
++recommended that one use \fBpam_keyinit\fR to ensure that a session keyring
++is established at login time.
++.SH "SEE ALSO"
++.IX Header "SEE ALSO"
++\&\fIcifscreds\fR\|(1), \fIpam_keyinit\fR\|(8)
++.SH "AUTHOR"
++.IX Header "AUTHOR"
++The pam_cifscreds \s-1PAM\s0 module was developed by Orion Poplawski
++<orion at nwra.com>.
+diff --git a/pam_cifscreds.pod b/pam_cifscreds.pod
+new file mode 100644
+index 0000000..c032416
+--- /dev/null
++++ b/pam_cifscreds.pod
+@@ -0,0 +1,84 @@
++# turn into a manpage with the following command:
++#
++# pod2man -s 8 -c '' -r '' --stderr pam_cifscreds.pod > pam_cifscreds.8
++#
++
++=head1 NAME
++
++pam_cifscreds - PAM module to manage NTLM credentials in kernel keyring
++
++=head1 SYNOPSIS
++
++Edit the PAM configuration files for the systems that you want to
++automatically register NTLM credentials for, e.g. /etc/pam.d/login,
++and modify as follows:
++
++        ...
++        auth       substack     system-auth
++    +++ auth       optional     pam_cifscreds.so
++        auth       include      postlogin
++        ...
++
++        ...
++        session    include      system-auth
++    +++ session    optional     pam_cifscreds.so domain=DOMAIN
++        session    include      postlogin
++        ...
++
++Change DOMAIN to the name of you Windows domain, or use host= as
++described below.
++
++=head1 DESCRIPTION
++
++The B<pam_cifscreds> PAM module is a tool for automatically adding
++credentials (username and password) for the purpose of establishing
++sessions in multiuser mounts.
++
++When a cifs filesystem is mounted with the "multiuser" option, and does
++not use krb5 authentication, it needs to be able to get the credentials
++for each user from somewhere. The B<pam_cifscreds> module can be used
++to provide these credentials to the kernel automatically at login.
++
++In the session section of the PAM configuration file, the module can
++either an NT domain name or a list of hostname or addresses.
++
++=head1 OPTIONS
++
++B<pam_cifscreds> supports a couple options which can be set in the PAM
++configuration files.  You must have one (and only one) of domain= or
++host=.
++
++=over
++
++=item B<debug>
++
++Turns on some extra debug logging.
++
++=item B<domain>=<NT domain name>
++
++Credentials will be added for the specified NT domain name.
++
++=item B<host>=<hostname or IP address>[,...]
++
++Credentials will be added for the specified hostnames or IP addresses.
++
++=back
++
++=head1 NOTES
++
++The pam_cifscreds PAM module requires a kernel built with support for
++the B<login> key type. That key type was added in v3.3 in mainline Linux
++kernels.
++
++Since B<pam_cifscreds> adds keys to the session keyring, it is highly
++recommended that one use B<pam_keyinit> to ensure that a session keyring
++is established at login time.
++
++=head1 SEE ALSO
++
++cifscreds(1), pam_keyinit(8)
++
++=head1 AUTHOR
++
++The pam_cifscreds PAM module was developed by Orion Poplawski
++<orion at nwra.com>.
+-- 
+1.8.4.2
+
diff --git a/cifs-utils.spec b/cifs-utils.spec
index 37ee458..88a7db7 100644
--- a/cifs-utils.spec
+++ b/cifs-utils.spec
@@ -3,7 +3,7 @@
 
 Name:            cifs-utils
 Version:         6.2
-Release:         4%{pre_release}%{?dist}
+Release:         5%{pre_release}%{?dist}
 Summary:         Utilities for mounting and managing CIFS mounts
 
 Group:           System Environment/Daemons
@@ -11,7 +11,7 @@ License:         GPLv3
 URL:             http://linux-cifs.samba.org/cifs-utils/
 BuildRoot:       %{_tmppath}/%{name}-%{version}%{pre_release}-%{release}-root-%(%{__id_u} -n)
 
-BuildRequires:   libcap-ng-devel libtalloc-devel krb5-devel keyutils-libs-devel autoconf automake libwbclient-devel
+BuildRequires:   libcap-ng-devel libtalloc-devel krb5-devel keyutils-libs-devel autoconf automake libwbclient-devel pam-devel
 
 Requires:        keyutils
 Requires(post):  /usr/sbin/alternatives
@@ -23,7 +23,12 @@ Patch2:          0002-getcifsacl-remove-some-dead-code.patch
 Patch3:          0003-asn1-remove-some-usused-functions.patch
 Patch4:          0004-data_blob-clean-out-unused-functions.patch
 Patch5:          0005-mount.cifs-fix-bad-free-of-string-returned-by-dirnam.patch
-Patch6:		 0001-asn1-fix-use-after-free-in-asn1_write.patch
+Patch6:          0001-asn1-fix-use-after-free-in-asn1_write.patch
+Patch7:          0001-autoconf-fix-link-of-libwbclient.patch
+Patch8:          0002-cifscreds-create-PAM-module-to-insert-credentials-at.patch
+Patch9:          0003-cifscreds-fix-up-some-whitespace-typos-and-build-war.patch
+Patch10:         0004-manpage-add-pam_cifscreds.8-man-page.patch
+
 
 %description
 The SMB/CIFS protocol is a standard file sharing protocol widely deployed
@@ -50,6 +55,10 @@ necessary for building ID mapping plugins for cifs-utils.
 %patch4 -p1
 %patch5 -p1
 %patch6 -p1
+%patch7 -p1
+%patch8 -p1
+%patch9 -p1
+%patch10 -p1
 
 %build
 %configure --prefix=/usr ROOTSBINDIR=%{_sbindir}
@@ -76,6 +85,7 @@ rm -rf %{buildroot}
 %{_sbindir}/cifs.upcall
 %{_sbindir}/cifs.idmap
 %{_libdir}/%{name}/idmapwb.so
+%{_libdir}/security/pam_cifscreds.so
 %{_mandir}/man1/getcifsacl.1.gz
 %{_mandir}/man1/setcifsacl.1.gz
 %{_mandir}/man1/cifscreds.1.gz
@@ -83,6 +93,7 @@ rm -rf %{buildroot}
 %{_mandir}/man8/cifs.idmap.8.gz
 %{_mandir}/man8/mount.cifs.8.gz
 %{_mandir}/man8/idmapwb.8.gz
+%{_mandir}/man8/pam_cifscreds.8.gz
 %ghost %{_sysconfdir}/cifs-utils/idmap-plugin
 %config(noreplace) %{_sysconfdir}/request-key.d/cifs.idmap.conf
 %config(noreplace) %{_sysconfdir}/request-key.d/cifs.spnego.conf
@@ -99,6 +110,10 @@ fi
 %{_includedir}/cifsidmap.h
 
 %changelog
+* Fri Dec 13 2013 Jeff Layton <jlayton at redhat.com> 6.2-5
+- fix linking of wbclient
+- add pam_cifscreds module and manpage
+
 * Mon Oct 14 2013 Jeff Layton <jlayton at redhat.com> 6.2-4
 - fix use-after-free in asn1_write
 


More information about the scm-commits mailing list