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 +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 +--- + 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 +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 +--- + 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 + #include + #include ++#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@samba.org) ++ * Copyright (C) 2010 Igor Druzhinin (jaxbrigs@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 . ++ */ ++ ++#include ++#include ++#include ++#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@samba.org) ++ * Copyright (C) 2010 Igor Druzhinin (jaxbrigs@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 . ++ */ ++ ++#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 ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++/* ++#include ++#include ++#include ++*/ ++ ++#include ++ ++#include ++#include ++#include ++ ++#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 +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 +--- + 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 +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 +--- + 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=" ++Credentials will be added for the specified \s-1NT\s0 domain name. ++.IP "\fBhost\fR=[,...]" 4 ++.IX Item "host=[,...]" ++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 ++. +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 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 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 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 ++ ++Turns on some extra debug logging. ++ ++=item B= ++ ++Credentials will be added for the specified NT domain name. ++ ++=item B=[,...] ++ ++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 key type. That key type was added in v3.3 in mainline Linux ++kernels. ++ ++Since B adds keys to the session keyring, it is highly ++recommended that one use B 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 ++. +-- +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 6.2-5 +- fix linking of wbclient +- add pam_cifscreds module and manpage + * Mon Oct 14 2013 Jeff Layton 6.2-4 - fix use-after-free in asn1_write