summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith M Wesolowski <wesolows@foobazco.org>2014-10-13 16:24:27 +0000
committerKeith M Wesolowski <wesolows@foobazco.org>2014-10-13 16:24:27 +0000
commit7940642e2f955b21ae5a813f41db265ddb93bfd0 (patch)
tree68570e4e49909ae178bbe27d7e79dea51c7922ca
parent3a0c2c96e2bc82a36566804bd4de234bfa8b5753 (diff)
parent45405cce0657d01714b3d014a0facf3bdce45736 (diff)
downloadillumos-joyent-7940642e2f955b21ae5a813f41db265ddb93bfd0.tar.gz
[illumos-gate merge]
commit 45405cce0657d01714b3d014a0facf3bdce45736 5110 want pam_timestamp module Manifests: usr/src/pkg/manifests/system-library.man5.inc usr/src/pkg/manifests/system-library.mf
-rw-r--r--manifest3
-rw-r--r--usr/src/cmd/su/su.c4
-rw-r--r--usr/src/lib/pam_modules/Makefile3
-rw-r--r--usr/src/lib/pam_modules/timestamp/Makefile41
-rw-r--r--usr/src/lib/pam_modules/timestamp/Makefile.com30
-rw-r--r--usr/src/lib/pam_modules/timestamp/amd64/Makefile17
-rw-r--r--usr/src/lib/pam_modules/timestamp/i386/Makefile20
-rw-r--r--usr/src/lib/pam_modules/timestamp/mapfile-vers36
-rw-r--r--usr/src/lib/pam_modules/timestamp/pam_timestamp.c416
-rw-r--r--usr/src/lib/pam_modules/timestamp/sparc/Makefile20
-rw-r--r--usr/src/lib/pam_modules/timestamp/sparcv9/Makefile21
-rw-r--r--usr/src/man/man5/Makefile3
-rw-r--r--usr/src/man/man5/pam_timestamp.5114
-rw-r--r--usr/src/pkg/manifests/system-library.man5.inc3
-rw-r--r--usr/src/pkg/manifests/system-library.mf7
15 files changed, 735 insertions, 3 deletions
diff --git a/manifest b/manifest
index c5e1697ce5..16fee01205 100644
--- a/manifest
+++ b/manifest
@@ -9889,6 +9889,8 @@ f usr/lib/security/amd64/pam_sample.so.1 0755 root bin
s usr/lib/security/amd64/pam_sample.so=pam_sample.so.1
f usr/lib/security/amd64/pam_smbfs_login.so.1 0755 root bin
s usr/lib/security/amd64/pam_smbfs_login.so=pam_smbfs_login.so.1
+f usr/lib/security/amd64/pam_timestamp.so.1 0755 root bin
+s usr/lib/security/amd64/pam_timestamp.so=pam_timestamp.so.1
f usr/lib/security/amd64/pam_unix_account.so.1 0755 root bin
s usr/lib/security/amd64/pam_unix_account.so=pam_unix_account.so.1
f usr/lib/security/amd64/pam_unix_auth.so.1 0755 root bin
@@ -18072,6 +18074,7 @@ f usr/share/man/man5/pam_roles.5 0444 root bin
f usr/share/man/man5/pam_sample.5 0444 root bin
f usr/share/man/man5/pam_smb_passwd.5 0444 root bin
f usr/share/man/man5/pam_smbfs_login.5 0444 root bin
+f usr/share/man/man5/pam_timestamp.5 0444 root bin
f usr/share/man/man5/pam_unix_account.5 0444 root bin
f usr/share/man/man5/pam_unix_auth.5 0444 root bin
f usr/share/man/man5/pam_unix_cred.5 0444 root bin
diff --git a/usr/src/cmd/su/su.c b/usr/src/cmd/su/su.c
index c1e6849263..5d8f6da20a 100644
--- a/usr/src/cmd/su/su.c
+++ b/usr/src/cmd/su/su.c
@@ -21,6 +21,7 @@
/*
* Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012 Milan Jurik. All rights reserved.
+ * Copyright 2014 Nexenta Systems, Inc.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
@@ -283,6 +284,9 @@ main(int argc, char **argv)
exit(1);
if (pam_set_item(pamh, PAM_TTY, ttyn) != PAM_SUCCESS)
exit(1);
+ if (getpwuid_r(getuid(), &pwd, pwdbuf, sizeof (pwdbuf)) == NULL ||
+ pam_set_item(pamh, PAM_AUSER, pwd.pw_name) != PAM_SUCCESS)
+ exit(1);
#endif /* DYNAMIC_SU */
openlog("su", LOG_CONS, LOG_AUTH);
diff --git a/usr/src/lib/pam_modules/Makefile b/usr/src/lib/pam_modules/Makefile
index fa74ccba7b..4df91511af 100644
--- a/usr/src/lib/pam_modules/Makefile
+++ b/usr/src/lib/pam_modules/Makefile
@@ -22,6 +22,8 @@
# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
+# Copyright 2014 Nexenta Systems, Inc.
+#
# lib/pam_modules/Makefile
#
@@ -45,6 +47,7 @@ SUBDIRS = \
sample \
smb \
smbfs \
+ timestamp \
tsol_acct \
unix_auth \
unix_account \
diff --git a/usr/src/lib/pam_modules/timestamp/Makefile b/usr/src/lib/pam_modules/timestamp/Makefile
new file mode 100644
index 0000000000..81f04b8670
--- /dev/null
+++ b/usr/src/lib/pam_modules/timestamp/Makefile
@@ -0,0 +1,41 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# Copyright 2014 Nexenta Systems, Inc.
+#
+
+include ../../Makefile.lib
+
+TEXT_DOMAIN= SUNW_OST_SYSOSPAM
+POFILE= pam_timestamp.po
+MSGFILES= pam_timestamp.c
+
+SUBDIRS= $(MACH)
+$(BUILD64)SUBDIRS += $(MACH64)
+
+all := TARGET= all
+clean := TARGET= clean
+clobber := TARGET= clobber
+install := TARGET= install
+lint := TARGET= lint
+
+.KEEP_STATE:
+
+all clean clobber install lint: $(SUBDIRS)
+
+_msg: $(MSGDOMAINPOFILE)
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
+
+include $(SRC)/Makefile.msg.targ
+include ../../Makefile.targ
diff --git a/usr/src/lib/pam_modules/timestamp/Makefile.com b/usr/src/lib/pam_modules/timestamp/Makefile.com
new file mode 100644
index 0000000000..596dbb5228
--- /dev/null
+++ b/usr/src/lib/pam_modules/timestamp/Makefile.com
@@ -0,0 +1,30 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# Copyright 2014 Nexenta Systems, Inc.
+#
+
+#
+# usr/src/lib/pam_modules/pam_timestamp/Makefile.com
+#
+
+LIBRARY= pam_timestamp.a
+VERS= .1
+OBJECTS= pam_timestamp.o
+
+include ../../Makefile.pam_modules
+
+LDLIBS += -lpam -lc
+
+all: $(LIBS)
+
+lint: lintcheck
+
+include $(SRC)/lib/Makefile.targ
diff --git a/usr/src/lib/pam_modules/timestamp/amd64/Makefile b/usr/src/lib/pam_modules/timestamp/amd64/Makefile
new file mode 100644
index 0000000000..03d73c9d78
--- /dev/null
+++ b/usr/src/lib/pam_modules/timestamp/amd64/Makefile
@@ -0,0 +1,17 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# Copyright 2014 Nexenta Systems, Inc.
+#
+
+include ../Makefile.com
+include ../../../Makefile.lib.64
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64)
diff --git a/usr/src/lib/pam_modules/timestamp/i386/Makefile b/usr/src/lib/pam_modules/timestamp/i386/Makefile
new file mode 100644
index 0000000000..51ba7d44a5
--- /dev/null
+++ b/usr/src/lib/pam_modules/timestamp/i386/Makefile
@@ -0,0 +1,20 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# Copyright 2014 Nexenta Systems, Inc.
+#
+
+#
+# usr/src/lib/pam_modules/pam_timestamp/i386/Makefile
+#
+
+include ../Makefile.com
+
+install: all $(ROOTLIBS) $(ROOTLINKS)
diff --git a/usr/src/lib/pam_modules/timestamp/mapfile-vers b/usr/src/lib/pam_modules/timestamp/mapfile-vers
new file mode 100644
index 0000000000..696d240332
--- /dev/null
+++ b/usr/src/lib/pam_modules/timestamp/mapfile-vers
@@ -0,0 +1,36 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# Copyright 2014 Nexenta Systems, Inc.
+#
+
+#
+# MAPFILE HEADER START
+#
+# WARNING: STOP NOW. DO NOT MODIFY THIS FILE.
+# Object versioning must comply with the rules detailed in
+#
+# usr/src/lib/README.mapfiles
+#
+# You should not be making modifications here until you've read the most current
+# copy of that file. If you need help, contact a gatekeeper for guidance.
+#
+# MAPFILE HEADER END
+#
+
+$mapfile_version 2
+
+SYMBOL_VERSION ILLUMOS_0.1 {
+ global:
+ pam_sm_authenticate;
+ pam_sm_setcred;
+ local:
+ *;
+};
diff --git a/usr/src/lib/pam_modules/timestamp/pam_timestamp.c b/usr/src/lib/pam_modules/timestamp/pam_timestamp.c
new file mode 100644
index 0000000000..dafc96923e
--- /dev/null
+++ b/usr/src/lib/pam_modules/timestamp/pam_timestamp.c
@@ -0,0 +1,416 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+/*
+ * Copyright 2014 Nexenta Systems, Inc.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <fcntl.h>
+#include <security/pam_appl.h>
+#include <security/pam_modules.h>
+#include <security/pam_impl.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <libgen.h>
+#include <errno.h>
+
+#define TIMESTAMP_DIR "/var/run/tty_timestamps"
+#define TIMESTAMP_TIMEOUT 5 /* default timeout */
+#define ROOT_UID 0 /* root uid */
+#define ROOT_GID 0 /* root gid */
+
+struct user_info {
+ dev_t dev; /* ID of device tty resides on */
+ dev_t rdev; /* tty device ID */
+ ino_t ino; /* tty inode number */
+ uid_t uid; /* user's uid */
+ pid_t ppid; /* parent pid */
+ pid_t sid; /* session ID associated with tty/ppid */
+ timestruc_t ts; /* time of tty last status change */
+};
+
+int debug = 0;
+
+int
+validate_basic(
+ pam_handle_t *pamh,
+ char *user_tty,
+ char *timestampfile)
+{
+ char *user;
+ char *auser;
+ char *ttyn;
+
+ /* get user, auser and users's tty */
+ (void) pam_get_item(pamh, PAM_USER, (void **)&user);
+ (void) pam_get_item(pamh, PAM_AUSER, (void **)&auser);
+ (void) pam_get_item(pamh, PAM_TTY, (void **)&ttyn);
+
+ if (user == NULL || *user == '\0') {
+ syslog(LOG_AUTH | LOG_ERR, "pam_timestamp: "
+ "PAM_USER NULL or empty");
+ return (PAM_IGNORE);
+ }
+
+ if (auser == NULL || *auser == '\0') {
+ syslog(LOG_AUTH | LOG_ERR, "pam_timestamp: "
+ "PAM_AUSER NULL or empty");
+ return (PAM_IGNORE);
+ }
+
+ if (ttyn == NULL || *ttyn == '\0') {
+ syslog(LOG_AUTH | LOG_ERR, "pam_timestamp: "
+ "PAM_TTY NULL or empty");
+ return (PAM_IGNORE);
+ }
+
+ if (debug)
+ syslog(LOG_AUTH | LOG_DEBUG, "pam_timestamp: "
+ "user = %s, auser = %s, tty = %s", user, auser, ttyn);
+
+ (void) strlcpy(user_tty, ttyn, MAXPATHLEN);
+
+ if (strchr(ttyn, '/') == NULL || strncmp(ttyn, "/dev/", 5) == 0) {
+ ttyn = strrchr(ttyn, '/') + 1;
+ } else {
+ syslog(LOG_AUTH | LOG_ERR, "pam_timestamp: "
+ "invalid tty: %s", ttyn);
+ return (PAM_IGNORE);
+ }
+
+ /* format timestamp file name */
+ (void) snprintf(timestampfile, MAXPATHLEN, "%s/%s/%s:%s", TIMESTAMP_DIR,
+ auser, ttyn, user);
+
+ return (PAM_SUCCESS);
+}
+
+int
+validate_dir(const char *dir)
+{
+ struct stat sb;
+
+ /*
+ * check that the directory exist and has
+ * right owner and permissions.
+ */
+ if (lstat(dir, &sb) < 0) {
+ syslog(LOG_AUTH | LOG_ERR, "pam_timestamp: "
+ "directory %s does not exist", dir);
+ return (PAM_IGNORE);
+ }
+
+ if (!S_ISDIR(sb.st_mode)) {
+ syslog(LOG_AUTH | LOG_ERR, "pam_timestamp: "
+ "%s is not a directory", dir);
+ return (PAM_IGNORE);
+ }
+
+ if (S_ISLNK(sb.st_mode)) {
+ syslog(LOG_AUTH | LOG_ERR, "pam_timestamp: "
+ "%s is a symbolic link", dir);
+ return (PAM_IGNORE);
+ }
+
+ if (sb.st_uid != 0 || sb.st_gid != 0) {
+ syslog(LOG_AUTH | LOG_ERR, "pam_timestamp: "
+ "%s is not owned by root", dir);
+ return (PAM_IGNORE);
+ }
+
+ if (sb.st_mode & (S_IWGRP | S_IWOTH | S_IROTH)) {
+ syslog(LOG_AUTH | LOG_ERR, "pam_timestamp: "
+ "%s has wrong permissions", dir);
+ return (PAM_IGNORE);
+ }
+
+ return (PAM_SUCCESS);
+}
+
+int
+create_dir(char *dir)
+{
+ /*
+ * create directory if it doesn't exist and attempt to set
+ * the owner to root.
+ */
+ if (mkdir(dir, S_IRWXU) < 0) {
+ if (errno != EEXIST) {
+ syslog(LOG_AUTH | LOG_ERR, "pam_timestamp: "
+ "can't create directory %s", dir);
+ return (PAM_IGNORE);
+ }
+ } else if (lchown(dir, ROOT_UID, ROOT_GID) < 0) {
+ syslog(LOG_AUTH | LOG_ERR, "pam_timestamp: "
+ "can't set permissions on directory %s", dir);
+ return (PAM_IGNORE);
+ }
+ return (PAM_SUCCESS);
+}
+
+/*
+ * pam_sm_authenticate
+ *
+ * Read authentication from user, using cached successful authentication
+ * attempts.
+ *
+ * returns PAM_SUCCESS on success, otherwise always returns PAM_IGNORE:
+ * while this module has "sufficient" control value, in case of any failure
+ * user will be authenticated with the pam_unix_auth module.
+ * options -
+ * debug
+ * timeout= timeout in min, default is 5
+ */
+/*ARGSUSED*/
+int
+pam_sm_authenticate(
+ pam_handle_t *pamh,
+ int flags,
+ int argc,
+ const char **argv)
+{
+ struct user_info info;
+ struct stat sb, tty;
+ time_t timeout = 0;
+ long tmp = 0;
+ int result = PAM_IGNORE;
+ int i;
+ int fd = -1;
+ char *p;
+ char user_tty[MAXPATHLEN];
+ char timestampdir[MAXPATHLEN];
+ char timestampfile[MAXPATHLEN];
+ char *sudir;
+
+ timeout = TIMESTAMP_TIMEOUT;
+
+ /* check options passed to this module */
+ for (i = 0; i < argc; i++) {
+ if (strcmp(argv[i], "debug") == 0) {
+ debug = 1;
+ } else if (strncmp(argv[i], "timeout=", 8) == 0) {
+ tmp = strtol(argv[i] + 8, &p, 0);
+ if ((p != NULL) && (*p == '\0') && tmp > 0) {
+ timeout = tmp;
+ }
+ }
+ }
+
+ if (validate_basic(pamh, user_tty, timestampfile) != PAM_SUCCESS)
+ return (result);
+
+ sudir = TIMESTAMP_DIR;
+ if (validate_dir(sudir) != PAM_SUCCESS)
+ return (result);
+
+ (void) strlcpy(timestampdir, timestampfile, MAXPATHLEN);
+
+ if (validate_dir(dirname(timestampdir)) != PAM_SUCCESS)
+ return (result);
+
+ /*
+ * check that timestamp file is exist and has right owner
+ * and permissions.
+ */
+ if (lstat(timestampfile, &sb) == 0 && sb.st_size != 0) {
+ if (!S_ISREG(sb.st_mode)) {
+ (void) unlink(timestampfile);
+ syslog(LOG_AUTH | LOG_ERR, "pam_timestamp: "
+ "timestamp file %s is not a regular file",
+ timestampfile);
+ return (result);
+ }
+
+ if (sb.st_uid != 0 || sb.st_gid != 0) {
+ (void) unlink(timestampfile);
+ syslog(LOG_AUTH | LOG_ERR, "pam_timestamp: "
+ "timestamp file %s is not owned by root",
+ timestampfile);
+ return (result);
+ }
+
+ if (sb.st_nlink != 1 || S_ISLNK(sb.st_mode)) {
+ (void) unlink(timestampfile);
+ syslog(LOG_AUTH | LOG_ERR, "pam_timestamp: "
+ "timestamp file %s is a symbolic link",
+ timestampfile);
+ return (result);
+ }
+
+ if (sb.st_mode & (S_IRWXG | S_IRWXO)) {
+ (void) unlink(timestampfile);
+ syslog(LOG_AUTH | LOG_ERR, "pam_timestamp: "
+ "timestamp file %s has wrong permissions",
+ timestampfile);
+ return (result);
+ }
+ } else {
+ if (debug)
+ syslog(LOG_AUTH | LOG_DEBUG, "pam_timestamp: "
+ "timestamp file %s does not exist: %m",
+ timestampfile);
+ return (result);
+ }
+
+
+ if (stat(user_tty, &tty) < 0) {
+ syslog(LOG_AUTH | LOG_ERR, "pam_timestamp: "
+ "can't stat tty: %m");
+ return (result);
+ }
+
+ if ((fd = open(timestampfile, O_RDONLY)) < 0) {
+ syslog(LOG_AUTH | LOG_ERR, "pam_timestamp: "
+ "can't open timestamp file %s for reading: %m",
+ timestampfile);
+ return (result);
+ }
+
+ if (read(fd, &info, sizeof (info)) != sizeof (info)) {
+ (void) close(fd);
+ (void) unlink(timestampfile);
+ syslog(LOG_AUTH | LOG_ERR, "pam_timestamp: "
+ "timestamp file '%s' is corrupt: %m", timestampfile);
+ return (result);
+ }
+
+ if (info.dev != tty.st_dev || info.ino != tty.st_ino ||
+ info.rdev != tty.st_rdev || info.sid != getsid(getpid()) ||
+ info.uid != getuid() || info.ts.tv_sec != tty.st_ctim.tv_sec ||
+ info.ts.tv_nsec != tty.st_ctim.tv_nsec) {
+ (void) close(fd);
+ (void) unlink(timestampfile);
+ syslog(LOG_AUTH | LOG_ERR, "pam_timestamp: "
+ "the content of the timestamp file '%s' is not valid",
+ timestampfile);
+ return (result);
+ }
+
+ if (time((time_t *)0) - sb.st_mtime > 60 * timeout) {
+ (void) unlink(timestampfile);
+ syslog(LOG_AUTH | LOG_ERR, "pam_timestamp: "
+ "timestamp file '%s' has expired, disallowing access",
+ timestampfile);
+ return (result);
+ } else {
+ if (debug)
+ syslog(LOG_AUTH | LOG_DEBUG, "pam_timestamp: "
+ "timestamp file %s is not expired, "
+ "allowing access ", timestampfile);
+ result = PAM_SUCCESS;
+ }
+
+ return (result);
+}
+
+/*
+ * pam_sm_setcred
+ *
+ * Creates timestamp directory and writes
+ * timestamp file if it doesn't exist.
+ *
+ * returns PAM_SUCCESS on success, otherwise PAM_IGNORE
+ */
+/*ARGSUSED*/
+int
+pam_sm_setcred(
+ pam_handle_t *pamh,
+ int flags,
+ int argc,
+ const char **argv)
+{
+ struct stat sb;
+ struct stat tty;
+ struct user_info info;
+ int result = PAM_IGNORE;
+ int fd = -1;
+ char user_tty[MAXPATHLEN];
+ char timestampdir[MAXPATHLEN];
+ char timestampfile[MAXPATHLEN];
+
+ /* validate flags */
+ if (flags && !(flags & PAM_ESTABLISH_CRED) &&
+ !(flags & PAM_REINITIALIZE_CRED) &&
+ !(flags & PAM_REFRESH_CRED) &&
+ !(flags & PAM_DELETE_CRED) &&
+ !(flags & PAM_SILENT)) {
+ syslog(LOG_ERR, "pam_timestamp: illegal flag %d", flags);
+ return (result);
+ }
+
+ if (validate_basic(pamh, user_tty, timestampfile) != PAM_SUCCESS)
+ return (result);
+
+ /*
+ * user doesn't need to authenticate for PAM_DELETE_CRED
+ */
+ if (flags & PAM_DELETE_CRED) {
+ (void) unlink(timestampfile);
+ return (result);
+ }
+
+ /* if the timestamp file exist, there is nothing to do */
+ if (lstat(timestampfile, &sb) == 0) {
+ if (debug)
+ syslog(LOG_AUTH | LOG_DEBUG, "pam_timestamp: "
+ "timestamp file %s is not expired", timestampfile);
+ return (result);
+ }
+
+ if (create_dir(TIMESTAMP_DIR) != PAM_SUCCESS)
+ return (result);
+
+ (void) strlcpy(timestampdir, timestampfile, MAXPATHLEN);
+
+ if (create_dir(dirname(timestampdir)) != PAM_SUCCESS)
+ return (result);
+
+ if (stat(user_tty, &tty) < 0) {
+ syslog(LOG_AUTH | LOG_ERR, "pam_timestamp: "
+ "can't stat tty: %m");
+ return (result);
+ }
+
+ info.dev = tty.st_dev;
+ info.ino = tty.st_ino;
+ info.rdev = tty.st_rdev;
+ info.sid = getsid(getpid());
+ info.uid = getuid();
+ info.ts = tty.st_ctim;
+
+ if ((fd = open(timestampfile, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR)) < 0) {
+ syslog(LOG_AUTH | LOG_ERR, "pam_timestamp: "
+ "can't open timestamp file %s for writing: %m",
+ timestampfile);
+ return (result);
+ } else if (fchown(fd, ROOT_UID, ROOT_GID) != 0) {
+ syslog(LOG_AUTH | LOG_ERR, "pam_timestamp: "
+ "can't set permissions on timestamp file %s: %m",
+ timestampfile);
+ (void) close(fd);
+ return (result);
+ }
+
+ if (write(fd, &info, sizeof (info)) != sizeof (info)) {
+ (void) close(fd);
+ syslog(LOG_AUTH | LOG_ERR, "pam_timestamp: "
+ "can't write timestamp file %s: %m", timestampfile);
+ return (result);
+ }
+ (void) close(fd);
+
+ return (PAM_SUCCESS);
+}
diff --git a/usr/src/lib/pam_modules/timestamp/sparc/Makefile b/usr/src/lib/pam_modules/timestamp/sparc/Makefile
new file mode 100644
index 0000000000..e8eb04ce91
--- /dev/null
+++ b/usr/src/lib/pam_modules/timestamp/sparc/Makefile
@@ -0,0 +1,20 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# Copyright 2014 Nexenta Systems, Inc.
+#
+
+#
+# usr/src/lib/pam_modules/pam_timestamp/sparc/Makefile
+#
+
+include ../Makefile.com
+
+install: all $(ROOTLIBS) $(ROOTLINKS)
diff --git a/usr/src/lib/pam_modules/timestamp/sparcv9/Makefile b/usr/src/lib/pam_modules/timestamp/sparcv9/Makefile
new file mode 100644
index 0000000000..7494e1031e
--- /dev/null
+++ b/usr/src/lib/pam_modules/timestamp/sparcv9/Makefile
@@ -0,0 +1,21 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# Copyright 2014 Nexenta Systems, Inc.
+#
+
+#
+# usr/src/lib/pam_modules/pam_timestamp/sparcv9/Makefile
+#
+
+include ../Makefile.com
+include ../../../Makefile.lib.64
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64)
diff --git a/usr/src/man/man5/Makefile b/usr/src/man/man5/Makefile
index a8015a3dd3..868e22eaf0 100644
--- a/usr/src/man/man5/Makefile
+++ b/usr/src/man/man5/Makefile
@@ -12,7 +12,7 @@
#
# Copyright 2011, Richard Lowe
# Copyright (c) 2012 by Delphix. All rights reserved.
-# Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+# Copyright 2014 Nexenta Systems, Inc.
# Copyright 2014 Garrett D'Amore <garrett@damore.org>
# Copyright (c) 2014, Joyent, Inc. All rights reserved.
#
@@ -96,6 +96,7 @@ MANFILES= Intro.5 \
pam_sample.5 \
pam_smb_passwd.5 \
pam_smbfs_login.5 \
+ pam_timestamp.5 \
pam_tsol_account.5 \
pam_unix_account.5 \
pam_unix_auth.5 \
diff --git a/usr/src/man/man5/pam_timestamp.5 b/usr/src/man/man5/pam_timestamp.5
new file mode 100644
index 0000000000..8ed105f825
--- /dev/null
+++ b/usr/src/man/man5/pam_timestamp.5
@@ -0,0 +1,114 @@
+.\"
+.\" This file and its contents are supplied under the terms of the
+.\" Common Development and Distribution License ("CDDL"), version 1.0.
+.\" You may only use this file in accordance with the terms of version
+.\" 1.0 of the CDDL.
+.\"
+.\" A full copy of the text of the CDDL should have accompanied this
+.\" source. A copy of the CDDL is also available via the Internet at
+.\" http://www.illumos.org/license/CDDL.
+.\"
+.\" Copyright 2014 Nexenta Systems, Inc.
+.\"
+.Dd Aug 20, 2014
+.Dt PAM_TIMESTAMP 5
+.Os
+.Sh NAME
+.Nm pam_timestamp
+.Nd PAM authentication module using cached successful
+authentication attempts
+.Sh SYNOPSIS
+.Nm pam_timestamp.so.1
+.Op Ar debug
+.Op Ar timeout=min
+.Sh DESCRIPTION
+The
+.Nm
+module caches successful tty-based authentication attempts by
+creating user's directories and per tty timestamp files in the
+common timestamp directory
+.Pa /var/run/tty_timestamps .
+Next authentication, if the timestamp file exist and not expired,
+the user will not be asked for a password, otherwise timestamp
+file will be deleted and user will be prompted to enter a password.
+.Lp
+The PAM items
+.Dv PAM_USER ,
+.Dv PAM_AUSER
+and
+.Dv PAM_TTY
+are used by this module.
+.Sy pam_timestamp
+is normally configured as
+.Sy sufficient
+and must be used in conjunction with the modules that support
+the UNIX authentication, which are
+.Xr pam_authtok_get 5 ,
+.Xr pam_unix_cred 5
+and
+.Xr pam_unix_auth 5 .
+Proper authentication operation requires
+.Xr pam_unix_cred 5
+be stacked above
+.Xr pam_timestamp .
+.Sh OPTIONS
+.Bl -tag -width Ds
+.It Dv debug
+Provides
+.Xr syslog 3
+debugging information at the
+.Sy LOG_AUTH | LOG_DEBUG
+level.
+.It Dv timeout
+Specifies the period (in miniutes) for which the timestamp
+file is valid. The default value is 5 minutes.
+.El
+.Sh FILES
+.Bl -tag -width indent
+.It Pa /var/run/tty_timestamps/...
+stores timestamp directories and files
+.El
+.Sh EXIT STATUS
+.Bl -tag -width Ds
+.It Dv PAM_SUCCESS
+Timestamp file is not expired.
+.It Dv PAM_IGNORE
+The
+.Nm
+module was not able to retrieve required credentials
+or timestamp file is expired or corrupt.
+.El
+.Sh EXAMPLES
+.Ss Example 1 Allowing su authentication
+.
+The following example is a
+.Xr pam.conf 4
+fragment that illustartes a default settings for allowing
+.Xr su 1M
+authentication:
+.Bd -literal -offset indent
+su auth required pam_unix_cred.so.1
+su auth sufficient pam_timestamp.so.1
+su auth requisite pam_authtok_get.so.1
+su auth required pam_unix_auth.so.1
+.Ed
+.Ss Example 2 Changing default timeout
+.
+The default timeout set to 10 minutes:
+.Bd -literal -offset indent
+su auth required pam_unix_cred.so.1
+su auth sufficient pam_timestamp.so.1 timeout=10
+su auth requisite pam_authtok_get.so.1
+su auth required pam_unix_auth.so.1
+.Ed
+.Sh INTERFACE STABILITY
+.Sy Uncommitted .
+.Sh MT LEVEL
+.Sy MT-Safe .
+.Sh SEE ALSO
+.Xr su 1M ,
+.Xr pam 3PAM ,
+.Xr pam_sm_authenticate 3PAM ,
+.Xr pam_sm_setcred 3PAM ,
+.Xr pam.conf 4 ,
+.Xr syslog 3C
diff --git a/usr/src/pkg/manifests/system-library.man5.inc b/usr/src/pkg/manifests/system-library.man5.inc
index a16b5c7995..1344b918e2 100644
--- a/usr/src/pkg/manifests/system-library.man5.inc
+++ b/usr/src/pkg/manifests/system-library.man5.inc
@@ -11,7 +11,7 @@
#
# Copyright 2011, Richard Lowe
-# Copyright 2012 Nexenta Systems, Inc. All rights reserved.
+# Copyright 2014 Nexenta Systems, Inc.
#
file path=usr/share/man/man5/audit_binfile.5
@@ -49,6 +49,7 @@ file path=usr/share/man/man5/pam_passwd_auth.5
file path=usr/share/man/man5/pam_rhosts_auth.5
file path=usr/share/man/man5/pam_roles.5
file path=usr/share/man/man5/pam_sample.5
+file path=usr/share/man/man5/pam_timestamp.5
file path=usr/share/man/man5/pam_tsol_account.5
file path=usr/share/man/man5/pam_unix_account.5
file path=usr/share/man/man5/pam_unix_auth.5
diff --git a/usr/src/pkg/manifests/system-library.mf b/usr/src/pkg/manifests/system-library.mf
index 517814cddb..089d9bc75d 100644
--- a/usr/src/pkg/manifests/system-library.mf
+++ b/usr/src/pkg/manifests/system-library.mf
@@ -20,7 +20,7 @@
#
#
-# Copyright 2011 Nexenta Systems, Inc. All rights reserved.
+# Copyright 2014 Nexenta Systems, Inc.
# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
# Copyright 2012 OmniTI Computer Consulting, Inc. All rights reserved.
# Copyright (c) 2013 Gary Mills
@@ -485,6 +485,7 @@ file path=usr/lib/security/$(ARCH64)/pam_passwd_auth.so.1
file path=usr/lib/security/$(ARCH64)/pam_rhosts_auth.so.1
file path=usr/lib/security/$(ARCH64)/pam_roles.so.1
file path=usr/lib/security/$(ARCH64)/pam_sample.so.1
+file path=usr/lib/security/$(ARCH64)/pam_timestamp.so.1
file path=usr/lib/security/$(ARCH64)/pam_tsol_account.so.1
file path=usr/lib/security/$(ARCH64)/pam_unix_account.so.1
file path=usr/lib/security/$(ARCH64)/pam_unix_auth.so.1
@@ -514,6 +515,7 @@ file path=usr/lib/security/pam_passwd_auth.so.1
file path=usr/lib/security/pam_rhosts_auth.so.1
file path=usr/lib/security/pam_roles.so.1
file path=usr/lib/security/pam_sample.so.1
+file path=usr/lib/security/pam_timestamp.so.1
file path=usr/lib/security/pam_tsol_account.so.1
file path=usr/lib/security/pam_unix_account.so.1
file path=usr/lib/security/pam_unix_auth.so.1
@@ -1228,6 +1230,8 @@ link path=usr/lib/security/$(ARCH64)/pam_rhosts_auth.so \
target=./pam_rhosts_auth.so.1
link path=usr/lib/security/$(ARCH64)/pam_roles.so target=./pam_roles.so.1
link path=usr/lib/security/$(ARCH64)/pam_sample.so target=./pam_sample.so.1
+link path=usr/lib/security/$(ARCH64)/pam_timestamp.so \
+ target=./pam_timestamp.so.1
link path=usr/lib/security/$(ARCH64)/pam_tsol_account.so \
target=./pam_tsol_account.so.1
link path=usr/lib/security/$(ARCH64)/pam_unix_account.so \
@@ -1267,6 +1271,7 @@ link path=usr/lib/security/pam_passwd_auth.so target=./pam_passwd_auth.so.1
link path=usr/lib/security/pam_rhosts_auth.so target=./pam_rhosts_auth.so.1
link path=usr/lib/security/pam_roles.so target=./pam_roles.so.1
link path=usr/lib/security/pam_sample.so target=./pam_sample.so.1
+link path=usr/lib/security/pam_timestamp.so target=./pam_timestamp.so.1
link path=usr/lib/security/pam_tsol_account.so target=./pam_tsol_account.so.1
link path=usr/lib/security/pam_unix_account.so target=./pam_unix_account.so.1
link path=usr/lib/security/pam_unix_auth.so target=./pam_unix_auth.so.1