⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 su.c

📁 Unix/Linux下转换用户ID的su程序源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* su for GNU.  Run a shell with substitute user and group IDs.   Copyright (C) 92, 93, 94, 95, 1996 Free Software Foundation, Inc.   This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 2, or (at your option)   any later version.   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.  *//* Run a shell with the real and effective UID and GID and groups   of USER, default `root'.   The shell run is taken from USER's password entry, /bin/sh if   none is specified there.  If the account has a password, su   prompts for a password unless run by a user with real UID 0.   Does not change the current directory.   Sets `HOME' and `SHELL' from the password entry for USER, and if   USER is not root, sets `USER' and `LOGNAME' to USER.   The subshell is not a login shell.   If one or more ARGs are given, they are passed as additional   arguments to the subshell.   Does not handle /bin/sh or other shells specially   (setting argv[0] to "-su", passing -c only to certain shells, etc.).   I don't see the point in doing that, and it's ugly.   This program intentionally does not support a "wheel group" that   restricts who can su to UID 0 accounts.  RMS considers that to   be fascist.   Options:   -, -l, --login       Make the subshell a login shell.                        Unset all environment variables except                        TERM, HOME and SHELL (set as above), and USER                        and LOGNAME (set unconditionally as above), and                        set PATH to a default value.                        Change to USER's home directory.                        Prepend "-" to the shell's name.   -c, --commmand=COMMAND                        Pass COMMAND to the subshell with a -c option                        instead of starting an interactive shell.   -f, --fast           Pass the -f option to the subshell.   -m, -p, --preserve-environment                        Do not change HOME, USER, LOGNAME, SHELL.                        Run $SHELL instead of USER's shell from /etc/passwd                        unless not the superuser and USER's shell is                        restricted.                        Overridden by --login and --shell.   -s, --shell=shell    Run SHELL instead of USER's shell from /etc/passwd                        unless not the superuser and USER's shell is                        restricted.   Compile-time options:   -DSYSLOG_SUCCESS     Log successful su's (by default, to root) with syslog.   -DSYSLOG_FAILURE     Log failed su's (by default, to root) with syslog.   -DSYSLOG_NON_ROOT    Log all su's, not just those to root (UID 0).   Never logs attempted su's to nonexistent accounts.   Written by David MacKenzie <djm@gnu.ai.mit.edu>.  */#include <config.h>#include <stdio.h>#include <getopt.h>#include <sys/types.h>#include <pwd.h>#include <grp.h>#include "system.h"#if defined(HAVE_SYSLOG_H) && defined(HAVE_SYSLOG)#include <syslog.h>#else /* !HAVE_SYSLOG_H */#ifdef SYSLOG_SUCCESS#undef SYSLOG_SUCCESS#endif#ifdef SYSLOG_FAILURE#undef SYSLOG_FAILURE#endif#ifdef SYSLOG_NON_ROOT#undef SYSLOG_NON_ROOT#endif#endif /* !HAVE_SYSLOG_H */#ifdef _POSIX_VERSION#include <limits.h>#else /* not _POSIX_VERSION */struct passwd *getpwuid ();struct group *getgrgid ();uid_t getuid ();#include <sys/param.h>#endif /* not _POSIX_VERSION */#ifndef HAVE_ENDGRENT# define endgrent() ((void) 0)/* [<][>][^][v][top][bottom][index][help] */#endif#ifndef HAVE_ENDPWENT# define endpwent() ((void) 0)/* [<][>][^][v][top][bottom][index][help] */#endif#ifdef HAVE_SHADOW_H#include <shadow.h>#endif#include "error.h"#ifdef HAVE_PATHS_H#include <paths.h>#endif/* The default PATH for simulated logins to non-superuser accounts.  */#ifdef _PATH_DEFPATH#define DEFAULT_LOGIN_PATH _PATH_DEFPATH#else#define DEFAULT_LOGIN_PATH ":/usr/ucb:/bin:/usr/bin"#endif/* The default PATH for simulated logins to superuser accounts.  */#ifdef _PATH_DEFPATH_ROOT#define DEFAULT_ROOT_LOGIN_PATH _PATH_DEFPATH_ROOT#else#define DEFAULT_ROOT_LOGIN_PATH "/usr/ucb:/bin:/usr/bin:/etc"#endif/* The shell to run if none is given in the user's passwd entry.  */#define DEFAULT_SHELL "/bin/sh"/* The user to become if none is specified.  */#define DEFAULT_USER "root"char *crypt ();char *getpass ();char *getusershell ();void endusershell ();void setusershell ();char *basename ();char *xmalloc ();char *xrealloc ();char *xstrdup ();extern char **environ;/* The name this program was run with.  */char *program_name;/* If nonzero, display usage information and exit.  */static int show_help;/* If nonzero, print the version on standard output and exit.  */static int show_version;/* If nonzero, pass the `-f' option to the subshell.  */static int fast_startup;/* If nonzero, simulate a login instead of just starting a shell.  */static int simulate_login;/* If nonzero, change some environment vars to indicate the user su'd to.  */static int change_environment;static struct option const longopts[] ={  {"command", required_argument, 0, 'c'},  {"fast", no_argument, &fast_startup, 1},  {"help", no_argument, &show_help, 1},  {"login", no_argument, &simulate_login, 1},  {"preserve-environment", no_argument, &change_environment, 0},  {"shell", required_argument, 0, 's'},  {"version", no_argument, &show_version, 1},  {0, 0, 0, 0}};/* Add VAL to the environment, checking for out of memory errors.  */static voidxputenv (const char *val)/* [<][>][^][v][top][bottom][index][help] */{  if (putenv (val))    error (1, 0, _("virtual memory exhausted"));}/* Return a newly-allocated string whose contents concatenate   those of S1, S2, S3.  */static char *concat (const char *s1, const char *s2, const char *s3)/* [<][>][^][v][top][bottom][index][help] */{  int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);  char *result = (char *) xmalloc (len1 + len2 + len3 + 1);  strcpy (result, s1);  strcpy (result + len1, s2);  strcpy (result + len1 + len2, s3);  result[len1 + len2 + len3] = 0;  return result;}/* Return the number of elements in ARR, a null-terminated array.  */static intelements (char **arr)/* [<][>][^][v][top][bottom][index][help] */{  int n = 0;  for (n = 0; *arr; ++arr)    ++n;  return n;}#if defined (SYSLOG_SUCCESS) || defined (SYSLOG_FAILURE)/* Log the fact that someone has run su to the user given by PW;   if SUCCESSFUL is nonzero, they gave the correct password, etc.  */static voidlog_su (const struct passwd *pw, int successful)/* [<][>][^][v][top][bottom][index][help] */{  const char *new_user, *old_user, *tty;#ifndef SYSLOG_NON_ROOT  if (pw->pw_uid)    return;#endif  new_user = pw->pw_name;  /* The utmp entry (via getlogin) is probably the best way to identify     the user, especially if someone su's from a su-shell.  */  old_user = getlogin ();  if (old_user == NULL)    old_user = "";  tty = ttyname (2);  if (tty == NULL)    tty = "";  /* 4.2BSD openlog doesn't have the third parameter.  */  openlog (basename (program_name), 0#ifdef LOG_AUTH           , LOG_AUTH#endif           );  syslog (LOG_NOTICE,#ifdef SYSLOG_NON_ROOT          "%s(to %s) %s on %s",#else          "%s%s on %s",#endif          successful ? "" : "FAILED SU ",#ifdef SYSLOG_NON_ROOT          new_user,#endif          old_user, tty);  closelog ();}#endif/* Ask the user for a password.   Return 1 if the user gives the correct password for entry PW,   0 if not.  Return 1 without asking for a password if run by UID 0   or if PW has an empty password.  */static intcorrect_password (const struct passwd *pw)/* [<][>][^][v][top][bottom][index][help] */{  char *unencrypted, *encrypted, *correct;#ifdef HAVE_SHADOW_H  /* Shadow passwd stuff for SVR3 and maybe other systems.  */  struct spwd *sp = getspnam (pw->pw_name);  endspent ();  if (sp)    correct = sp->sp_pwdp;  else#endif  correct = pw->pw_passwd;  if (getuid () == 0 || correct == 0 || correct[0] == '\0')    return 1;  unencrypted = getpass (_("Password:"));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -