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 }