--- old/usr/src/Targetdirs	Sat Jun 30 22:01:37 2012
+++ new/usr/src/Targetdirs	Sat Jun 30 22:01:37 2012
@@ -127,6 +127,7 @@
 	/etc/security/prof_attr.d \
 	/etc/security/tsol	\
 	/etc/gss	\
+	/etc/pam.d	\
 	/etc/init.d  \
 	/etc/dhcp	\
 	/etc/lib  \
--- old/usr/src/cmd/Makefile	Sat Jun 30 22:01:38 2012
+++ new/usr/src/cmd/Makefile	Sat Jun 30 22:01:38 2012
@@ -289,6 +289,7 @@
 	od		\
 	pack		\
 	pagesize	\
+	pamconv		\
 	passmgmt	\
 	passwd		\
 	pathchk		\
--- /dev/null	Sat Jun 30 22:01:38 2012
+++ new/usr/src/cmd/pamconv/Makefile	Sat Jun 30 22:01:38 2012
@@ -0,0 +1,49 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright 2012 Joshua M. Clulow <josh@sysmgr.org>
+#
+
+PROG=           pamconv
+MANIFEST=	pam-upgrade.xml
+SVCMETHOD=	pam-upgrade
+
+include ../Makefile.cmd
+TEXT_DOMAIN=	SUNW_OST_ADMIN
+
+FILEMODE=       0555
+
+ROOTMANIFESTDIR=	$(ROOTSVCSYSTEM)
+
+CLOBBERFILES +=	$(SVCMETHOD)
+
+.KEEP_STATE:
+
+all: $(PROG) 
+
+install:	all $(ROOTUSRSBINPROG) $(ROOTMANIFEST) $(ROOTSVCMETHOD)
+
+check:		$(CHKMANIFEST)
+
+clean:
+
+lint:   	lint_PROG
+ 
+include ../Makefile.targ
--- /dev/null	Sat Jun 30 22:01:38 2012
+++ new/usr/src/cmd/pamconv/pam-upgrade.sh	Sat Jun 30 22:01:38 2012
@@ -0,0 +1,30 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2012 Joshua M. Clulow <josh@sysmgr.org>
+#
+
+# Convert an existing legacy pam.conf into /etc/pam.d shards
+# and replace existing pam.conf with placeholder
+/usr/sbin/pamconv -r
+
+# Disable this service as the upgrade is done
+/usr/sbin/svcadm disable "$SMF_FMRI"
--- /dev/null	Sat Jun 30 22:01:38 2012
+++ new/usr/src/cmd/pamconv/pam-upgrade.xml	Sat Jun 30 22:01:38 2012
@@ -0,0 +1,91 @@
+<?xml version="1.0"?>
+<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
+<!--
+ Copyright 2012 Joshua M. Clulow <josh@sysmgr.org>
+
+ CDDL HEADER START
+
+ The contents of this file are subject to the terms of the
+ Common Development and Distribution License (the "License").
+ You may not use this file except in compliance with the License.
+
+ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ or http://www.opensolaris.org/os/licensing.
+ See the License for the specific language governing permissions
+ and limitations under the License.
+
+ When distributing Covered Code, include this CDDL HEADER in each
+ file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ If applicable, add the following below this CDDL HEADER, with the
+ fields enclosed by brackets "[]" replaced with your own identifying
+ information: Portions Copyright [yyyy] [name of copyright owner]
+
+ CDDL HEADER END
+
+	NOTE:  This service manifest is not editable; its contents will
+	be overwritten by package or patch operations, including
+	operating system upgrade.  Make customizations in a different
+	file.
+
+	Service manifest for the PAM configuration upgrade (pamconv) service.
+-->
+
+<service_bundle type='manifest' name='SUNWcsr:pam-upgrade'>
+
+<service
+	name='system/pam-upgrade'
+	type='service'
+	version='1'>
+
+	<create_default_instance enabled='true' />
+
+	<single_instance />
+
+	<dependency
+		name='filesystem'
+		grouping='require_all'
+		restart_on='none'
+		type='service'>
+		<service_fmri value='svc:/system/filesystem/local'/>
+	</dependency>
+
+	<exec_method
+		type='method'
+		name='stop'
+		exec=':true'
+		timeout_seconds='60' >
+	</exec_method>
+
+	<exec_method
+		type='method'
+		name='start'
+		exec='/lib/svc/method/pamconv %m'
+		timeout_seconds='120' >
+	</exec_method>
+
+	<property_group
+		name='startd'
+		type='framework'>
+		<propval name='duration' type='astring' value='transient' />
+	</property_group>
+
+	<stability value='Unstable' />
+
+	<template>
+		<common_name>
+			<loctext xml:lang='C'>pam-upgrade</loctext>
+		</common_name>
+		<description>
+			<loctext xml:lang='C'>
+pam-upgrade handles the conversion of a legacy, monolithic /etc/pam.conf file
+into /etc/pam.d per-service shard files.
+			</loctext>
+		</description>
+		<documentation>
+			<manpage title='pam.conf' section='4'
+				manpath='/usr/share/man' />
+		</documentation>
+	</template>
+</service>
+
+</service_bundle>
--- /dev/null	Sat Jun 30 22:01:39 2012
+++ new/usr/src/cmd/pamconv/pamconv.c	Sat Jun 30 22:01:39 2012
@@ -0,0 +1,393 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2012 Joshua M. Clulow <josh@sysmgr.org>
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <err.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+#define	PAM_CONFIG	"/etc/pam.conf"
+#define	PAM_CONFIG_DIR	"/etc/pam.d"
+
+#define	SENTINEL0	" CDDL HEADER END"
+#define	SENTINEL1	" present in this file in previous releases are " \
+			"still acceptable."
+#define	SENTINEL2	" Authentication management"
+
+#define	LEGACY_CONTENTS	"#\n" \
+			"# Legacy PAM Configuration\n" \
+			"#\n" \
+			"# The shipped PAM configuration has moved from " \
+				"the legacy " PAM_CONFIG "\n" \
+			"# to the new " PAM_CONFIG_DIR " model.  See " \
+				"pam.conf(4) for more information.\n"
+
+
+typedef struct pamline {
+	char *service;
+	char *copyfrom;
+	char *commentfrom;
+	struct pamline *next;
+} pamline_t;
+
+typedef struct servicelist {
+	char *service;
+	struct servicelist *next;
+} servicelist_t;
+
+
+static int fd;
+static char *f;
+static size_t flen;
+
+static pamline_t *all = NULL;
+static servicelist_t *services = NULL;
+
+static char *pam_config = PAM_CONFIG;
+static char *pam_config_dir = PAM_CONFIG_DIR;
+
+static boolean_t preview = B_FALSE;
+static boolean_t verbose = B_FALSE;
+static boolean_t replace_original = B_FALSE;
+
+static boolean_t onlycomments = B_TRUE;
+
+
+static void
+store_service(char *service)
+{
+	servicelist_t *sl = calloc(1, sizeof (servicelist_t));
+	sl->service = service;
+	if (services == NULL) {
+		services = sl;
+	} else {
+		servicelist_t *t = services;
+		while (t != NULL) {
+			if (strcmp(t->service, sl->service) == 0)
+				return;
+			if (t->next == NULL) {
+				t->next = sl;
+				break;
+			}
+			t = t->next;
+		}
+	}
+}
+
+static void
+print_service(FILE *file, char *service)
+{
+	pamline_t *t = all;
+	while (t != NULL) {
+		if (t->service && strcmp(t->service, service) == 0) {
+			if (t->copyfrom && fprintf(file, "%s",
+			    t->copyfrom) < 0)
+				err(2, "could not write file");
+			if (t->commentfrom && fprintf(file, "#%s",
+			    t->commentfrom) < 0)
+				err(2, "could not write file");
+			if (fprintf(file, "\n") < 0)
+				err(2, "could not write file");
+		}
+		t = t->next;
+	}
+}
+
+static void
+write_service_file(char *service)
+{
+	FILE *out;
+	char *path;
+
+	if (asprintf(&path, "%s/%s", pam_config_dir, service) < 0)
+		err(2, "could not asprintf");
+	if (verbose)
+		(void) fprintf(stderr, "service '%s' -> %s\n", service, path);
+	out = fopen(path, "w+");
+	if (out == NULL)
+		err(2, "could not open %s for write", path);
+	free(path);
+
+	print_service(out, service);
+
+	(void) fclose(out);
+}
+
+static void
+write_legacy_file(void)
+{
+	FILE *out;
+
+	if (verbose)
+		(void) fprintf(stderr, "replacing %s with placeholder file",
+		    pam_config);
+
+	out = fopen(pam_config, "w+");
+	if (out == NULL)
+		err(2, "could not open %s for write", pam_config);
+
+	fprintf(out, LEGACY_CONTENTS);
+
+	(void) fclose(out);
+}
+
+static void
+store_pamline(pamline_t *add)
+{
+	if ((add->service && strlen(add->service) > 0) ||
+	    (add->copyfrom && strlen(add->copyfrom) > 0))
+		onlycomments = B_FALSE;
+
+	/*
+	 * If we find the end of various known header block strings,
+	 * and we've thus far only seen a block comment, then turf
+	 * all existing lines.
+	 */
+	if (all && onlycomments && add->commentfrom &&
+	    (strcmp(SENTINEL0, add->commentfrom) == 0 ||
+	    strcmp(SENTINEL1, add->commentfrom) == 0 ||
+	    strcmp(SENTINEL2, add->commentfrom) == 0)) {
+		pamline_t *pres, *t = all;
+		while (t != NULL) {
+			pres = t->next;
+			free(t);
+			t = pres;
+		}
+		all = NULL;
+		free(add);
+		return;
+	}
+
+	if (add->service != NULL)
+		store_service(add->service);
+
+	if (all == NULL) {
+		all = add;
+	} else {
+		pamline_t *t = all;
+		while (t != NULL) {
+			if (add->service != NULL && t->service == NULL) {
+				/* apply this service to all unclaimed lines */
+				t->service = add->service;
+			}
+			if (t->next == NULL) {
+				t->next = add;
+				break;
+			}
+			t = t->next;
+		}
+	}
+}
+
+static void
+open_pam_conf(char *filename)
+{
+	struct stat st;
+
+	fd = open(filename, O_RDONLY);
+	if (fd == -1) {
+		/* If there is no /etc/pam.conf, then silently exit. */
+		if (errno == ENOENT) {
+			if (verbose)
+				(void) fprintf(stderr, "no %s found;"
+				    " not running.\n", pam_config);
+			exit(0);
+		} else {
+			err(2, "could not open %s", filename);
+		}
+	}
+
+	if (fstat(fd, &st) == -1)
+		err(2, "could not stat %s", filename);
+	flen = st.st_size;
+
+	f = mmap(NULL, flen, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
+	if (f == MAP_FAILED)
+		err(2, "could not mmap %s", filename);
+}
+
+static void
+close_pam_conf(void)
+{
+	(void) munmap(f, flen);
+	(void) close(fd);
+}
+
+static pamline_t *
+new_pamline(void)
+{
+	pamline_t *pl = calloc(1, sizeof (pamline_t));
+	if (pl == NULL)
+		abort();
+	return (pl);
+}
+
+static void
+find_lines(void)
+{
+	char *pos;
+	int state = 0;
+	pamline_t *t = new_pamline();
+	boolean_t prelimwhitespace = B_FALSE;
+
+	t->copyfrom = f;
+	for (pos = f; pos < f + flen; pos++) {
+		switch (state) {
+		case 0:
+			switch (*pos) {
+			case '#':
+				*pos = '\0';
+
+				t->commentfrom = pos + 1;
+
+				prelimwhitespace = B_FALSE;
+				state = 1;
+				break;
+			case ' ':
+			case '\t':
+				*pos = '\0';
+
+				t->service = t->copyfrom;
+				t->copyfrom = pos + 1;
+
+				prelimwhitespace = B_TRUE;
+				state = 1;
+				break;
+			case '\n':
+				*pos = '\0';
+
+				store_pamline(t);
+
+				t = new_pamline();
+				t->copyfrom = pos + 1;
+				break;
+			}
+			break;
+		case 1:
+			switch (*pos) {
+			case ' ':
+			case '\t':
+				if (prelimwhitespace)
+					t->copyfrom++;
+				break;
+			case '\n':
+				*pos = '\0';
+
+				store_pamline(t);
+
+				t = new_pamline();
+				t->copyfrom = pos + 1;
+
+				state = 0;
+				break;
+			default:
+				prelimwhitespace = B_FALSE;
+			}
+		}
+	}
+}
+
+static void
+output_services(void)
+{
+	servicelist_t *s = services;
+
+	while (s != NULL) {
+		if (preview) {
+			(void) fprintf(stdout, "------------ %s/%s :\n",
+			    pam_config_dir, s->service);
+			print_service(stdout, s->service);
+			(void) fprintf(stdout, "\n");
+		} else {
+			write_service_file(s->service);
+		}
+		s = s->next;
+	}
+}
+
+int
+main(int argc, char **argv)
+{
+	int c;
+
+	while ((c = getopt(argc, argv, ":nvri:o:")) != -1) {
+		switch (c) {
+		case 'v':
+			verbose = B_TRUE;
+			break;
+		case 'n':
+			preview = B_TRUE;
+			break;
+		case 'r':
+			replace_original = B_TRUE;
+			break;
+		case 'i':
+			pam_config = optarg;
+			break;
+		case 'o':
+			pam_config_dir = optarg;
+			break;
+		case ':':
+			errx(1, "Option -%c requires an operand", optopt);
+			break;
+		case '?':
+			errx(1, "Unrecognised option: -%c", optopt);
+			break;
+		}
+	}
+
+	if (verbose) {
+		(void) fprintf(stderr, "input file: %s\n", pam_config);
+		(void) fprintf(stderr, "output dir: %s\n", pam_config_dir);
+	}
+
+	open_pam_conf(pam_config);
+	find_lines();
+
+	/*
+	 * If we haven't found any non-trivial lines, then exit now.
+	 */
+	if (onlycomments) {
+		if (verbose)
+			(void) fprintf(stderr, "trivial %s detected; not "
+			    "running.\n", pam_config);
+		goto done;
+	}
+
+	output_services();
+
+	if (!preview && replace_original)
+		write_legacy_file();
+
+done:
+	close_pam_conf();
+	return (0);
+}
--- old/usr/src/lib/libpam/Makefile	Sat Jun 30 22:01:39 2012
+++ new/usr/src/lib/libpam/Makefile	Sat Jun 30 22:01:39 2012
@@ -22,6 +22,8 @@
 # Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
+# Copyright 2012 Joshua M. Clulow <josh@sysmgr.org>
+#
 
 include ../Makefile.lib
 
@@ -37,7 +39,19 @@
 HDRDIR=		.
 
 # install pam.conf
-ETCFILES=	pam.conf
+ETCFILES=	pam.conf \
+		pam.d/cron \
+		pam.d/cups \
+		pam.d/gdm-autologin \
+		pam.d/krlogin \
+		pam.d/krsh \
+		pam.d/ktelnet \
+		pam.d/login \
+		pam.d/other \
+		pam.d/passwd \
+		pam.d/ppp \
+		pam.d/rlogin \
+		pam.d/rsh
 ROOTETC=	$(ROOT)/etc
 IETCFILES=	$(ETCFILES:%=$(ROOTETC)/%)
 
--- old/usr/src/lib/libpam/pam.conf	Sat Jun 30 22:01:39 2012
+++ new/usr/src/lib/libpam/pam.conf	Sat Jun 30 22:01:39 2012
@@ -1,135 +1,5 @@
 #
-# CDDL HEADER START
+# Legacy PAM configuration
 #
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-# PAM configuration
-#
-# Unless explicitly defined, all services use the modules
-# defined in the "other" section.
-#
-# Modules are defined with relative pathnames, i.e., they are
-# relative to /usr/lib/security/$ISA. Absolute path names, as
-# present in this file in previous releases are still acceptable.
-#
-# Authentication management
-#
-# login service (explicit because of pam_dial_auth)
-#
-login	auth requisite		pam_authtok_get.so.1
-login	auth required		pam_dhkeys.so.1
-login	auth required		pam_unix_cred.so.1
-login	auth required		pam_unix_auth.so.1
-login	auth required		pam_dial_auth.so.1
-#
-# rlogin service (explicit because of pam_rhost_auth)
-#
-rlogin	auth sufficient		pam_rhosts_auth.so.1
-rlogin	auth requisite		pam_authtok_get.so.1
-rlogin	auth required		pam_dhkeys.so.1
-rlogin	auth required		pam_unix_cred.so.1
-rlogin	auth required		pam_unix_auth.so.1
-#
-# Kerberized rlogin service
-#
-krlogin	auth required		pam_unix_cred.so.1
-krlogin	auth required		pam_krb5.so.1
-#
-# rsh service (explicit because of pam_rhost_auth,
-# and pam_unix_auth for meaningful pam_setcred)
-#
-rsh	auth sufficient		pam_rhosts_auth.so.1
-rsh	auth required		pam_unix_cred.so.1
-#
-# Kerberized rsh service
-#
-krsh	auth required		pam_unix_cred.so.1
-krsh	auth required		pam_krb5.so.1
-#
-# Kerberized telnet service
-#
-ktelnet	auth required		pam_unix_cred.so.1
-ktelnet	auth required		pam_krb5.so.1
-#
-# PPP service (explicit because of pam_dial_auth)
-#
-ppp	auth requisite		pam_authtok_get.so.1
-ppp	auth required		pam_dhkeys.so.1
-ppp	auth required		pam_unix_cred.so.1
-ppp	auth required		pam_unix_auth.so.1
-ppp	auth required		pam_dial_auth.so.1
-#
-# GDM Autologin (explicit because of pam_allow).  These need to be
-# here as there is no mechanism for packages to amend pam.conf as
-# they are installed.
-#
-gdm-autologin auth  required    pam_unix_cred.so.1
-gdm-autologin auth  sufficient  pam_allow.so.1
-#
-# Default definitions for Authentication management
-# Used when service name is not explicitly mentioned for authentication
-#
-other	auth requisite		pam_authtok_get.so.1
-other	auth required		pam_dhkeys.so.1
-other	auth required		pam_unix_cred.so.1
-other	auth required		pam_unix_auth.so.1
-#
-# passwd command (explicit because of a different authentication module)
-#
-passwd	auth required		pam_passwd_auth.so.1
-#
-# cron service (explicit because of non-usage of pam_roles.so.1)
-#
-cron	account required	pam_unix_account.so.1
-#
-# cups service (explicit because of non-usage of pam_roles.so.1)
-#
-cups	account	required	pam_unix_account.so.1
-#
-# GDM Autologin (explicit because of pam_allow) This needs to be here
-# as there is no mechanism for packages to amend pam.conf as they are
-# installed.
-#
-gdm-autologin account  sufficient  pam_allow.so.1
-#
-# Default definition for Account management
-# Used when service name is not explicitly mentioned for account management
-#
-other	account requisite	pam_roles.so.1
-other	account required	pam_unix_account.so.1
-#
-# Default definition for Session management
-# Used when service name is not explicitly mentioned for session management
-#
-other	session required	pam_unix_session.so.1
-#
-# Default definition for Password management
-# Used when service name is not explicitly mentioned for password management
-#
-other	password required	pam_dhkeys.so.1
-other	password requisite	pam_authtok_get.so.1
-other	password requisite	pam_authtok_check.so.1
-other	password required	pam_authtok_store.so.1
-#
-# Support for Kerberos V5 authentication and example configurations can
-# be found in the pam_krb5(5) man page under the "EXAMPLES" section.
-#
+# The shipped PAM configuration has moved from the legacy /etc/pam.conf
+# to the new /etc/pam.d model.  See pam.conf(4) for more information.
--- /dev/null	Sat Jun 30 22:01:39 2012
+++ new/usr/src/lib/libpam/pam.d/cron	Sat Jun 30 22:01:39 2012
@@ -0,0 +1,4 @@
+#
+# cron service (explicit because of non-usage of pam_roles.so.1)
+#
+cron	account required	pam_unix_account.so.1
--- /dev/null	Sat Jun 30 22:01:40 2012
+++ new/usr/src/lib/libpam/pam.d/cups	Sat Jun 30 22:01:40 2012
@@ -0,0 +1,4 @@
+#
+# cups service (explicit because of non-usage of pam_roles.so.1)
+#
+cups	account	required	pam_unix_account.so.1
--- /dev/null	Sat Jun 30 22:01:40 2012
+++ new/usr/src/lib/libpam/pam.d/gdm-autologin	Sat Jun 30 22:01:40 2012
@@ -0,0 +1,10 @@
+#
+# GDM Autologin (explicit because of pam_allow).  These need to be
+# here as historically there has been no mechanism for packages to
+# amend pam.conf as they are installed.  It will continue to be
+# shipped until downstream distributions pick it up instead.
+#
+gdm-autologin auth  required    pam_unix_cred.so.1
+gdm-autologin auth  sufficient  pam_allow.so.1
+#
+gdm-autologin account  sufficient  pam_allow.so.1
--- /dev/null	Sat Jun 30 22:01:40 2012
+++ new/usr/src/lib/libpam/pam.d/krlogin	Sat Jun 30 22:01:40 2012
@@ -0,0 +1,5 @@
+#
+# Kerberized rlogin service
+#
+krlogin	auth required		pam_unix_cred.so.1
+krlogin	auth required		pam_krb5.so.1
--- /dev/null	Sat Jun 30 22:01:40 2012
+++ new/usr/src/lib/libpam/pam.d/krsh	Sat Jun 30 22:01:40 2012
@@ -0,0 +1,5 @@
+#
+# Kerberized rsh service
+#
+krsh	auth required		pam_unix_cred.so.1
+krsh	auth required		pam_krb5.so.1
--- /dev/null	Sat Jun 30 22:01:40 2012
+++ new/usr/src/lib/libpam/pam.d/ktelnet	Sat Jun 30 22:01:40 2012
@@ -0,0 +1,5 @@
+#
+# Kerberized telnet service
+#
+ktelnet	auth required		pam_unix_cred.so.1
+ktelnet	auth required		pam_krb5.so.1
--- /dev/null	Sat Jun 30 22:01:40 2012
+++ new/usr/src/lib/libpam/pam.d/login	Sat Jun 30 22:01:40 2012
@@ -0,0 +1,8 @@
+#
+# login service (explicit because of pam_dial_auth)
+#
+login	auth requisite		pam_authtok_get.so.1
+login	auth required		pam_dhkeys.so.1
+login	auth required		pam_unix_cred.so.1
+login	auth required		pam_unix_auth.so.1
+login	auth required		pam_dial_auth.so.1
--- /dev/null	Sat Jun 30 22:01:40 2012
+++ new/usr/src/lib/libpam/pam.d/other	Sat Jun 30 22:01:40 2012
@@ -0,0 +1,20 @@
+#
+# Default definitions
+#
+# Used when a module type (e.g. "auth") is not explicitly configured for a
+# particular service (e.g. "sudo").
+#
+other	auth requisite		pam_authtok_get.so.1
+other	auth required		pam_dhkeys.so.1
+other	auth required		pam_unix_cred.so.1
+other	auth required		pam_unix_auth.so.1
+#
+other	account requisite	pam_roles.so.1
+other	account required	pam_unix_account.so.1
+#
+other	session required	pam_unix_session.so.1
+#
+other	password required	pam_dhkeys.so.1
+other	password requisite	pam_authtok_get.so.1
+other	password requisite	pam_authtok_check.so.1
+other	password required	pam_authtok_store.so.1
--- /dev/null	Sat Jun 30 22:01:41 2012
+++ new/usr/src/lib/libpam/pam.d/passwd	Sat Jun 30 22:01:41 2012
@@ -0,0 +1,4 @@
+#
+# passwd command (explicit because of a different authentication module)
+#
+passwd	auth required		pam_passwd_auth.so.1
--- /dev/null	Sat Jun 30 22:01:41 2012
+++ new/usr/src/lib/libpam/pam.d/ppp	Sat Jun 30 22:01:41 2012
@@ -0,0 +1,8 @@
+#
+# PPP service (explicit because of pam_dial_auth)
+#
+ppp	auth requisite		pam_authtok_get.so.1
+ppp	auth required		pam_dhkeys.so.1
+ppp	auth required		pam_unix_cred.so.1
+ppp	auth required		pam_unix_auth.so.1
+ppp	auth required		pam_dial_auth.so.1
--- /dev/null	Sat Jun 30 22:01:41 2012
+++ new/usr/src/lib/libpam/pam.d/rlogin	Sat Jun 30 22:01:41 2012
@@ -0,0 +1,8 @@
+#
+# rlogin service (explicit because of pam_rhost_auth)
+#
+rlogin	auth sufficient		pam_rhosts_auth.so.1
+rlogin	auth requisite		pam_authtok_get.so.1
+rlogin	auth required		pam_dhkeys.so.1
+rlogin	auth required		pam_unix_cred.so.1
+rlogin	auth required		pam_unix_auth.so.1
--- /dev/null	Sat Jun 30 22:01:41 2012
+++ new/usr/src/lib/libpam/pam.d/rsh	Sat Jun 30 22:01:41 2012
@@ -0,0 +1,6 @@
+#
+# rsh service (explicit because of pam_rhost_auth,
+# and pam_unix_auth for meaningful pam_setcred)
+#
+rsh	auth sufficient		pam_rhosts_auth.so.1
+rsh	auth required		pam_unix_cred.so.1
--- old/usr/src/lib/libpam/pam_framework.c	Sat Jun 30 22:01:41 2012
+++ new/usr/src/lib/libpam/pam_framework.c	Sat Jun 30 22:01:41 2012
@@ -21,6 +21,8 @@
 /*
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ *
+ * Copyright 2012 Joshua M. Clulow <josh@sysmgr.org>
  */
 
 #include <syslog.h>
@@ -80,11 +82,11 @@
 static int	load_function(void *, char *, int (**func)());
 
 /* functions to read and store the pam.conf configuration file */
-static int	open_pam_conf(struct pam_fh **, pam_handle_t *, char *);
+static int	open_pam_conf(struct pam_fh **, pam_handle_t *, char *, int);
 static void	close_pam_conf(struct pam_fh *);
-static int	read_pam_conf(pam_handle_t *, char *);
+static int	read_pam_conf(pam_handle_t *, char *, char *, int);
 static int 	get_pam_conf_entry(struct pam_fh *, pam_handle_t *,
-    pamtab_t **);
+    pamtab_t **, char *, int);
 static char	*read_next_token(char **);
 static char	*nextline(struct pam_fh *, pam_handle_t *, int *);
 static int	verify_pam_conf(pamtab_t *, char *);
