📄 passwd.c
字号:
/* Copyright (C) 2003, 2004, 2005 Thorsten Kukuk Author: Thorsten Kukuk <kukuk@suse.de> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#if defined(HAVE_CONFIG_H)#include "config.h"#endif#define _GNU_SOURCE#include <pwd.h>#include <time.h>#include <errno.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <shadow.h>#include <unistd.h>#include <getopt.h>#include <syslog.h>#include <security/pam_appl.h>#include <security/pam_misc.h>#ifdef WITH_SELINUX#include <selinux/selinux.h>#include <selinux/av_permissions.h>#endif#ifdef HAVE_LIBNSCD_H#include <libnscd.h>#endif#include "i18n.h"#include "public.h"#include "logging.h"#include "logindefs.h"#include "read-files.h"#include "error_codes.h"#ifndef GPASSWD_PROGRAM#define GPASSWD_PROGRAM "gpasswd"#endif#ifndef CHFN_PROGRAM#define CHFN_PROGRAM "chfn"#endif#ifndef CHSH_PROGRAM#define CHSH_PROGRAM "chsh"#endif/* How often should we try to lock the passwd database ? */#define MAX_LOCK_RETRIES 3static struct pam_conv conv = { misc_conv, NULL};static longconv2long (const char *param){ long val; char *cp; val = strtol (param, &cp, 10); if (*cp) return -2; return val;}static const char *pw_status (const char *pass){ if (*pass == '*' || *pass == '!' || *pass == 'x') return "LK"; if (*pass == '\0') return "NP"; return "PS";}static char *date_to_str (time_t t){ static char buf[80]; struct tm *tm; tm = gmtime (&t); strftime (buf, sizeof buf, "%m/%d/%Y", tm); return buf;}static voiddisplay_pw (const struct passwd *pw){ struct spwd *sp;#define DAY (24L*3600L)#define SCALE DAY sp = getspnam (pw->pw_name); if (sp) { printf ("%s %s %s %ld %ld %ld %ld\n", sp->sp_namp, pw_status (sp->sp_pwdp), date_to_str (sp->sp_lstchg * SCALE), (sp->sp_min * SCALE) / DAY, (sp->sp_max * SCALE) / DAY, (sp->sp_warn * SCALE) / DAY, (sp->sp_inact * SCALE) / DAY); } else printf ("%s %s\n", pw->pw_name, pw_status (pw->pw_passwd));}/* A conversation function which uses an internally-stored value for * the responses. */static intstdin_conv (int num_msg, const struct pam_message **msgm, struct pam_response **response, void *appdata_ptr){ struct pam_response *reply; int count; /* Sanity test. */ if (num_msg <= 0) return PAM_CONV_ERR; /* Allocate memory for the responses. */ reply = calloc (num_msg, sizeof (struct pam_response)); if (reply == NULL) return PAM_CONV_ERR; /* Each prompt elicits the same response. */ for (count = 0; count < num_msg; ++count) { reply[count].resp_retcode = 0; reply[count].resp = strdup (appdata_ptr); } /* Set the pointers in the response structure and return. */ *response = reply; return PAM_SUCCESS;}static voidprint_usage (FILE *stream, const char *program){ fprintf (stream, _("Usage: %s [-f|-g|-s|-k[-q]] [account]\n"), program); fprintf (stream, _(" %s [-D binddn] [-n min] [-x max] [-w warn] [-i inact] account\n"), program); fprintf (stream, _(" %s {-l|-u|-d|-S[-a]|-e|-h} account\n"), program); fprintf (stream, _(" %s --stdin account\n"), program);}static voidprint_help (const char *program){ print_usage (stdout, program); fprintf (stdout, _("%s - change password information\n\n"), program); fputs (_(" -f Change the finger (GECOS) information\n"), stdout); fputs (_(" -h Change the home directory\n"), stdout); fputs (_(" -s Change the login shell\n"), stdout); fputs (_(" -g Change the group password\n"), stdout); fputs (_(" -k Change the password only if expired\n"), stdout); fputs (_(" -q Try to be quiet\n"), stdout); fputs (_(" -S Show the password attributes\n"), stdout); fputs (_(" -a Only with -S, show for all accounts\n"), stdout); fputs (_(" -d Delete the password for the named account\n"), stdout); fputs (_(" -l Locks the password entry for \"account\"\n"), stdout); fputs (_(" -u Try to unlock the password entry for \"account\"\n"), stdout); fputs (_(" -e Force the user to change password at next login\n"), stdout); fputs (_(" -n min Set minimum field for \"account\"\n"), stdout); fputs (_(" -x max Set maximum field for \"account\"\n"), stdout); fputs (_(" -w warn Set warn field for \"account\"\n"), stdout); fputs (_(" --service srv Use nameservice 'srv'\n"), stdout); fputs (_(" -D binddn Use dn \"binddn\" to bind to the LDAP directory\n"), stdout); fputs (_(" -P path Search passwd and shadow file in \"path\"\n"), stdout); fputs (_(" --stdin Read new password from stdin (root only)\n"), stdout); fputs (_(" --help Give this help list\n"), stdout); fputs (_(" --usage Give a short usage message\n"), stdout); fputs (_(" --version Print program version\n"), stdout); fputs (_("Valid services are: files, nis, nisplus, ldap\n"), stdout);}static intpasswd_main (const char *program, int argc, char **argv){ int buflen = 256; char *buffer = alloca (buflen); struct passwd resultbuf; struct passwd *pw = NULL; int admin_only = 0; int silent = 0; uid_t uid = getuid (); user_t *pw_data = NULL; char *caller_name = NULL; char *use_service = NULL; char *binddn = NULL; int k_flag = 0, a_flag = 0, d_flag = 0, e_flag = 0, h_flag = 0, i_flag = 0, l_flag = 0, n_flag = 0, u_flag = 0, x_flag = 0, S_flag = 0, w_flag = 0, P_flag = 0, stdin_flag = 0; long inact = 0, age_min = 0, age_max = 0, warn = 0; /* Parse program arguments */ while (1) { int c; int option_index = 0; static struct option long_options[] = { {"binddn", required_argument, NULL, 'D'}, {"path", required_argument, NULL, 'P'}, {"version", no_argument, NULL, '\255'}, {"usage", no_argument, NULL, '\254'}, {"help", no_argument, NULL, '\253'}, {"stdin", no_argument, NULL, '\252'}, {"service", required_argument, NULL, '\251'}, {NULL, 0, NULL, '\0'} }; c = getopt_long (argc, argv, "adD:hlquSekn:x:i:w:P:", long_options, &option_index); if (c == EOF) break; switch (c) { case 'a': a_flag = 1; break; case 'd': d_flag = 1; admin_only = 1; break; case 'D': binddn = optarg; break; case 'e': e_flag = 1; admin_only = 1; break; case 'h': h_flag = 1; admin_only = 1; break; case 'i': i_flag = 1; inact = conv2long (optarg); if (inact <= -2) { print_error (program); return E_BAD_ARG; } admin_only = 1; break; case 'k': k_flag = 1; /* ok for users */ break; case 'l': l_flag = 1; admin_only = 1; break; case 'n': n_flag = 1; age_min = conv2long (optarg); if (age_min <= -2) { print_error (program); return E_BAD_ARG; } admin_only = 1; break; case 'q': silent = 1; /* ok for users */ break; case '\251': if (use_service != NULL) { print_error (program); return E_BAD_ARG; } if (strcasecmp (optarg, "yp") == 0 || strcasecmp (optarg, "nis") == 0) use_service = "nis"; else if (strcasecmp (optarg, "nis+") == 0 || strcasecmp (optarg, "nisplus") == 0) use_service = "nisplus"; else if (strcasecmp (optarg, "files") == 0) use_service = "files"; else if (strcasecmp (optarg, "ldap") == 0) use_service = "ldap"; else { fprintf (stderr, _("Service `%s' not supported.\n"), optarg); print_usage (stderr, program); return E_BAD_ARG; } break; case 'x': x_flag = 1; age_max = conv2long (optarg); if (age_max <= -2) { print_error (program); return E_BAD_ARG; } admin_only = 1; break; case 'S': S_flag = 1; /* ok for users */ break; case 'u': u_flag = 1; admin_only = 1; break; case 'w': w_flag = 1; warn = conv2long (optarg); if (warn <= -2) { print_error (program); return E_BAD_ARG; } admin_only = 1; break; case 'P': P_flag = 1; files_etc_dir = strdup (optarg); break; case '\252': stdin_flag = 1; break; case '\253': print_help (program); return 0; case '\255': print_version (program, "2005"); return 0; case '\254': print_usage (stdout, program); return E_USAGE; default: print_error (program); return E_BAD_ARG; } } argc -= optind; argv += optind; /* We have more than one username or we have -S -a with a username */ if (argc > 1|| (a_flag && S_flag && argc != 0)) { fprintf (stderr, _("%s: Too many arguments.\n"), program); print_error (program); return E_USAGE; } /* For admin only commands we need a user name */ if (argc == 0 && admin_only) { fprintf (stderr, _("%s: User argument missing\n"), program); print_error (program); return E_USAGE; } /* Print a list of all users with status informations. The -a flag requires -S, no other flags, no username, and you must be root. */ if (a_flag) { if (admin_only || !S_flag || (argc != 0)) { print_error (program); return E_USAGE; } if (uid != 0) { fprintf (stderr, _("%s: Permission denied.\n"), program); sec_log (program, MSG_PASSWORD_STATUS_FOR_ALL_DENIED, uid); return E_NOPERM; } sec_log (program, MSG_DISPLAY_PASSWORD_STATUS_FOR_ALL, uid); setpwent (); while ((pw = getpwent ())) display_pw (pw); endpwent ();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -