Группа :: Система/Основа
Пакет: pam_pkcs11
Главная Изменения Спек Патчи Sources Загрузить Gear Bugs and FR Repocop
Патч: pam_pkcs11-0.6.9-config-control.patch
Скачать
Скачать
configure.ac | 10 +
etc/Makefile.am | 14 ++
etc/control.d/Makefile.am | 3 +
etc/control.d/pam-pkcs11-mapping.in | 10 +
etc/control.d/pam-pkcs11-module.in | 202 +++++++++++++++++
etc/control.d/pam-pkcs11-profile.in | 325 +++++++++++++++++++++++++++
etc/control.d/pkcs11-events.in | 209 +++++++++++++++++
etc/mapping.profiles/cert.in | 13 ++
etc/mapping.profiles/cn.in | 12 +
etc/mapping.profiles/mail.in | 16 ++
etc/mapping.profiles/subject.in | 12 +
etc/modules.avail/aladdin.in | 10 +
etc/pam.d_login.example.in | 2 +-
etc/pam_pkcs11.conf.example.in | 59 +++--
etc/profiles/opensc | 9 +
etc/system-auth-pkcs11_strict | 11 +
etc/system-auth-use_first_pass-pkcs11_strict | 6 +
17 files changed, 899 insertions(+), 24 deletions(-)
diff --git a/configure.ac b/configure.ac
index 2821092..69ae387 100644
--- a/configure.ac
+++ b/configure.ac
@@ -258,6 +258,16 @@ doc/doxygen.conf
etc/Makefile
etc/pam.d_login.example
etc/pam_pkcs11.conf.example
+etc/control.d/Makefile
+etc/control.d/pam-pkcs11-module
+etc/control.d/pam-pkcs11-profile
+etc/control.d/pam-pkcs11-mapping
+etc/control.d/pkcs11-events
+etc/mapping.profiles/cn
+etc/mapping.profiles/mail
+etc/mapping.profiles/subject
+etc/mapping.profiles/cert
+etc/modules.avail/aladdin
src/Makefile
src/scconf/Makefile
src/common/Makefile
diff --git a/etc/Makefile.am b/etc/Makefile.am
index fc5e35b..fd3f7bc 100644
--- a/etc/Makefile.am
+++ b/etc/Makefile.am
@@ -1,6 +1,7 @@
# Process this file with automake to create Makefile.in
MAINTAINERCLEANFILES = Makefile.in
+SUBDIRS = control.d
TO_INSTALL = \
subject_mapping.example \
@@ -16,3 +17,16 @@ EXTRA_DIST = $(TO_INSTALL) \
doc_DATA = $(TO_INSTALL) \
pam_pkcs11.conf.example \
pam.d_login.example
+
+pamdir = $(sysconfdir)/pam.d
+pam_DATA = system-auth-pkcs11_strict system-auth-use_first_pass-pkcs11_strict
+
+modulesdir = $(confdir)/modules.avail
+modules_DATA = modules.avail/aladdin
+
+profilesdir = $(confdir)/profiles
+profiles_DATA = profiles/opensc
+
+mprofilesdir = $(confdir)/mapping.profiles
+mprofiles_DATA = mapping.profiles/cn mapping.profiles/mail \
+ mapping.profiles/subject mapping.profiles/cert
diff --git a/etc/control.d/Makefile.am b/etc/control.d/Makefile.am
new file mode 100644
index 0000000..c70e93c
--- /dev/null
+++ b/etc/control.d/Makefile.am
@@ -0,0 +1,3 @@
+controldir = $(sysconfdir)/control.d/facilities
+control_SCRIPTS = pam-pkcs11-module pam-pkcs11-profile pam-pkcs11-mapping \
+ pkcs11-events
diff --git a/etc/control.d/pam-pkcs11-mapping.in b/etc/control.d/pam-pkcs11-mapping.in
new file mode 100755
index 0000000..b3cee4f
--- /dev/null
+++ b/etc/control.d/pam-pkcs11-mapping.in
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+. /etc/control.d/functions
+
+CONFIG="${CONFIG:-@confdir@/pam_pkcs11.conf}"
+MAPPING_PROFILES_DIR="${MAPPING_PROFILES_DIR:-@confdir@/mapping.profiles}"
+
+export PROFILES_DIR="$MAPPING_PROFILES_DIR"
+export SUMMARY="${SUMMARY:-PKCS11 username mapping profile selector}"
+"${0%/*}/pam-pkcs11-profile" "$@"
diff --git a/etc/control.d/pam-pkcs11-module.in b/etc/control.d/pam-pkcs11-module.in
new file mode 100755
index 0000000..8efdded
--- /dev/null
+++ b/etc/control.d/pam-pkcs11-module.in
@@ -0,0 +1,202 @@
+#!/bin/sh
+
+. /etc/control.d/functions
+
+CONFIG="${CONFIG:-@confdir@/pam_pkcs11.conf}"
+CONFIG_MGR="${CONFIG_MGR:-@confdir@/pkcs11_eventmgr.conf}"
+MODULES_DIR="${MODULES_DIR:-@confdir@/modules.avail}"
+
+new_summary "PKCS11 module selector"
+
+list_modules() {
+ local conf="${1:-$CONFIG}"
+ sed -n -e '/^[[:space:]]*pkcs11_module[[:space:]]\+[^{]\+[[:space:]]*{/,/}/ {
+ /^[[:space:]]*pkcs11_module[[:space:]]\+/ {
+ s/^[[:space:]]*pkcs11_module[[:space:]]\+//;
+ s/[[:space:]]*{.*$/:/;
+ p;
+ }
+ /^[[:space:]]*module[[:space:]]*=/ {
+ s/^[[:space:]]*module[[:space:]]*=[[:space:]]*"\?\([^;]\+\)"\?.*$/-- path:\1/;
+ p;
+ }
+ /^[[:space:]]*description[[:space:]]*=/ {
+ s/^[[:space:]]*description[[:space:]]*=[[:space:]]*"\?\([^";]\+\)"\?.*$/-- desc:\1/;
+ p;
+ }
+ }' -- "$conf"
+}
+
+for_each_module() {
+ local modules="$1"; shift
+
+ [ -s "$modules" ] || return 0
+
+ local func="$1"; shift
+ local module_name=
+ local module_path=
+ local module_desc=
+
+ while read ln; do
+ case "$ln" in
+ --\ path:*)
+ module_path="${ln##*path:}"
+ ;;
+ --\ desc:*)
+ module_desc="${ln##*desc:}"
+ ;;
+ *:)
+ if [ -n "$module_name" ]; then
+ if [ -z "$module_desc" ]; then
+ module_desc="$(echo "$module_name" | tr '[:lower:]' '[:upper:]') module"
+ fi
+ "$func" "$module_name" "$module_path" "$module_desc" "$@"
+ fi
+ module_name="${ln%:}"; module_path=; module_desc=
+ ;;
+ esac
+ done <"$modules"
+
+ if [ -n "$module_name" ]; then
+ if [ -z "$module_desc" ]; then
+ module_desc="$(echo "$module_name" | tr '[:lower:]' '[:upper:]') module"
+ fi
+ "$func" "$module_name" "$module_path" "$module_desc" "$@"
+ fi
+}
+
+register_module() {
+ new_help "$1" "$3"
+}
+
+check_name() {
+ if [ "$1" = "$4" ]; then
+ echo "$1"
+ fi
+}
+
+register_new_module() {
+ local already="$(for_each_module "$4" check_name "$1")"
+ if [ -z "$already" ]; then
+ new_help "$1" "$3"
+ fi
+}
+
+read_selected() {
+ sed -n -e '/^[[:space:]]*pam_pkcs11[[:space:]]*{/,$ {
+ /^[[:space:]]*pam_pkcs11[[:space:]]*{/ d;
+ /{/,/}/ d;
+ /}/ q;
+ /^[[:space:]]*use_pkcs11_module[[:space:]]*=/ {
+ s/^[[:space:]]*use_pkcs11_module[[:space:]]*=[[:space:]]*//;
+ s/;.*$//;
+ p; q;
+ }
+ }' -- "$CONFIG"
+}
+
+get_path() {
+ if [ "$1" = "$4" ]; then
+ echo "$2"
+ fi
+}
+
+add_to_config() {
+ local module="$1"; shift
+ local newmod="$workdir/newmod"
+
+ sed -e 's/^.*$/ &/' "${MODULES_DIR%/}/$module" >"$newmod"
+ echo "}" >>"$newmod"
+
+ sed -i -e "/^[[:space:]]*pam_pkcs11[[:space:]]*{/,$ {
+ /^[[:space:]]*pam_pkcs11[[:space:]]*{/ { p; d }
+ /{/,/}/ { p; d }
+ /}/ {
+ r $newmod
+ ; d
+ }
+ /}/,\$ { p; d }
+ }" -- "$CONFIG"
+}
+
+select_module() {
+ local module="$1"; shift
+ local module_path=
+
+ module_path="$(for_each_module "$workdir/configured" get_path "$module")"
+ if [ -z "$module_path" ]; then
+ module_path="$(for_each_module "$workdir/available" get_path "$module")"
+ if [ -n "$module_path" ]; then
+ # Add module to the main config
+ add_to_config "$module"
+ fi
+ fi
+ if [ -z "$module_path" ]; then
+ echo "ERROR: Module path isn't set!" >&2
+ return 1
+ fi
+
+ sed -i -e "/^[[:space:]]*pam_pkcs11[[:space:]]*{/,\$ {
+ /^[[:space:]]*pam_pkcs11[[:space:]]*{/ { p; d; }
+ /{/,/}/ { p; d }
+ /}/,\$ { p; d }
+ /^[[:space:]]*use_pkcs11_module[[:space:]]*=/ {
+ s/^[[:space:]]*use_pkcs11_module[[:space:]]*=.*\$/ use_pkcs11_module = $module;/;
+ }
+ }" -- "$CONFIG"
+
+ # Skip the event manager configuration if its conffile is missing
+ [ -e "$CONFIG_MGR" ] || return 0
+
+ module_path="$(echo "$module_path" | sed -e 's,/,\\/,g')"
+ sed -i -e "/^[[:space:]]*pkcs11_eventmgr[[:space:]]*{/,\$ {
+ /^[[:space:]]*pkcs11_eventmgr[[:space:]]*{/ { p; d; }
+ /{/,/}/ { p; d }
+ /}/,\$ { p; d }
+ /^[[:space:]]*pkcs11_module[[:space:]]*=/ {
+ s/^[[:space:]]*pkcs11_module[[:space:]]*=.*\$/\\tpkcs11_module = $module_path;/;
+ }
+ }" -- "$CONFIG_MGR"
+}
+
+
+## Main
+
+REQUEST="$*"
+
+workdir="$(mktemp -d --tmpdir "${0##*/}.XXXX")"
+trap "rm -rf \"$workdir\"" EXIT
+
+list_modules >"$workdir/configured"
+if [ -d "$MODULES_DIR" ]; then
+ ls -1 "$MODULES_DIR" | while read conf; do
+ case "$conf" in
+ *~|.*|*.rpmnew|*.rpmold)
+ ;;
+ *)
+ list_modules "${MODULES_DIR%/}/$conf" >>"$workdir/available"
+ ;;
+ esac
+ done
+fi
+
+for_each_module "$workdir/configured" register_module
+for_each_module "$workdir/available" register_new_module "$workdir/configured"
+
+case "$REQUEST" in
+ help|'help '*)
+ control_help "${REQUEST#help}"
+ ;;
+ list)
+ control_list
+ ;;
+ summary)
+ control_summary
+ ;;
+ status)
+ read_selected
+ ;;
+ *)
+ select_module "$REQUEST"
+ ;;
+esac
diff --git a/etc/control.d/pam-pkcs11-profile.in b/etc/control.d/pam-pkcs11-profile.in
new file mode 100755
index 0000000..7215f06
--- /dev/null
+++ b/etc/control.d/pam-pkcs11-profile.in
@@ -0,0 +1,325 @@
+#!/bin/sh
+
+. /etc/control.d/functions
+
+CONFIG="${CONFIG:-@confdir@/pam_pkcs11.conf}"
+PROFILES_DIR="${PROFILES_DIR:-@confdir@/profiles}"
+SUMMARY="${SUMMARY:-PKCS11 profile selector}"
+
+new_summary "$SUMMARY"
+
+read_desc() {
+ local profile="$1"; shift
+ sed -n -e '/^#/ {
+ s/^#[[:space:]]*//;
+ p;
+ q
+ }' -- "$profile"
+}
+
+_read_values() {
+ local profile="$1"; shift
+ sed -n -e '/^[[:space:]]*pam_pkcs11[[:space:]]*{/,/}/ {
+ /^[[:space:]]*pam_pkcs11[[:space:]]*{/ d;
+ /^[[:space:]]*[^[:space:]{]*[^{]*[^[:space:]{]\+[[:space:]]*{/,/}/ {
+ /^[[:space:]]*[^[:space:]{]*[^{]*[^[:space:]{]\+[[:space:]]*{/ {
+ s/^[[:space:]]*\([^[:space:]{]*[^{]*[^[:space:]{]\+\)[[:space:]]*{.*$/ subname = \1;/;
+ s/"/\\"/g;
+ s/= \(.*\);$/= "\1";/;
+ p; d
+ }
+ /^[[:space:]]*\([^=[:space:]]\+\)[[:space:]]*=[[:space:]]*[^;]\+;/ {
+ s/^[[:space:]]*\([^=[:space:]]\+\)[[:space:]]*=[[:space:]]*\(.*[^[:space:]]\)[[:space:]]*;$/ subvalues[subname][\1] = \2;/;
+ s/"/\\"/g;
+ s/subvalues\[subname\]\[\(.*\)\] = \(.*\);$/subvalues[subname]["\1"] = "\2";/;
+ p; d
+ }
+ /}/ d
+ }
+ /{/,/}/ d;
+ /^[[:space:]]*[^=[:space:]]\+[[:space:]]*=[[:space:]]*[^;]\+;/ {
+ s/^[[:space:]]*\([^=[:space:]]\+\)[[:space:]]*=[[:space:]]*\([^;]\+\);.*$/ values[\1] = \2;/;
+ s/"/\\"/g;
+ s/values\[\(.*\)\] = \(.*\);$/values["\1"] = "\2";/;
+ p; d
+ }
+ }' -- "$profile"
+}
+
+make_parser_begin() {
+ local profile="$1"; shift
+ local name="${profile##*/}"; shift
+ case "$name" in
+ *.*)
+ name="$name"
+ ;;
+ *)
+ name="$name.begin.awk"
+ ;;
+ esac
+
+ cat <<EOF >"$workdir/$name"
+BEGIN {
+ pam_pkcs11 = 0;
+ subconfig = 0;
+EOF
+
+ _read_values "$profile" >>"$workdir/$name"
+
+ cat <<EOF >>"$workdir/$name"
+}
+EOF
+}
+
+make_parser() {
+ local name="${1:-.parser.awk}"
+ cat <<EOF >"$workdir/$name"
+/^[[:space:]]*#/ {
+ if (OUT) { print; }
+ next;
+}
+
+/^[[:space:]]*[^[:space:]{]*[^{]*[^[:space:]{]+[[:space:]]*{/ {
+ if (\$1 == "pam_pkcs11" && \$2 == "{") {
+ pam_pkcs11 = 1;
+ } else if (pam_pkcs11) {
+ subconfig = 1;
+ subname = \$1;
+ for (i = 2; i < NF && \$i != "{"; i++) {
+ subname = subname " " \$i;
+ }
+ }
+ if (OUT) { print; }
+ next;
+}
+
+/^[[:space:]]*[^=[:space:]]+[[:space:]]*=[[:space:]]*[^;]+;/ {
+ value = \$0;
+ if (CMP) {
+ sub(/^[^=]+=[[:space:]]*/, "", value);
+ sub(/[[:space:]]*;([[:space:]#]+.*)?\$/, "", value);
+ }
+ if (subconfig) {
+ if (subname in subvalues && \$1 in subvalues[subname]) {
+ if (OUT) {
+ print " " \$1 " = " subvalues[subname][\$1] ";";
+ }
+ if (!CMP || value == subvalues[subname][\$1]) {
+ delete subvalues[subname][\$1];
+ }
+ if (!CMP) {
+ existing[subname] = 1;
+ }
+ } else {
+ if (OUT) { print; }
+ }
+ } else {
+ if (\$1 in values) {
+ if (OUT) {
+ print " " \$1 " = " values[\$1] ";";
+ }
+ if (!CMP || value == values[\$1]) {
+ delete values[\$1];
+ }
+ } else {
+ if (OUT) { print; }
+ }
+ }
+ next;
+}
+
+/}/ {
+ if (subconfig) {
+ subconfig = 0;
+ if (subname in subvalues) {
+ for (key in subvalues[subname]) {
+ if (OUT) {
+ print " " key " = " subvalues[subname][key] ";";
+ }
+ if (!CMP) {
+ delete subvalues[subname][key];
+ }
+ }
+ if (!CMP) {
+ existing[subname] = 1;
+ }
+ }
+ } else if (pam_pkcs11) {
+ pam_pkcs11 = 0;
+ for (key in values) {
+ if (OUT) {
+ print " " key " = " values[key] ";";
+ }
+ if (!CMP) {
+ delete values[key];
+ }
+ }
+ for (subname in subvalues) {
+ if (!(subname in existing)) {
+ if (OUT) {
+ print "";
+ print " " subname " {";
+ }
+ for (key in subvalues[subname]) {
+ if (OUT) {
+ print " " key " = " subvalues[subname][key] ";";
+ }
+ if (!CMP) {
+ delete subvalues[subname][key];
+ }
+ }
+ }
+ if (!CMP) {
+ delete subvalues[subname];
+ }
+ }
+ }
+ if (OUT) { print; }
+ next;
+}
+
+{ if (OUT) { print; } }
+
+END {
+ value_count = 0;
+ for (key in values) { value_count++ };
+ subvalue_count = 0;
+ for (subname in subvalues) {
+ for (key in subvalues[subname]) {
+ subvalue_count++;
+ }
+ }
+ diff = 0;
+ if (value_count > 0 || subvalue_count > 0) {
+ diff = 1;
+ print "pam_pkcs11 {";
+ for (key in values) {
+ print " " key " = " values[key] ";";
+ }
+ for (subname in subvalues) {
+ subvalue_count = 0;
+ for (key in subvalues[subname]) {
+ subvalue_count++;
+ }
+ if (subvalue_count > 0) {
+ print "";
+ print " " subname " {";
+ for (key in subvalues[subname]) {
+ print " " key " = " subvalues[subname][key] ";";
+ }
+ print " }";
+ }
+ }
+ print "}";
+ }
+ if (diff) {
+ exit 1;
+ }
+}
+EOF
+}
+
+read_current() {
+ local name=
+
+ make_parser
+ for_each_profile make_parser_begin
+
+ for f in $workdir/*.begin.awk; do
+ name="${f##*/}"; name="${name%.begin.awk}"
+ if awk -f "$f" -f "$workdir/.parser.awk" -v 'CMP=1' "$CONFIG" 1>/dev/null 2>&1; then
+ echo "$name"
+ return 0
+ fi
+ done
+
+ echo 'custom'
+}
+
+update() {
+ local profile="$1"; shift
+ local name="${profile##*/}"
+ make_parser
+ make_parser_begin "$profile"
+ awk -f "$workdir/$name.begin.awk" -f "$workdir/.parser.awk" \
+ -v 'OUT=1' -- "$CONFIG" \
+ >"$workdir/.config.updated" && \
+ mv "$workdir/.config.updated" "$CONFIG"
+}
+
+use_profile() {
+ local profile="${PROFILES_DIR%/}/$1"; shift
+ if [ -e "$profile" ]; then
+ update "$profile" && \
+ use_module "$profile"
+ else
+ echo "ERROR: Profile not found: $1" >&2
+ return 1
+ fi
+}
+
+read_module() {
+ local profile="$1"; shift
+ sed -n -e '/^[[:space:]]*use_pkcs11_module[[:space:]]*=/ {
+ s/^[[:space:]]*use_pkcs11_module[[:space:]]*=[[:space:]]*//;
+ s/;.*$//;
+ p;
+ q
+ }' -- "$profile"
+}
+
+use_module() {
+ local module="$(read_module "$1")"
+ if [ -n "$module" ]; then
+ if ! control pam-pkcs11-module "$module"; then
+ echo "Error selecting module: ${module##*/}" >&2
+ return 1
+ fi
+ fi
+}
+
+for_each_profile() {
+ local func="$1"; shift
+ if [ -d $PROFILES_DIR ]; then
+ for p in ${PROFILES_DIR%/}/*; do
+ case "${p##*/}" in
+ *~|.*|*.rpmnew|*.rpmold)
+ ;;
+ *)
+ "$func" "$p" "$@"
+ ;;
+ esac
+ done
+ fi
+}
+
+register_profile() {
+ new_help "${1##*/}" "$(read_desc "$1")"
+}
+
+## Main
+
+REQUEST="$*"
+
+workdir="$(mktemp -d --tmpdir "${0##*/}.XXXX")"
+trap "rm -rf \"$workdir\"" EXIT
+
+for_each_profile register_profile
+
+case "$REQUEST" in
+ help|'help '*)
+ control_help "${REQUEST#help}"
+ ;;
+ list)
+ control_list
+ ;;
+ summary)
+ control_summary
+ ;;
+ status)
+ read_current
+ ;;
+ *)
+ use_profile "$REQUEST"
+ ;;
+esac
diff --git a/etc/control.d/pkcs11-events.in b/etc/control.d/pkcs11-events.in
new file mode 100755
index 0000000..eb3a5a6
--- /dev/null
+++ b/etc/control.d/pkcs11-events.in
@@ -0,0 +1,209 @@
+#!/bin/sh
+
+. /etc/control.d/functions
+. alterator-service-functions
+
+CONFIG="${CONFIG:-@confdir@/pkcs11_eventmgr.conf}"
+
+CA_INSERT="/usr/bin/card-inserted"
+CA_REMOVE="/usr/bin/card-removed"
+SERVICE="pkcs11-eventmgr"
+
+new_summary "PKCS11 event actions"
+new_help 'other' "User specified or package default actions"
+new_help 'disabled' "Event monitring is disabled"
+new_help 'card_actions' "Actions handled by the $CA_INSERT and $CA_REMOVE alternatives"
+
+read_event_action() {
+ local ev="$1"; shift
+ sed -n -e "/^[[:space:]]*event[[:space:]]\\+$ev[[:space:]]*{/,/^[[:space:]]*}[#[:space:]]*\$/ {
+ /^[[:space:]]*action[[:space:]]*=/,/;[[:space:]]*\$/ {
+ H;
+ /;[[:space:]]*\$/! d;
+ g;
+ s/^[[:space:]]*action[[:space:]]*=[[:space:]]*//;
+ s/\\n/ /g;
+ s/\",[[:space:]]\\+\"/\", \"/g;
+ s/\",[[:space:]]\\+;/\",;/;
+ s/;[[:space:]]*\$//p;
+ s/^.*\$//; h;
+ }
+ }" -- "$CONFIG"
+}
+
+comment_event_action() {
+ local ev="$1"; shift
+ sed -i -e "/^[[:space:]]*event[[:space:]]\\+$ev[[:space:]]*{/,/^[[:space:]]*}[#[:space:]]*\$/ {
+ /^[[:space:]]*\\(#[[:space:]]*\\)*action[[:space:]]*=/,/;[[:space:]]*\$/ {
+ /^[[:space:]]*}[#[:space:]]*\$/ { p; d };
+ s/^[#[:space:]]*/\\t\\t/;
+ H;
+ /;[[:space:]]*\$/! d;
+ g;
+ s/^[[:space:]]*\\(#[[:space:]]*\\)*action[[:space:]]*=[[:space:]]*/\\t\\t#action = /;
+ s/\\n/ /g;
+ s/\",[[:space:]]\\+\"/\", \"/g;
+ s/\",[[:space:]]\\+;/\",;/;
+ x; s/^.*\$//; x;
+ }
+ }" -- "$CONFIG"
+}
+
+add_event_action() {
+ local ev="$1"; shift
+ local act="$1"; shift
+ act="$(echo "$act" | sed -e 's,/,\\/,g')"
+ comment_event_action "$ev"
+ sed -i -e "/^[[:space:]]*event[[:space:]]\\+$ev[[:space:]]*{/,/^[[:space:]]*}[#[:space:]]*\$/ {
+ /^[[:space:]]*}[#[:space:]]*\$/ {
+ s/^.*}\\([^}]*\\)\$/\\t\\taction = \"$act\";\\n\\t}\\1/;
+ }
+ }" -- "$CONFIG"
+}
+
+delete_event_action() {
+ local ev="$1"; shift
+ comment_event_action "$ev"
+ sed -i -e "/^[[:space:]]*event[[:space:]]\\+$ev[[:space:]]*{/,/^[[:space:]]*}[#[:space:]]*\$/ {
+ /^[[:space:]]*\\#action[[:space:]]*=/ {
+ x; /^.\\+\$/ p; d;
+ }
+ }" -- "$CONFIG"
+}
+
+restore_event_action() {
+ local ev="$1"; shift
+ comment_event_action "$ev"
+ sed -i -e "/^[[:space:]]*event[[:space:]]\\+$ev[[:space:]]*{/,/^[[:space:]]*}[#[:space:]]*\$/ {
+ /^[[:space:]]*\\#action[[:space:]]*=/ {
+ x; /^.\\+\$/ p; d;
+ }
+ /^[[:space:]]*}[#[:space:]]*\$/ {
+ x; s/#action/action/p; x;
+ }
+ }" -- "$CONFIG"
+}
+
+## Main
+
+REQUEST="$*"
+
+action_command() {
+ local act="$1"; shift
+ act="${act#\"}"
+ act="${act%%\",*}"
+ act="${act%\"}"
+ act="${act%% *}"
+ echo "$act"
+}
+
+read_oninsert() {
+ oninsert="$(action_command "$(read_event_action 'card_insert')")"
+ if [ -z "$oninsert" ]; then
+ return 1
+ elif [ ! -x "$oninsert" ]; then
+ echo "Warning: $oninsert is configured for 'insert' but isn't available!" >&2
+ return 2
+ fi
+}
+
+read_onremove() {
+ onremove="$(action_command "$(read_event_action 'card_remove')")"
+ if [ -z "$onremove" ]; then
+ return 1
+ elif [ ! -x "$onremove" ]; then
+ echo "Warning: $onremove is configured for 'remove' but isn't available!" >&2
+ return 2
+ fi
+}
+
+is_enabled() {
+ if sd_service_exists "$SERVICE" && \
+ ! sd_service_control "$SERVICE" 'is-enabled'
+ then
+ return 1
+ fi
+
+ if sysv_service_exists "$SERVICE" && \
+ ! sysv_service_control "$SERVICE" 'is-enabled'
+ then
+ return 1
+ fi
+
+ return 0
+}
+
+ret=0; startstop=
+
+case "$REQUEST" in
+ help|'help '*)
+ control_help "${REQUEST#help}"
+ ;;
+ list)
+ control_list
+ ;;
+ summary)
+ control_summary
+ ;;
+ status)
+ if is_enabled; then
+ read_oninsert ||:
+ read_onremove ||:
+ if [ "$oninsert" = "$CA_INSERT" -a "$onremove" = "$CA_REMOVE" ]
+ then
+ echo "card_actions"
+ else
+ echo "other"
+ fi
+ else
+ echo "disabled"
+ fi
+ ;;
+ card_actions)
+ startstop="$SERVICE"
+ if [ -x "$CA_INSERT" ]; then
+ if [ "$oninsert" != "$CA_INSERT" ]; then
+ add_event_action 'card_insert' "$CA_INSERT"
+ fi
+ else
+ echo "Error: $CA_INSERT is not available!" >&2
+ ret=1
+ fi
+ if [ -x "$CA_REMOVE" ]; then
+ if [ "$onremove" != "$CA_REMOVE" ]; then
+ add_event_action 'card_remove' "$CA_REMOVE"
+ fi
+ else
+ echo "Error: $CA_REMOVE is not available!" >&2
+ ret=1
+ fi
+ ;;
+ other)
+ startstop="$SERVICE"
+ if [ "$oninsert" != "$CA_INSERT" ]; then
+ delete_event_action 'card_insert'
+ restore_event_action 'card_insert'
+ read_oninsert || ret=$?
+ fi
+ if [ "$onremove" != "$CA_INSERT" ]; then
+ delete_event_action 'card_remove'
+ restore_event_action 'card_remove'
+ read_onremove || ret=$?
+ fi
+ ;;
+ disabled)
+ service_control "$SERVICE" 'disable'
+ ;;
+esac
+
+if [ -n "$startstop" ]; then
+ sact=
+ if [ $ret -eq 0 ]; then
+ sact='enable'
+ else
+ sact='disable'
+ fi
+ for name in $startstop; do
+ service_control "$name" "$sact"
+ done
+fi
diff --git a/etc/mapping.profiles/cert.in b/etc/mapping.profiles/cert.in
new file mode 100644
index 0000000..45d745a
--- /dev/null
+++ b/etc/mapping.profiles/cert.in
@@ -0,0 +1,13 @@
+# Map by the certificate itself
+#
+pam_pkcs11 {
+ use_mappers = openssh, opensc;
+ mapper openssh {
+ debug = false;
+ module = @libdir@/pam_pkcs11/openssh_mapper.so;
+ }
+ mapper opensc {
+ debug = false;
+ module = @libdir@/pam_pkcs11/opensc_mapper.so;
+ }
+}
diff --git a/etc/mapping.profiles/cn.in b/etc/mapping.profiles/cn.in
new file mode 100644
index 0000000..200a9f3
--- /dev/null
+++ b/etc/mapping.profiles/cn.in
@@ -0,0 +1,12 @@
+# Map the CN (common name) to user name
+#
+pam_pkcs11 {
+ use_mappers = cn;
+ mapper cn {
+ debug = false;
+ module = internal;
+ ignorecase = true;
+ # mapfile = file://@confdir@/cn_map;
+ mapfile = "none";
+ }
+}
diff --git a/etc/mapping.profiles/mail.in b/etc/mapping.profiles/mail.in
new file mode 100644
index 0000000..640c77c
--- /dev/null
+++ b/etc/mapping.profiles/mail.in
@@ -0,0 +1,16 @@
+# Map the email address to user name
+#
+pam_pkcs11 {
+ use_mappers = mail;
+ mapper mail {
+ debug = false;
+ module = internal;
+ # mapfile = file://@confdir@/mail_mapping;
+ mapfile = "none";
+ # Some certs store email in uppercase. take care on this
+ ignorecase = true;
+ # Also check that host matches mx domain
+ # when using mapfile this feature is ignored
+ ignoredomain = false;
+ }
+}
diff --git a/etc/mapping.profiles/subject.in b/etc/mapping.profiles/subject.in
new file mode 100644
index 0000000..a673cd6
--- /dev/null
+++ b/etc/mapping.profiles/subject.in
@@ -0,0 +1,12 @@
+# Map the cert. subject to user name
+#
+pam_pkcs11 {
+ use_mappers = subject;
+ mapper subject {
+ debug = false;
+ module = internal;
+ ignorecase = false;
+ # mapfile = file://@confdir@/subject_mapping;
+ mapfile = "none";
+ }
+}
diff --git a/etc/modules.avail/aladdin.in b/etc/modules.avail/aladdin.in
new file mode 100644
index 0000000..b5e6a1e
--- /dev/null
+++ b/etc/modules.avail/aladdin.in
@@ -0,0 +1,10 @@
+# Aladdin eTokenPRO 32
+pkcs11_module etoken {
+ module = /usr/local/lib/libetpkcs11.so
+ description = "Aladdin eTokenPRO-32";
+ slot_num = 0;
+ support_threads = true;
+ ca_dir = @confdir@/cacerts;
+ crl_dir = @confdir@/crls;
+ cert_policy = ca,signature;
+}
diff --git a/etc/pam.d_login.example.in b/etc/pam.d_login.example.in
index 35493e8..8edb288 100644
--- a/etc/pam.d_login.example.in
+++ b/etc/pam.d_login.example.in
@@ -1,7 +1,7 @@
#%PAM-1.0
auth sufficient pam_pkcs11.so nullok try_first_pass \
pkcs11_module=@libdir@/pkcs11/opensc-pkcs11.so \
- ca_dir=/etc/pam_pkcs11 crl_dir=/etc/pam_pkcs11 cert_policy=none
+ ca_dir=@confdir*/cacerts crl_dir=@confdir@/crls cert_policy=none
auth required pam_securetty.so
auth required pam_stack.so service=system-auth
auth required pam_nologin.so
diff --git a/etc/pam_pkcs11.conf.example.in b/etc/pam_pkcs11.conf.example.in
index 648ec7a..294515a 100644
--- a/etc/pam_pkcs11.conf.example.in
+++ b/etc/pam_pkcs11.conf.example.in
@@ -23,6 +23,30 @@ pam_pkcs11 {
# previously set (intended for stacking password modules only).
use_authtok = false;
+ # card_only means:
+ # 1) always get the userid from the certificate.
+ # 2) don't prompt for the user name if the card is present.
+ # 3) if the token is present, then we must use the cardAuth mechanism.
+ card_only = false;
+
+ # wait_for_card means:
+ # 1) nothing if card_only isn't set
+ # 2) if logged in, block in pam conversation until the token used for login
+ # is inserted
+ # 3) if not logged in, block until a token that could be used for logging in
+ # is inserted
+ # right now, logged in means PKC11_LOGIN_TOKEN_NAME is set,
+ # but we could something else later (like set some per-user state in
+ # a pam session module keyed off uid)
+ wait_for_card = false;
+
+ # List of screen saver services.
+ # This list is only parsed if card_only is set. Basically the screen saver
+ # will bypass pam_pkcs11 if a token was not used to login (The basic idea is
+ # you always unlock the screen saver with the same mechanism you used to
+ # login).
+ screen_savers = mate-screensaver, gnome-screensaver, kde4-kscreensaver, kscreensaver, xscreensaver;
+
# Filename of the PKCS #11 module. The default value is "default"
use_pkcs11_module = opensc;
@@ -54,14 +78,14 @@ pam_pkcs11 {
# 1- A directory with openssl hash-links to all certificates
# 2- A CA file in PEM (.pem) or ASN1 (.cer) format,
# containing all allowed CA certs
- # The default value is /etc/pam_pkcs11/cacerts.
- ca_dir = /etc/pam_pkcs11/cacerts;
+ # The default value is @confdir@.
+ ca_dir = @confdir@/cacerts;
# Path to the directory where the local (offline) CRLs are stored.
# Same convention as above is applied: you can choose either
# hash-link directory or CRL file
- # The default value is /etc/pam_pkcs11/crls.
- crl_dir = /etc/pam_pkcs11/crls;
+ # The default value is @confdir@/crls.
+ crl_dir = @confdir@/crls;
# Some pcks#11 libraries can handle multithreading. So
# set it to true to properly call C_Initialize()
@@ -89,17 +113,6 @@ pam_pkcs11 {
token_type = "Smart card";
}
- # Aladdin eTokenPRO 32
- pkcs11_module etoken {
- module = /usr/local/lib/libetpkcs11.so
- description = "Aladdin eTokenPRO-32";
- slot_num = 0;
- support_threads = true;
- ca_dir = /etc/pam_pkcs11/cacerts;
- crl_dir = /etc/pam_pkcs11/crls;
- cert_policy = ca,signature;
- }
-
# NSS (Network Security Service) config
pkcs11_module nss {
nss_dir = /etc/ssl/nssdb;
@@ -112,8 +125,8 @@ pam_pkcs11 {
description = "Default pkcs#11 module";
slot_num = 0;
support_threads = false;
- ca_dir = /etc/pam_pkcs11/cacerts;
- crl_dir = /etc/pam_pkcs11/crls;
+ ca_dir = @confdir@/cacerts;
+ crl_dir = @confdir@/crls;
cert_policy = none;
}
@@ -138,7 +151,7 @@ pam_pkcs11 {
# If used null mapper should be the last in the list :-)
# Also you should select at least one mapper, otherwise
# certificate will not match :-)
- use_mappers = digest, cn, pwent, uid, mail, subject, null;
+ use_mappers = openssh, opensc;
# When no absolute path or module info is provided, use this
# value as module search path
@@ -157,7 +170,7 @@ pam_pkcs11 {
# Use one of "cn" , "subject" , "kpn" , "email" , "upn" , "uid" or "serial"
cert_item = cn;
# Define mapfile if needed, else select "none"
- mapfile = file:///etc/pam_pkcs11/generic_mapping;
+ mapfile = file://@confdir@/generic_mapping;
# Decide if use getpwent() to map login
use_getpwent = false;
}
@@ -169,7 +182,7 @@ pam_pkcs11 {
# module = @libdir@/pam_pkcs11/subject_mapper.so;
module = internal;
ignorecase = false;
- mapfile = file:///etc/pam_pkcs11/subject_mapping;
+ mapfile = file://@confdir@/subject_mapping;
}
# Search public keys from $HOME/.ssh/authorized_keys to match users
@@ -255,7 +268,7 @@ pam_pkcs11 {
module = internal;
# module = @libdir@/pam_pkcs11/cn_mapper.so;
ignorecase = true;
- # mapfile = file:///etc/pam_pkcs11/cn_map;
+ # mapfile = file://@confdir@/cn_map;
mapfile = "none";
}
@@ -266,7 +279,7 @@ pam_pkcs11 {
# module = @libdir@/pam_pkcs11/mail_mapper.so;
# Declare mapfile or
# leave empty "" or "none" to use no map
- mapfile = file:///etc/pam_pkcs11/mail_mapping;
+ mapfile = file://@confdir@/mail_mapping;
# Some certs store email in uppercase. take care on this
ignorecase = true;
# Also check that host matches mx domain
@@ -313,7 +326,7 @@ pam_pkcs11 {
# Select one of:
# "null","md2","md4","md5","sha","sha1","dss","dss1","ripemd160"
algorithm = "sha1";
- mapfile = file:///etc/pam_pkcs11/digest_mapping;
+ mapfile = file://@confdir@/digest_mapping;
# mapfile = "none";
}
diff --git a/etc/profiles/opensc b/etc/profiles/opensc
new file mode 100644
index 0000000..46709cd
--- /dev/null
+++ b/etc/profiles/opensc
@@ -0,0 +1,9 @@
+# OpenSC default
+#
+pam_pkcs11 {
+ nullok = true;
+ use_first_pass = false;
+ try_first_pass = false;
+ use_authtok = false;
+ use_pkcs11_module = opensc;
+}
diff --git a/etc/system-auth-pkcs11_strict b/etc/system-auth-pkcs11_strict
new file mode 100644
index 0000000..1cc6342
--- /dev/null
+++ b/etc/system-auth-pkcs11_strict
@@ -0,0 +1,11 @@
+#%PAM-1.0
+auth [success=done ignore=ignore default=die] pam_pkcs11.so
+auth requisite pam_succeed_if.so user ingroup wheel
+auth include system-auth-local
+
+account include system-auth-local
+
+password include system-auth-local
+
+session include system-auth-local
+session required pam_mkhomedir.so silent
diff --git a/etc/system-auth-use_first_pass-pkcs11_strict b/etc/system-auth-use_first_pass-pkcs11_strict
new file mode 100644
index 0000000..201f033
--- /dev/null
+++ b/etc/system-auth-use_first_pass-pkcs11_strict
@@ -0,0 +1,6 @@
+#%PAM-1.0
+auth [success=done ignore=ignore default=die] pam_pkcs11.so use_first_pass
+auth requisite pam_succeed_if.so user ingroup wheel
+auth include system-auth-use_first_pass-local
+
+password include system-auth-use_first_pass-local