@@ -1010,15 +1012,38 @@
 	int	success = 0;
 	pamtab_t *modulep;
 	int	(*sm_func)();
+	char	*service;
+	char	*service_file;
+	int	shardfile = 1;
 
 	if (pamh == NULL)
 		return (PAM_SYSTEM_ERR);
 
-	/* read initial entries from pam.conf */
-	if ((err = read_pam_conf(pamh, PAM_CONFIG)) != PAM_SUCCESS) {
-		return (err);
+	(void) pam_get_item(pamh, PAM_SERVICE, (void **)&service);
+	if (service == NULL || *service == '\0') {
+		__pam_log(LOG_AUTH | LOG_ERR, "No service name");
+		return (PAM_SYSTEM_ERR);
 	}
 
+	/* read initial entries from /etc/pam.d/<service> */
+	if (asprintf(&service_file, "%s%s", PAM_CONFIG_DIR, service) < 0)
+		return (PAM_SYSTEM_ERR);
+	if ((err = read_pam_conf(pamh, service_file, service, shardfile))
+	    != PAM_SUCCESS) {
+		shardfile = 0;
+		pam_trace(PAM_DEBUG_CONF, "run_stack[%d:%s]: can't read "
+		    "service-specific conf %s", pamh->include_depth,
+		    pam_trace_cname(pamh), modulep->module_path, service_file);
+
+		/* fall back to reading initial entries from pam.conf */
+		if ((err = read_pam_conf(pamh, PAM_CONFIG, service, shardfile))
+		    != PAM_SUCCESS) {
+			return (err);
+		}
+	}
+	free(service_file);
+	service_file = NULL;
+
 	if ((modulep =
 	    pamh->pam_conf_info[pamh->include_depth][type]) == NULL) {
 		__pam_log(LOG_AUTH | LOG_ERR, "%s no initial module present",
@@ -1053,7 +1078,8 @@
 				goto exit_return;
 			}
 			if ((err = read_pam_conf(pamh,
-			    modulep->module_path)) != PAM_SUCCESS) {
+			    modulep->module_path, service, shardfile))
+			    != PAM_SUCCESS) {
 				__pam_log(LOG_AUTH | LOG_ERR,
 				    "run_stack[%d:%s]: can't read included "
 				    "conf %s", pamh->include_depth,
@@ -1911,16 +1937,18 @@
  */
 
 static int
-open_pam_conf(struct pam_fh **pam_fh, pam_handle_t *pamh, char *config)
+open_pam_conf(struct pam_fh **pam_fh, pam_handle_t *pamh, char *config,
+    int shardfile)
 {
 	struct stat64	stb;
 	int		fd;
 
 	if ((fd = open(config, O_RDONLY)) == -1) {
-		__pam_log(LOG_AUTH | LOG_ALERT,
-		    "open_pam_conf[%d:%s]: open(%s) failed: %s",
-		    pamh->include_depth, pam_trace_cname(pamh), config,
-		    strerror(errno));
+		if (!shardfile)
+			__pam_log(LOG_AUTH | LOG_ALERT,
+			    "open_pam_conf[%d:%s]: open(%s) failed: %s",
+			    pamh->include_depth, pam_trace_cname(pamh), config,
+			    strerror(errno));
 		return (0);
 	}
 	/* Check the ownership and file modes */
@@ -1988,14 +2016,14 @@
  */
 
 static int
-read_pam_conf(pam_handle_t *pamh, char *config)
+read_pam_conf(pam_handle_t *pamh, char *config, char *service, int shardfile)
 {
 	struct pam_fh	*pam_fh;
 	pamtab_t	*pamentp;
 	pamtab_t	*tpament;
-	char		*service;
 	int		error;
 	int		i = pamh->include_depth;	/* include depth */
+	int		j;
 	/*
 	 * service types:
 	 * error (-1), "auth" (0), "account" (1), "session" (2), "password" (3)
@@ -2002,22 +2030,16 @@
 	 */
 	int service_found[PAM_NUM_MODULE_TYPES+1] = {0, 0, 0, 0, 0};
 
-	(void) pam_get_item(pamh, PAM_SERVICE, (void **)&service);
-	if (service == NULL || *service == '\0') {
-		__pam_log(LOG_AUTH | LOG_ERR, "No service name");
-		return (PAM_SYSTEM_ERR);
-	}
-
 	pamh->pam_conf_name[i] = strdup(config);
 	pam_trace(PAM_DEBUG_CONF, "read_pam_conf[%d:%s](%p) open(%s)",
 	    i, pam_trace_cname(pamh), (void *)pamh, config);
-	if (open_pam_conf(&pam_fh, pamh, config) == 0) {
+	if (open_pam_conf(&pam_fh, pamh, config, shardfile) == 0) {
 		return (PAM_SYSTEM_ERR);
 	}
 
 	while ((error =
-	    get_pam_conf_entry(pam_fh, pamh, &pamentp)) == PAM_SUCCESS &&
-	    pamentp) {
+	    get_pam_conf_entry(pam_fh, pamh, &pamentp, service, shardfile))
+	    == PAM_SUCCESS && pamentp) {
 
 		/* See if entry is this service and valid */
 		if (verify_pam_conf(pamentp, service)) {
@@ -2121,6 +2143,44 @@
 			free_pamconf(pamentp);
 		}
 	}
+
+	/*
+	 * If this is a shard file and we have no entries for this
+	 * module type (e.g. "account"), then generate a single
+	 * "include" rule for the shard file "other" as a fallback.
+	 */
+	if (shardfile && strcasecmp(service, "other") != 0) {
+		for (j = 0; j < PAM_NUM_MODULE_TYPES; j++) {
+			if (service_found[j + 1] == 0 &&
+			    pamh->pam_conf_info[i][j] == NULL) {
+				pamtab_t *pe = calloc(1, sizeof (pamtab_t));
+
+				pam_trace(PAM_DEBUG_CONF, "read_pam_conf(%p):"
+				    "falling back to \"other\" for module "
+				    "type \"%s\" in service \"%s\"",
+				    (void *)pamh, pam_snames[j], service);
+				if (pe == NULL) {
+					error = PAM_SYSTEM_ERR;
+					__pam_log(LOG_AUTH | LOG_ERR,
+					    "calloc: out of memory");
+					goto out;
+				}
+				pe->pam_service = strdup(service);
+				pe->pam_type = j;
+				pe->pam_flag = PAM_INCLUDE;
+				if (asprintf(&pe->module_path, "%s%s",
+				    PAM_CONFIG_DIR, "other") < 0) {
+					free(pe);
+					error = PAM_SYSTEM_ERR;
+					__pam_log(LOG_AUTH | LOG_ERR,
+					    "asprintf: out of memory");
+					goto out;
+				}
+				pamh->pam_conf_info[i][j] = pe;
+			}
+		}
+	}
+
 out:
 	(void) close_pam_conf(pam_fh);
 	if (error != PAM_SUCCESS)
@@ -2133,7 +2193,8 @@
  */
 
 static int
-get_pam_conf_entry(struct pam_fh *pam_fh, pam_handle_t *pamh, pamtab_t **pam)
+get_pam_conf_entry(struct pam_fh *pam_fh, pam_handle_t *pamh, pamtab_t **pam,
+    char *service, int shardfile)
 {
 	char		*cp, *arg;
 	int		argc;
@@ -2165,17 +2226,28 @@
 	pam_trace(PAM_DEBUG_CONF,
 	    "pam.conf[%s] entry:\t%s", pam_trace_cname(pamh), current_line);
 
-	/* get service name (e.g. login, su, passwd) */
-	if ((arg = read_next_token(&cp)) == 0) {
-		__pam_log(LOG_AUTH | LOG_CRIT,
-		    "illegal pam.conf[%s] entry: %s: missing SERVICE NAME",
-		    pam_trace_cname(pamh), current_line);
-		goto out;
+	if (shardfile) {
+		/*
+		 * If this is an /etc/pam.d shard file, then the service name
+		 * comes from the file name of the shard.
+		 */
+		if (((*pam)->pam_service = strdup(service)) == 0) {
+			__pam_log(LOG_AUTH | LOG_ERR, "strdup: out of memory");
+			goto out;
+		}
+	} else {
+		/* get service name (e.g. login, su, passwd) */
+		if ((arg = read_next_token(&cp)) == 0) {
+			__pam_log(LOG_AUTH | LOG_CRIT,
+			    "illegal pam.conf[%s] entry: %s: missing SERVICE "
+			    "NAME", pam_trace_cname(pamh), current_line);
+			goto out;
+		}
+		if (((*pam)->pam_service = strdup(arg)) == 0) {
+			__pam_log(LOG_AUTH | LOG_ERR, "strdup: out of memory");
+			goto out;
+		}
 	}
-	if (((*pam)->pam_service = strdup(arg)) == 0) {
-		__pam_log(LOG_AUTH | LOG_ERR, "strdup: out of memory");
-		goto out;
-	}
 
 	/* get module type (e.g. authentication, acct mgmt) */
 	if ((arg = read_next_token(&cp)) == 0) {
@@ -2240,24 +2312,28 @@
 		goto out;
 	}
 	if (arg[0] != '/') {
-		size_t len;
+		int ret;
 		/*
 		 * If module path does not start with "/", then
 		 * prepend PAM_LIB_DIR (/usr/lib/security/).
 		 */
-		/* sizeof (PAM_LIB_DIR) has room for '\0' */
-		len = sizeof (PAM_LIB_DIR) + sizeof (PAM_ISA_DIR) + strlen(arg);
-		if (((*pam)->module_path = malloc(len)) == NULL) {
-			__pam_log(LOG_AUTH | LOG_ERR, "strdup: out of memory");
-			goto out;
-		}
 		if ((*pam)->pam_flag & PAM_INCLUDE) {
-			(void) snprintf((*pam)->module_path, len, "%s%s",
-			    PAM_LIB_DIR, arg);
+			/*
+			 * If this is an /etc/pam.d shard, we want to get
+			 * included files from /etc/pam.d rather than
+			 * /usr/lib/security.
+			 */
+			ret = asprintf(&(*pam)->module_path, "%s%s",
+			    (shardfile ? PAM_CONFIG_DIR : PAM_LIB_DIR), arg);
 		} else {
-			(void) snprintf((*pam)->module_path, len, "%s%s%s",
+			ret = asprintf(&(*pam)->module_path, "%s%s%s",
 			    PAM_LIB_DIR, PAM_ISA_DIR, arg);
 		}
+		if (ret < 0) {
+			__pam_log(LOG_AUTH | LOG_ERR,
+			    "asprintf: out of memory");
+			goto out;
+		}
 	} else {
 		/* Full path provided for module */
 		char *isa;
--- old/usr/src/lib/libpam/pam_impl.h	Sat Jun 30 22:01:42 2012
+++ new/usr/src/lib/libpam/pam_impl.h	Sat Jun 30 22:01:42 2012
@@ -21,6 +21,8 @@
 /*
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ *
+ * Copyright 2012 Joshua M. Clulow <josh@sysmgr.org>
  */
 
 #ifndef	_PAM_IMPL_H
@@ -37,6 +39,7 @@
 #define	PAMTXD		"SUNW_OST_SYSOSPAM"
 
 #define	PAM_CONFIG	"/etc/pam.conf"
+#define	PAM_CONFIG_DIR	"/etc/pam.d/"
 #define	PAM_ISA		"/$ISA/"
 #define	PAM_LIB_DIR	"/usr/lib/security/"
 #ifdef	_LP64
--- old/usr/src/man/man4/Makefile	Sat Jun 30 22:01:42 2012
+++ new/usr/src/man/man4/Makefile	Sat Jun 30 22:01:42 2012
@@ -236,6 +236,7 @@
 		md.cf.4				\
 		mdi_ib_cache.4			\
 		mdi_scsi_vhci_cache.4		\
+		pam.d.4				\
 		pci_unitaddr_persistent.4	\
 		pcie.4				\
 		qop.4				\
@@ -277,6 +278,8 @@
 
 qop.4				:= SOSRC = man4/mech.4
 
+pam.d.4				:= SOSRC = man4/pam.conf.4
+
 pcie.4				:= SOSRC = man4/pci.4
 
 sendmail.cf.4			:= SOSRC = man4/sendmail.4
--- old/usr/src/man/man4/pam.conf.4	Sat Jun 30 22:01:43 2012
+++ new/usr/src/man/man4/pam.conf.4	Sat Jun 30 22:01:43 2012
@@ -1,14 +1,18 @@
 '\" te
 .\" Copyright (C) 2006, Sun Microsystems, Inc. All Rights Reserved.
+.\" Copyright 2012 Joshua M. Clulow <josh@sysmgr.org>
 .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License").  You may not use this file except in compliance with the License.
 .\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing.  See the License for the specific language governing permissions and limitations under the License.
 .\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE.  If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
-.TH PAM.CONF 4 "Jun 19, 2006"
+.TH PAM.CONF 4 "Jun 30, 2012"
 .SH NAME
-pam.conf \- configuration file for pluggable authentication modules
+pam.d, pam.conf \- configuration for pluggable authentication modules
 .SH SYNOPSIS
 .LP
 .nf
+\fB/etc/pam.d\fR
+.fi
+.nf
 \fB/etc/pam.conf\fR
 .fi
 
@@ -15,10 +19,12 @@
 .SH DESCRIPTION
 .sp
 .LP
-\fBpam.conf\fR is the configuration file for the Pluggable Authentication
-Module architecture, or \fBPAM\fR. A \fBPAM\fR module provides functionality
+
+\fB/etc/pam.d\fR is the configuration directory for the Pluggable Authentication
+Module architecture, or \fBPAM\fR.  A \fBPAM\fR module provides functionality
 for one or more of four possible services: authentication, account management,
-session management, and password management.
+session management, and password management.  The configuration directory
+contains per-service 'shards' of the legacy, monolithic \fBpam.conf\fR file.
 .sp
 .ne 2
 .na
@@ -82,6 +88,14 @@
 
 .sp
 .LP
+If shard files are used in \fB/etc/pam.d\fR instead of the monolithic
+\fBpam.conf\fR file, then the \fIservice_name\fR column is not present in
+those files.  The \fIservice_name\fR is, instead, derived from the
+filename of the shard.  As an example, for the service 'login' the configuration
+would now be in \fB/etc/pam.d/login\fR and would omit the first column
+(previously containing 'login').
+.sp
+.LP
 The following is an example of a \fBpam.conf\fR configuration file with support
 for authentication, account management, session management and password
 management modules (See the \fBpam.conf\fR file that is shipped with your
@@ -132,9 +146,10 @@
 The \fImodule_path\fR field specifies the relative pathname to a shared library
 object, or an included \fBPAM\fR configuration file, which implements the
 service functionality. If the pathname is not absolute, shared library objects
-are assumed to be relative to \fB/usr/lib/security/$ISA/\fR, and included
-\fBPAM\fR configuration files are assumed to be relative to
-\fB/usr/lib/security/\fR.
+are assumed to be relative to \fB/usr/lib/security/$ISA/\fR, and \fBPAM\fR
+configuration files included in shards are assumed to be relative to
+\fB/etc/pam.d/\fR, or \fB/usr/lib/security/\fB if included in the legacy
+\fBpam.conf\fR.
 .sp
 .LP
 The \fBISA\fR token is replaced by an implementation defined directory name
@@ -345,6 +360,15 @@
 Configuration file
 .RE
 
+.sp
+.ne 2
+.na
+\fB\fB/etc/pam.d\fR\fR
+.ad
+.RS 29n
+Configuration directory
+.RE
+
 .sp
 .ne 2
 .na
--- old/usr/src/pkg/manifests/SUNWcs.man4.inc	Sat Jun 30 22:01:43 2012
+++ new/usr/src/pkg/manifests/SUNWcs.man4.inc	Sat Jun 30 22:01:43 2012
@@ -80,6 +80,7 @@
 file path=usr/share/man/man4/nsswitch.conf.4
 file path=usr/share/man/man4/packingrules.4
 file path=usr/share/man/man4/pam.conf.4
+file path=usr/share/man/man4/pam.d.4
 file path=usr/share/man/man4/passwd.4
 file path=usr/share/man/man4/pci_unitaddr_persistent.4
 file path=usr/share/man/man4/phones.4
--- old/usr/src/pkg/manifests/SUNWcs.mf	Sat Jun 30 22:01:43 2012
+++ new/usr/src/pkg/manifests/SUNWcs.mf	Sat Jun 30 22:01:43 2012
@@ -63,6 +63,7 @@
 dir path=etc/net/ticots group=sys
 dir path=etc/net/ticotsord group=sys
 dir path=etc/opt group=sys
+dir path=etc/pam.d group=sys
 dir path=etc/rc0.d group=sys
 dir path=etc/rc1.d group=sys
 dir path=etc/rc2.d group=sys
@@ -408,6 +409,18 @@
 file path=etc/nsswitch.files group=sys
 file path=etc/nsswitch.ldap group=sys
 file path=etc/pam.conf group=sys preserve=true
+file path=etc/pam.d/cron group=sys preserve=true
+file path=etc/pam.d/cups group=sys preserve=true
+file path=etc/pam.d/gdm-autologin group=sys preserve=true
+file path=etc/pam.d/krlogin group=sys preserve=true
+file path=etc/pam.d/krsh group=sys preserve=true
+file path=etc/pam.d/ktelnet group=sys preserve=true
+file path=etc/pam.d/login group=sys preserve=true
+file path=etc/pam.d/other group=sys preserve=true
+file path=etc/pam.d/passwd group=sys preserve=true
+file path=etc/pam.d/ppp group=sys preserve=true
+file path=etc/pam.d/rlogin group=sys preserve=true
+file path=etc/pam.d/rsh group=sys preserve=true
 file path=etc/passwd group=sys preserve=true
 file path=etc/profile group=sys preserve=true
 file path=etc/project group=sys preserve=true
@@ -561,6 +574,7 @@
 file path=lib/svc/manifest/system/logadm-upgrade.xml group=sys mode=0444
 file path=lib/svc/manifest/system/manifest-import.xml group=sys mode=0444
 file path=lib/svc/manifest/system/name-service-cache.xml group=sys mode=0444
+file path=lib/svc/manifest/system/pam-upgrade.xml group=sys mode=0444
 file path=lib/svc/manifest/system/pfexecd.xml group=sys mode=0444
 file path=lib/svc/manifest/system/rbac.xml group=sys mode=0444
 file path=lib/svc/manifest/system/rmtmpfiles.xml group=sys mode=0444
@@ -600,6 +614,7 @@
 file path=lib/svc/method/net-physical mode=0555
 file path=lib/svc/method/net-routing-setup mode=0555
 file path=lib/svc/method/net-svc mode=0555
+file path=lib/svc/method/pam-upgrade mode=0555
 file path=lib/svc/method/rmtmpfiles mode=0555
 file path=lib/svc/method/rpc-bind mode=0555
 file path=lib/svc/method/svc-allocate mode=0555
@@ -1377,6 +1392,7 @@
 file path=usr/sbin/nscd mode=0555
 file path=usr/sbin/nwamadm mode=0555
 file path=usr/sbin/nwamcfg mode=0555
+file path=usr/sbin/pamconv group=sys mode=0555
 file path=usr/sbin/pmadm group=sys mode=0555
 file path=usr/sbin/praudit mode=0555
 $(i386_ONLY)file path=usr/sbin/prtdiag group=sys mode=2755
