Репозиторий Sisyphus
Последнее обновление: 1 октября 2023 | Пакетов: 18631 | Посещений: 37550005
en ru br
Репозитории ALT
S:0.6.12.1-alt1
5.1: 0.6.1-alt5
www.altlinux.org/Changes

Группа :: Система/Основа
Пакет: 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
 
дизайн и разработка: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
текущий майнтейнер: Michael Shigorin