--- old/usr/src/cmd/passwd/passwd.c	Mon Jun 22 09:35:36 2015
+++ new/usr/src/cmd/passwd/passwd.c	Mon Jun 22 09:35:36 2015
@@ -30,6 +30,9 @@
 /*	  All Rights Reserved	*/
 
 /*
+ * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+ */
+/*
  * passwd is a program whose sole purpose is to manage
  * the password file, map, or table. It allows system administrator
  * to add, change and display password attributes.
@@ -84,6 +87,7 @@
 #define	HFLAG 0x1000		/* change home directory */
 #define	XFLAG 0x2000		/* no login */
 #define	UFLAG 0x4000		/* unlock user's password */
+#define	STFLAG 0x6000		/* read the password from stdin */
 
 #define	NONAGEFLAG	(EFLAG | GFLAG | HFLAG)
 #define	AGEFLAG	(LFLAG | FFLAG | MFLAG | NFLAG | WFLAG | XFLAG | UFLAG)
@@ -178,6 +182,8 @@
 static long		maxdate;	/* password aging information */
 static int		passwd_conv(int, struct pam_message **,
 			    struct pam_response **, void *);
+static int		stdin_conv(int, struct pam_message **,
+			    struct pam_response **, void *);
 static struct pam_conv	pam_conv = {passwd_conv, NULL};
 static pam_handle_t	*pamh;		/* Authentication handle */
 static char		*usrname;	/* user whose attribute we update */
@@ -234,8 +240,9 @@
 	char	*input;
 	int	tries = 1;
 	int	updated_reps;
+	ssize_t s;
+	char	st_pass[PASS_MAX];
 
-
 	if ((prognamep = strrchr(argv[0], '/')) != NULL)
 		++prognamep;
 	else
@@ -294,6 +301,16 @@
 		usrname = argv[optind];
 	}
 
+	if (flag == STFLAG) {
+		if ((s = read(STDIN_FILENO, st_pass, sizeof (st_pass))) <= 0)
+			passwd_exit(FMERR);
+
+		st_pass[s - 1] = '\0';
+		if ((pam_conv.appdata_ptr = strdup(st_pass)) == NULL)
+			passwd_exit(FMERR);
+		pam_conv.conv = stdin_conv;
+	}
+
 	if (pam_start("passwd", usrname, &pam_conv, &pamh) != PAM_SUCCESS) {
 		passwd_exit(NOPERM);
 	}
@@ -362,7 +379,7 @@
 		break;
 	}
 
