Print this page
4107 Add passwd option to read passwords from stdin
*** 28,37 ****
--- 28,40 ----
/* Copyright (c) 1987, 1988 Microsoft Corporation */
/* 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.
* Non privileged user can change password or display
* password attributes which corresponds to their login name.
*** 82,91 ****
--- 85,95 ----
#define EFLAG 0x400 /* change shell */
#define GFLAG 0x800 /* change gecos information */
#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)
#define MUTEXFLAG (DFLAG | LFLAG | XFLAG | UFLAG | SAFLAG)
*** 176,185 ****
--- 180,191 ----
static uid_t uid;
static char *prognamep;
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 */
static adt_session_data_t *ah; /* audit session handle */
static adt_event_data_t *event = NULL; /* event to be generated */
*** 232,243 ****
int i;
attrlist *attributes = NULL;
char *input;
int tries = 1;
int updated_reps;
-
if ((prognamep = strrchr(argv[0], '/')) != NULL)
++prognamep;
else
prognamep = argv[0];
--- 238,250 ----
int i;
attrlist *attributes = NULL;
char *input;
int tries = 1;
int updated_reps;
+ ssize_t s;
+ char st_pass[PASS_MAX];
if ((prognamep = strrchr(argv[0], '/')) != NULL)
++prognamep;
else
prognamep = argv[0];
*** 292,301 ****
--- 299,318 ----
}
} else {
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);
}
auth_rep.type = repository.type;
*** 360,370 ****
/* system error */
passwd_exit(FMERR);
break;
}
! if (flag == 0) { /* changing user password */
int chk_authtok = 0; /* check password strength */
dprintf1("call pam_chauthtok() repository name =%s\n",
repository.type);
--- 377,387 ----
/* system error */
passwd_exit(FMERR);
break;
}
! if (flag == STFLAG || flag == 0) { /* changing user password */
int chk_authtok = 0; /* check password strength */
dprintf1("call pam_chauthtok() repository name =%s\n",
repository.type);
*** 686,696 ****
int opt;
int flag;
flag = 0;
! while ((opt = getopt(argc, argv, "r:aldefghsux:n:w:N")) != EOF) {
switch (opt) {
case 'r': /* Repository Specified */
/* repository: this option should be specified first */
--- 703,713 ----
int opt;
int flag;
flag = 0;
! while ((opt = getopt(argc, argv, "r:aldefghsux:n:w:N:S")) != EOF) {
switch (opt) {
case 'r': /* Repository Specified */
/* repository: this option should be specified first */
*** 738,748 ****
if (ckuid() != SUCCESS) {
retval = NOPERM;
return (FAIL);
}
! if (flag & (LFLAG|SAFLAG|DFLAG|XFLAG|UFLAG)) {
rusage();
retval = BADOPT;
return (FAIL);
}
flag |= DFLAG;
--- 755,765 ----
if (ckuid() != SUCCESS) {
retval = NOPERM;
return (FAIL);
}
! if (flag & (LFLAG|SAFLAG|DFLAG|XFLAG|UFLAG|STFLAG)) {
rusage();
retval = BADOPT;
return (FAIL);
}
flag |= DFLAG;
*** 770,780 ****
* for FILES or LDAP
*/
if ((IS_FILES(repository) || IS_LDAP(repository)) &&
((retval = ckuid()) != SUCCESS))
return (FAIL);
! if (flag & (MUTEXFLAG|NONAGEFLAG)) {
rusage(); /* exit */
retval = BADOPT;
return (FAIL);
}
flag |= XFLAG;
--- 787,797 ----
* for FILES or LDAP
*/
if ((IS_FILES(repository) || IS_LDAP(repository)) &&
((retval = ckuid()) != SUCCESS))
return (FAIL);
! if (flag & (MUTEXFLAG|NONAGEFLAG|STFLAG)) {
rusage(); /* exit */
retval = BADOPT;
return (FAIL);
}
flag |= XFLAG;
*** 802,812 ****
* for FILES or LDAP
*/
if ((IS_FILES(repository) || IS_LDAP(repository)) &&
((retval = ckuid()) != SUCCESS))
return (FAIL);
! if (flag & (MUTEXFLAG|NONAGEFLAG)) {
rusage(); /* exit */
retval = BADOPT;
return (FAIL);
}
flag |= LFLAG;
--- 819,829 ----
* for FILES or LDAP
*/
if ((IS_FILES(repository) || IS_LDAP(repository)) &&
((retval = ckuid()) != SUCCESS))
return (FAIL);
! if (flag & (MUTEXFLAG|NONAGEFLAG|STFLAG)) {
rusage(); /* exit */
retval = BADOPT;
return (FAIL);
}
flag |= LFLAG;
*** 834,844 ****
* for FILES or LDAP
*/
if ((IS_FILES(repository) || IS_LDAP(repository)) &&
((retval = ckuid()) != SUCCESS))
return (FAIL);
! if (flag & (MUTEXFLAG|NONAGEFLAG)) {
rusage(); /* exit */
retval = BADOPT;
return (FAIL);
}
flag |= UFLAG;
--- 851,861 ----
* for FILES or LDAP
*/
if ((IS_FILES(repository) || IS_LDAP(repository)) &&
((retval = ckuid()) != SUCCESS))
return (FAIL);
! if (flag & (MUTEXFLAG|NONAGEFLAG|STFLAG)) {
rusage(); /* exit */
retval = BADOPT;
return (FAIL);
}
flag |= UFLAG;
*** 869,879 ****
if ((IS_FILES(repository) || IS_LDAP(repository)) &&
(ckuid() != SUCCESS)) {
retval = NOPERM;
return (FAIL);
}
! if (flag & (SAFLAG|MFLAG|NONAGEFLAG)) {
retval = BADOPT;
return (FAIL);
}
flag |= MFLAG;
if ((int)strlen(optarg) <= 0 ||
--- 886,896 ----
if ((IS_FILES(repository) || IS_LDAP(repository)) &&
(ckuid() != SUCCESS)) {
retval = NOPERM;
return (FAIL);
}
! if (flag & (SAFLAG|MFLAG|NONAGEFLAG|STFLAG)) {
retval = BADOPT;
return (FAIL);
}
flag |= MFLAG;
if ((int)strlen(optarg) <= 0 ||
*** 908,918 ****
* for FILES or LDAP
*/
if ((IS_FILES(repository) || IS_LDAP(repository)) &&
((retval = ckuid()) != SUCCESS))
return (FAIL);
! if (flag & (SAFLAG|NFLAG|NONAGEFLAG)) {
retval = BADOPT;
return (FAIL);
}
flag |= NFLAG;
if ((int)strlen(optarg) <= 0 ||
--- 925,935 ----
* for FILES or LDAP
*/
if ((IS_FILES(repository) || IS_LDAP(repository)) &&
((retval = ckuid()) != SUCCESS))
return (FAIL);
! if (flag & (SAFLAG|NFLAG|NONAGEFLAG|STFLAG)) {
retval = BADOPT;
return (FAIL);
}
flag |= NFLAG;
if ((int)strlen(optarg) <= 0 ||
*** 949,959 ****
if ((IS_FILES(repository) || IS_LDAP(repository)) &&
(ckuid() != SUCCESS)) {
retval = NOPERM;
return (FAIL);
}
! if (flag & (SAFLAG|WFLAG|NONAGEFLAG)) {
retval = BADOPT;
return (FAIL);
}
flag |= WFLAG;
if ((int)strlen(optarg) <= 0 ||
--- 966,976 ----
if ((IS_FILES(repository) || IS_LDAP(repository)) &&
(ckuid() != SUCCESS)) {
retval = NOPERM;
return (FAIL);
}
! if (flag & (SAFLAG|WFLAG|NONAGEFLAG|STFLAG)) {
retval = BADOPT;
return (FAIL);
}
flag |= WFLAG;
if ((int)strlen(optarg) <= 0 ||
*** 1050,1060 ****
* for FILES or LDAP
*/
if ((IS_FILES(repository) || IS_LDAP(repository)) &&
((retval = ckuid()) != SUCCESS))
return (FAIL);
! if (flag & (SAFLAG|FFLAG|NONAGEFLAG)) {
retval = BADOPT;
return (FAIL);
}
flag |= FFLAG;
attrlist_add(attributes, ATTR_EXPIRE_PASSWORD, NULL);
--- 1067,1077 ----
* for FILES or LDAP
*/
if ((IS_FILES(repository) || IS_LDAP(repository)) &&
((retval = ckuid()) != SUCCESS))
return (FAIL);
! if (flag & (SAFLAG|FFLAG|NONAGEFLAG|STFLAG)) {
retval = BADOPT;
return (FAIL);
}
flag |= FFLAG;
attrlist_add(attributes, ATTR_EXPIRE_PASSWORD, NULL);
*** 1064,1074 ****
/* if no repository the default for -e is files */
if (repository.type == NULL)
repository = __REPFILES;
! if (flag & (EFLAG|SAFLAG|AGEFLAG)) {
retval = BADOPT;
return (FAIL);
}
flag |= EFLAG;
break;
--- 1081,1091 ----
/* if no repository the default for -e is files */
if (repository.type == NULL)
repository = __REPFILES;
! if (flag & (EFLAG|SAFLAG|AGEFLAG|STFLAG)) {
retval = BADOPT;
return (FAIL);
}
flag |= EFLAG;
break;
*** 1085,1095 ****
*/
if (IS_FILES(repository) && (ckuid() != SUCCESS)) {
retval = NOPERM;
return (FAIL);
}
! if (flag & (GFLAG|SAFLAG|AGEFLAG)) {
retval = BADOPT;
return (FAIL);
}
flag |= GFLAG;
break;
--- 1102,1112 ----
*/
if (IS_FILES(repository) && (ckuid() != SUCCESS)) {
retval = NOPERM;
return (FAIL);
}
! if (flag & (GFLAG|SAFLAG|AGEFLAG|STFLAG)) {
retval = BADOPT;
return (FAIL);
}
flag |= GFLAG;
break;
*** 1112,1128 ****
gettext(MSG_NIS_HOMEDIR));
retval = BADSYN;
return (FAIL);
}
! if (flag & (HFLAG|SAFLAG|AGEFLAG)) {
retval = BADOPT;
return (FAIL);
}
flag |= HFLAG;
break;
!
case '?':
rusage();
retval = BADOPT;
return (FAIL);
}
--- 1129,1156 ----
gettext(MSG_NIS_HOMEDIR));
retval = BADSYN;
return (FAIL);
}
! 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;
return (FAIL);
}
*** 1671,1680 ****
--- 1699,1759 ----
}
return (PAM_SUCCESS);
}
/*
+ *
+ * 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
*/
/*
* int attrlist_add(attrlist **l, attrtype type, char *val)
*** 1773,1779 ****
--- 1852,1859 ----
MSG("\tpasswd -r ldap [-egh] [name]\n");
MSG("\tpasswd -r ldap -sa\n");
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
}