-	if (flag == 0) {			/* changing user password */
+	if (flag == STFLAG || flag == 0) {	/* changing user password */
 		int	chk_authtok = 0;	/* check password strength */
 
 		dprintf1("call pam_chauthtok() repository name =%s\n",
@@ -688,7 +705,7 @@
 
 	flag = 0;
 
-	while ((opt = getopt(argc, argv, "r:aldefghsux:n:w:N")) != EOF) {
+	while ((opt = getopt(argc, argv, "r:aldefghsux:n:w:N:S")) != EOF) {
 		switch (opt) {
 
 		case 'r': /* Repository Specified */
@@ -740,7 +757,7 @@
 				retval = NOPERM;
 				return (FAIL);
 			}
-			if (flag & (LFLAG|SAFLAG|DFLAG|XFLAG|UFLAG)) {
+			if (flag & (LFLAG|SAFLAG|DFLAG|XFLAG|UFLAG|STFLAG)) {
 				rusage();
 				retval = BADOPT;
 				return (FAIL);
@@ -772,7 +789,7 @@
 			if ((IS_FILES(repository) || IS_LDAP(repository)) &&
 			    ((retval = ckuid()) != SUCCESS))
 				return (FAIL);
-			if (flag & (MUTEXFLAG|NONAGEFLAG)) {
+			if (flag & (MUTEXFLAG|NONAGEFLAG|STFLAG)) {
 				rusage();	/* exit */
 				retval = BADOPT;
 				return (FAIL);
@@ -804,7 +821,7 @@
 			if ((IS_FILES(repository) || IS_LDAP(repository)) &&
 			    ((retval = ckuid()) != SUCCESS))
 				return (FAIL);
-			if (flag & (MUTEXFLAG|NONAGEFLAG)) {
+			if (flag & (MUTEXFLAG|NONAGEFLAG|STFLAG)) {
 				rusage();	/* exit */
 				retval = BADOPT;
 				return (FAIL);
@@ -836,7 +853,7 @@
 			if ((IS_FILES(repository) || IS_LDAP(repository)) &&
 			    ((retval = ckuid()) != SUCCESS))
 				return (FAIL);
-			if (flag & (MUTEXFLAG|NONAGEFLAG)) {
+			if (flag & (MUTEXFLAG|NONAGEFLAG|STFLAG)) {
 				rusage();	/* exit */
 				retval = BADOPT;
 				return (FAIL);
@@ -871,7 +888,7 @@
 				retval = NOPERM;
 				return (FAIL);
 			}
-			if (flag & (SAFLAG|MFLAG|NONAGEFLAG)) {
+			if (flag & (SAFLAG|MFLAG|NONAGEFLAG|STFLAG)) {
 				retval = BADOPT;
 				return (FAIL);
 			}
@@ -910,7 +927,7 @@
 			if ((IS_FILES(repository) || IS_LDAP(repository)) &&
 			    ((retval = ckuid()) != SUCCESS))
 				return (FAIL);
-			if (flag & (SAFLAG|NFLAG|NONAGEFLAG)) {
+			if (flag & (SAFLAG|NFLAG|NONAGEFLAG|STFLAG)) {
 				retval = BADOPT;
 				return (FAIL);
 			}
@@ -951,7 +968,7 @@
 				retval = NOPERM;
 				return (FAIL);
 			}
-			if (flag & (SAFLAG|WFLAG|NONAGEFLAG)) {
+			if (flag & (SAFLAG|WFLAG|NONAGEFLAG|STFLAG)) {
 				retval = BADOPT;
 				return (FAIL);
 			}
@@ -1052,7 +1069,7 @@
 			if ((IS_FILES(repository) || IS_LDAP(repository)) &&
 			    ((retval = ckuid()) != SUCCESS))
 				return (FAIL);
-			if (flag & (SAFLAG|FFLAG|NONAGEFLAG)) {
+			if (flag & (SAFLAG|FFLAG|NONAGEFLAG|STFLAG)) {
 				retval = BADOPT;
 				return (FAIL);
 			}
@@ -1066,7 +1083,7 @@
 			if (repository.type == NULL)
 				repository = __REPFILES;
 
-			if (flag & (EFLAG|SAFLAG|AGEFLAG)) {
+			if (flag & (EFLAG|SAFLAG|AGEFLAG|STFLAG)) {
 				retval = BADOPT;
 				return (FAIL);
 			}
@@ -1087,7 +1104,7 @@
 				retval = NOPERM;
 				return (FAIL);
 			}
-			if (flag & (GFLAG|SAFLAG|AGEFLAG)) {
+			if (flag & (GFLAG|SAFLAG|AGEFLAG|STFLAG)) {
 				retval = BADOPT;
 				return (FAIL);
 			}
@@ -1114,13 +1131,24 @@
 				return (FAIL);
 			}
 
-			if (flag & (HFLAG|SAFLAG|AGEFLAG)) {
+			if (flag & (HFLAG|SAFLAG|AGEFLAG|STFLAG)) {
 				retval = BADOPT;
 				return (FAIL);
 			}
 			flag |= HFLAG;
 			break;
-
+		case 'S':
+			if (ckuid() != SUCCESS) {
+				retval = NOPERM;
+				return (FAIL);
+			}
+			if (flag & (MUTEXFLAG|NONAGEFLAG|AGEFLAG)) {
+				rusage();	/* exit */
+				retval = BADOPT;
+				return (FAIL);
+			}
+			flag |= STFLAG;
+			break;
 		case '?':
 			rusage();
 			retval = BADOPT;
@@ -1673,6 +1701,57 @@
 }
 
 /*
+ *
+ * stdin_conv():
+ *      This is the conv function called for reading
+ *      the password from standard input.
+ *
+ */
+/*ARGSUSED*/
+static int
+stdin_conv(int num_msg, struct pam_message **msg,
+	    struct pam_response **response, void *appdata_ptr)
+{
+	struct pam_response *reply = NULL;
+	int			replies = 0;
+
+	if (num_msg <= 0)
+		return (PAM_CONV_ERR);
+
+	reply = calloc(num_msg, sizeof (struct pam_response));
+	if (reply == NULL)
+		return (PAM_BUF_ERR);
+
+	for (replies = 0; replies < num_msg; replies ++) {
+		reply[replies].resp = NULL;
+		reply[replies].resp_retcode = PAM_SUCCESS;
+		switch (msg[replies]->msg_style) {
+		case PAM_PROMPT_ECHO_OFF:
+			reply[replies].resp = strdup(appdata_ptr);
+			if (reply[replies].resp == NULL)
+				goto err;
+			break;
+		case PAM_PROMPT_ECHO_ON:
+		case PAM_ERROR_MSG:
+		case PAM_TEXT_INFO:
+			reply[replies].resp = strdup("");
+			if (reply[replies].resp == NULL)
+				goto err;
+			break;
+		default:
+			free(reply);
+			return (PAM_CONV_ERR);
+		}
+	}
+	*response = reply;
+	return (PAM_SUCCESS);
+
+err:
+	free(reply);
+	return (PAM_BUF_ERR);
+}
+
+/*
  * 		Utilities Functions
  */
 
@@ -1775,5 +1854,6 @@
 	MSG("\tpasswd -r ldap -s [name]\n");
 	MSG("\tpasswd -r ldap [-l|-N|-u] [-f] [-n min] [-w warn] "
 	    "[-x max] name\n");
+	MSG("\tpasswd -S [name]\n");
 #undef MSG
 }
--- old/usr/src/man/man1/passwd.1	Mon Jun 22 09:35:36 2015
+++ new/usr/src/man/man1/passwd.1	Mon Jun 22 09:35:36 2015
@@ -1,10 +1,11 @@
 '\" te
 .\" Copyright 1989 AT&T
 .\" Copyright (c) 2009, Sun Microsystems, Inc. All Rights Reserved.
+.\" Copyright 2015 Nexenta Systems, Inc. All rights reserved.
 .\" 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 PASSWD 1 "May 31, 2013"
+.TH PASSWD 1 "Jun 18, 2015"
 .SH NAME
 passwd \- change login password and password attributes
 .SH SYNOPSIS
@@ -80,8 +81,12 @@
      [\fB-x\fR \fImax\fR] [\fB-D\fR \fIdomainname\fR] \fIname\fR
 .fi
 
+.LP
+.nf
+\fBpasswd\fR \fB-S\fR [\fIname\fR]
+.fi
+
 .SH DESCRIPTION
-.sp
 .LP
 The \fBpasswd\fR command changes the password or lists password attributes
 associated with the user's login \fIname\fR. Additionally, privileged users can
@@ -367,7 +372,6 @@
 .RE
 
 .SS "Security"
-.sp
 .LP
 \fBpasswd\fR uses \fBpam\fR(3PAM) for password change. It calls PAM with a
 service name \fBpasswd\fR and uses service module type \fBauth\fR for
@@ -379,7 +383,6 @@
 \fBcron\fR(1M)). The \fB-N\fR option can be used to disallow password based
 login, while continuing to allow delayed execution.
 .SH OPTIONS
-.sp
 .LP
 The following options are supported:
 .sp
@@ -519,7 +522,6 @@
 .RE
 
 .SS "Privileged User Options"
-.sp
 .LP
 Only a privileged user can use the following options:
 .sp
@@ -612,8 +614,16 @@
 turned off immediately if \fImax\fR is set to \fB\(mi1\fR\&.
 .RE
 
-.SH OPERANDS
 .sp
+.ne 2
+.na
+\fB\fB-S\fR\fR
+.ad
+.RS 11n
+Read the password from standard input (pipe).
+.RE
+
+.SH OPERANDS
 .LP
 The following operand is supported:
 .sp
@@ -626,7 +636,6 @@
 .RE
 
 .SH ENVIRONMENT VARIABLES
-.sp
 .LP
 If any of the \fBLC_*\fR variables, that is, \fBLC_CTYPE\fR, \fBLC_MESSAGES\fR,
 \fBLC_TIME\fR, \fBLC_COLLATE\fR, \fBLC_NUMERIC\fR, and \fBLC_MONETARY\fR (see
@@ -664,7 +673,6 @@
 .RE
 
 .SH EXIT STATUS
-.sp
 .LP
 The \fBpasswd\fR command exits with one of the following values:
 .sp
@@ -767,7 +775,6 @@
 .RE
 
 .SH FILES
-.sp
 .ne 2
 .na
 \fB\fB/etc/default/passwd\fR\fR
@@ -1002,7 +1009,6 @@
 .RE
 
 .SH ATTRIBUTES
-.sp
 .LP
 See \fBattributes\fR(5) for descriptions of the following attributes:
 .sp
@@ -1023,7 +1029,6 @@
 .LP
 The human readable output is Uncommitted. The options are Committed.
 .SH SEE ALSO
-.sp
 .LP
 \fBat\fR(1), \fBbatch\fR(1), \fBfinger\fR(1), \fBkpasswd\fR(1), \fBlogin\fR(1),
 \fBnistbladm\fR(1), \fBcron\fR(1M), \fBdomainname\fR(1M), \fBeeprom\fR(1M),
@@ -1037,7 +1042,6 @@
 \fBpam_authtok_store\fR(5), \fBpam_dhkeys\fR(5), \fBpam_ldap\fR(5),
 \fBpam_unix_account\fR(5), \fBpam_unix_auth\fR(5), \fBpam_unix_session\fR(5)
 .SH NOTES
-.sp
 .LP
 The \fBpam_unix\fR(5) module is no longer supported. Similar functionality is
 provided by \fBpam_unix_account\fR(5), \fBpam_unix_auth\fR(5),
@@ -1044,7 +1048,6 @@
 \fBpam_unix_session\fR(5), \fBpam_authtok_check\fR(5),
 \fBpam_authtok_get\fR(5), \fBpam_authtok_store\fR(5), \fBpam_dhkeys\fR(5), and
 \fBpam_passwd_auth\fR(5).
-.sp
 .LP
 The \fBnispasswd\fR and \fBypasswd\fR commands are wrappers around
 \fBpasswd\fR. Use of \fBnispasswd\fR and \fBypasswd\fR is discouraged. Use
