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

📄 groupmod.c

📁 pwdutils是一套密码管理工具
💻 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.  */#ifdef HAVE_CONFIG_H#include "config.h"#endif#define _GNU_SOURCE#include <time.h>#include <utmp.h>#include <fcntl.h>#include <paths.h>#include <ctype.h>#include <errno.h>#include <stdio.h>#include <getopt.h>#include <unistd.h>#include <string.h>#include <signal.h>#include <libgen.h>#include <sys/resource.h>#ifdef HAVE_LIBNSCD_H#include <libnscd.h>#endif#ifdef USE_LDAP#include "libldap.h"#endif#include "i18n.h"#include "group.h"#include "public.h"#include "logging.h"#include "utf8conv.h"#include "logindefs.h"#include "read-files.h"#include "error_codes.h"static voidprint_usage (FILE * stream, const char *program){  fprintf (stream, _("Usage: %s [-g gid [-o]] [-n new_name] group\n"), program);}static voidprint_help (const char *program){  print_usage (stdout, program);  fprintf (stdout, _("%s - modify a group entry\n\n"), program);  fputs (_("  -D binddn      Use dn \"binddn\" to bind to the LDAP directory\n"),	 stdout);  fputs (_("  -g gid         Change the groupid to the given number\n"),	 stdout);  fputs (_("  -k skeldir     Specify an alternative skel directory\n"),	 stdout);  fputs (_("  -n name        Change group name.\n"), stdout);  fputs (_("  -o             Allow duplicate (non-unique) UID\n"), stdout);  fputs (_("  -P path        Search passwd, shadow and group file in \"path\"\n"),	 stdout);  fputs (_("  -p password    Encrypted password as returned by crypt(3)\n"),	 stdout);  fputs (_("  -A user        Add the user to the group entry\n"), stdout);  fputs (_("  -R user        Remove the user from the group entry\n"), stdout);  fputs (_("  --service srv  Use nameservice 'srv'\n"), stdout);  fputs (_("      --help     Give this help list\n"), stdout);  fputs (_("      --usage    Give a short usage message\n"), stdout);  fputs (_("  -v, --version  Print program version\n"), stdout);  fputs (_("Valid services are: files, ldap\n"), stdout);}static const char *program = "groupmod";static struct option long_options[] = {#ifdef USE_LDAP  {"binddn", required_argument, NULL, 'D'},#endif  {"gid", required_argument, NULL, 'g'},  {"name", required_argument, NULL, 'n'},  {"non-unique", no_argument, NULL, 'o'},  {"path", required_argument, NULL, 'P'},  {"password", required_argument, NULL, 'p'},  {"add-user", required_argument, NULL, 'A'},  {"remove-user", required_argument, NULL, 'R'},  {"version", no_argument, NULL, 'v'},  {"service", required_argument, NULL, '\253'},  {"usage", no_argument, NULL, '\254'},  {"help", no_argument, NULL, '\255'},  {NULL, 0, NULL, '\0'}};static const char *short_options = "A:D:g:n:oP:p:R:v";static struct group *files_getgrnam (const char *name){  enum nss_status status;  static int buflen = 256;  static char *buffer = NULL;  static struct group resultbuf;  if (buffer == NULL)    buffer = malloc (buflen);  while ((status =	  files_getgrnam_r (name, &resultbuf, buffer, buflen,			    &errno)) == NSS_STATUS_TRYAGAIN	 && errno == ERANGE)    {      errno = 0;      buflen += 256;      buffer = realloc (buffer, buflen);    }  if (status == NSS_STATUS_SUCCESS)    return &resultbuf;  else    return NULL;}static struct group *files_getgrgid (gid_t gid){  enum nss_status status;  static int buflen = 256;  static char *buffer = NULL;  static struct group resultbuf;  if (buffer == NULL)    buffer = malloc (buflen);  while ((status = files_getgrgid_r (gid, &resultbuf, buffer, buflen, &errno))	 == NSS_STATUS_TRYAGAIN && errno == ERANGE)    {      errno = 0;      buflen += 256;      buffer = realloc (buffer, buflen);    }  if (status == NSS_STATUS_SUCCESS)    return &resultbuf;  else    return NULL;}/* XXX move to libpwdutils.  */static char **add_gr_mem (const char *name, char **gr_mem){  char **groups;  unsigned int i;  int already_added = 0;  i = 0;  while (gr_mem[i])    {      if (strcmp (gr_mem[i], name) == 0)        already_added = 1;      ++i;    }  ++i;                          /* for trailing NULL pointer */  if (!already_added)    ++i;  groups = malloc (i * sizeof (char *));  i = 0;  while (gr_mem[i])    {      groups[i] = strdup (gr_mem[i]);      ++i;    }  if (!already_added)    {      groups[i] = strdup (name);      ++i;    }  groups[i] = NULL;  return groups;}intmain (int argc, char **argv){  char *use_service = NULL;  group_t *gr_data;#ifdef USE_LDAP  char *binddn = NULL;#endif  char *modify_group;  char *new_name = NULL;  char *new_password = NULL;  gid_t new_gid = 0;  char *know_gid = NULL;  char *remove_user = NULL;  char *add_user = NULL;  int non_unique = 0;  int have_extrapath = 0;  int retval = E_SUCCESS;  setlocale (LC_ALL, "");  bindtextdomain (PACKAGE, LOCALEDIR);  textdomain (PACKAGE);  open_sec_log (program);  /* Before going any further, raise the ulimit and ignore     signals.  */  init_environment ();  while (1)    {      int c;      int option_index = 0;      c = getopt_long (argc, argv, short_options,		       long_options, &option_index);      if (c == (-1))	break;      switch (c)	{	case 'D':#ifdef USE_LDAP	  binddn = optarg;#endif	  break;	case 'g':	  if (strtoid (optarg, &new_gid) == -1)	/* invalid number */	    {	      fprintf (stderr,		       _("%s: invalid numeric argument `%s' for Group ID.\n"),		       program, optarg);	      return E_BAD_ARG;	    }	  know_gid = optarg;	  break;	case 'n':	  new_name = locale_to_utf8 (optarg);	  break;	case 'o':	  non_unique = 1;	  break;	case 'P':	  files_etc_dir = strdup (optarg);	  have_extrapath = 1;	  /* If -P option is used, set use_service to "files" if not	     already set through an option. If we don't limitate to	     service files, we can get trouble finding the right	     source.  */	  if (!use_service)	    use_service = "files";	  break;	case 'p':		/* set encrypted password */	  if (strcspn (optarg, ":\n") != strlen (optarg))	    {	      fprintf (stderr,		       _("%s: invalid characters in password `%s'.\n"),		       program, optarg);	      return E_BAD_ARG;	    }	  new_password = optarg;	  break;	case 'R':	  if (remove_user != NULL)	    {	      print_usage (stderr, program);	      return E_BAD_ARG;	    }	  remove_user = locale_to_utf8 (optarg);	  break;	case '\253':	  if (use_service != NULL)	    {	      print_usage (stderr, program);	      return E_BAD_ARG;	    }	  if (strcasecmp (optarg, "files") == 0)	    use_service = "files";#ifdef USE_LDAP	  else if (strcasecmp (optarg, "ldap") == 0)	    use_service = "ldap";#endif	  else	    {	      fprintf (stderr, _("Service `%s' not supported.\n"), optarg);	      print_usage (stderr, program);	      return E_BAD_ARG;	    }	  break;	case 'A':	  if (add_user != NULL)	    {	      print_usage (stderr, program);	      return E_BAD_ARG;	    }	  add_user = locale_to_utf8 (optarg);	  break;	case '\255':	  print_help (program);	  return 0;	case 'v':	  print_version (program, "2005");	  return 0;	case '\254':	  print_usage (stdout, program);	  return 0;	default:	  print_error (program);	  return E_USAGE;	}    }  argc -= optind;  argv += optind;  if (argc > 1)    {      fprintf (stderr, _("%s: Too many arguments.\n"), program);      print_error (program);      return E_USAGE;    }  else if (argc == 0)    {      fprintf (stderr, _("%s: Too few arguments.\n"), program);      print_error (program);      return E_USAGE;    }  else    {      int buflen = 256;      char *buffer = alloca (buflen);      struct passwd resultbuf;      struct passwd *pw;      /* Determine our own user name for PAM authentication.  */      while (getpwuid_r (getuid (), &resultbuf, buffer, buflen, &pw) != 0	     && errno == ERANGE)	{	  errno = 0;	  buflen += 256;	  buffer = alloca (buflen);	}      if (!pw)	{	  sec_log (program, MSG_NO_ACCOUNT_FOUND, getuid ());	  fprintf (stderr, _("%s: Cannot determine your user name.\n"),		   program);	  return E_UNKNOWN_USER;	}      if (do_authentication ("shadow", pw->pw_name, NULL) != 0)	{	  sec_log (program, MSG_PERMISSION_DENIED, pw->pw_name,                   pw->pw_uid, getuid());	  return E_NOPERM;	}    }  modify_group = locale_to_utf8 (argv[0]);  /* Check, if the account we should modify exist.  */  gr_data = find_group_data (modify_group, 0, use_service);  if (gr_data == NULL || gr_data->service == S_NONE)    {				/* Group does not exist.  */      if (use_service)        fprintf (stderr, _("%s: Group `%s' not found in service `%s'.\n"),                 program, utf8_to_locale (modify_group), use_service);      else        fprintf (stderr, _("%s: Unknown group `%s'.\n"), program,                 utf8_to_locale (modify_group));      sec_log (program, MSG_UNKNOWN_GROUP, modify_group, getuid ());      return E_NOTFOUND;    }  /* After this, we can start modifying the existing account.  */  if (know_gid != NULL && !non_unique)    {      if (getgrgid (new_gid) != NULL ||	  (have_extrapath && files_getgrgid (new_gid) != NULL))	{	  fprintf (stderr, _("%s: GID %u is not unique.\n"),		   program, new_gid);	  sec_log (program, MSG_GID_NOT_UNIQUE, new_gid, getuid ());	  return E_GID_IN_USE;	}    }  /* If group should be renamed, check that the new name is valid     and does not already exist.  */  if (new_name)    {      if (check_name (new_name) != 0)	{	  fprintf (stderr, _("%s: Invalid group name `%s'.\n"),		   program, utf8_to_locale (new_name));	  sec_log (program, MSG_GROUP_NAME_INVALID, new_name, getuid())	  return E_BAD_ARG;	}      else	{	  if (getgrnam (new_name) != NULL ||	      (have_extrapath && files_getgrnam (new_name) != NULL))	    {	      fprintf (stderr, _("%s: Group `%s' already exists.\n"),		       program, utf8_to_locale (new_name));	      sec_log (program, MSG_GROUP_ALREADY_EXISTS, new_name, getuid ());	      return E_NAME_IN_USE;	    }	}    }  /* Lock passwd file, so that a concurrent useradd process will not     add the user a second time or a second user with the same uid.  */  if ((use_service == NULL || strcmp (use_service, "files") == 0) &&      lock_database () != 0)    {      fputs (_("Cannot lock password file: already locked.\n"), stderr);      sec_log (program, MSG_PASSWD_FILE_ALREADY_LOCKED);      return E_PWDBUSY;    }  else    {      gr_data->todo = DO_MODIFY;      if (new_name)	gr_data->new_name = strdup (new_name);      if (new_password)	gr_data->newpassword = strdup (new_password);      if (know_gid)	{	  gr_data->have_new_gid = 1;	  gr_data->new_gid = new_gid;	}      if (remove_user)	gr_data->new_gr_mem = remove_gr_mem (remove_user, gr_data->gr.gr_mem);      if (add_user)	gr_data->new_gr_mem = add_gr_mem (add_user, gr_data->gr.gr_mem);#ifdef USE_LDAP      if (gr_data->service == S_LDAP)	{	  if (binddn == NULL)	    {	      binddn = get_caller_dn ();	      if (binddn == NULL)		{		  fprintf (stderr,			   _			   ("%s: Cannot modify group in LDAP database without DN.\n"),			   program);		}	      else		gr_data->binddn = strdup (binddn);	    }	  else	    gr_data->binddn = strdup (binddn);	  if (gr_data->oldclearpwd == NULL)	    {	      char *cp = get_ldap_password (gr_data->binddn);	      if (cp)		gr_data->oldclearpwd = strdup (cp);	      else		{		  fprintf (stderr,			   _("%s: Group not modified in LDAP database.\n"),			   program);		  return E_FAILURE;		}	    }	}#endif      if (write_group_data (gr_data, 1) != 0)	{	  sec_log (program, MSG_ERROR_MODIFYING_GROUP,		   gr_data->gr.gr_name,  gr_data->gr.gr_gid, getuid())	    return E_FAILURE;        }      else        {	  if (remove_user)	    sec_log (program, MSG_USER_REMOVED_FROM_GROUP,		     remove_user, gr_data->gr.gr_name, gr_data->gr.gr_gid, getuid());	  if (add_user)	    sec_log (program, MSG_USER_ADDED_TO_GROUP, add_user, gr_data->gr.gr_name,		     gr_data->gr.gr_gid, getuid());	  if (new_name)	    sec_log (program, MSG_GROUP_NAME_CHANGED, gr_data->new_name,		     gr_data->gr.gr_name, gr_data->gr.gr_gid, getuid());	  if (new_password)	    sec_log (program, MSG_GROUP_PASSWORD_CHANGED, gr_data->gr.gr_name,		     gr_data->gr.gr_gid, getuid());	  if (know_gid)	    sec_log (program, MSG_GROUP_ID_CHANGED, gr_data->gr.gr_name, gr_data->new_gid,		     gr_data->gr.gr_gid, getuid());	}#ifdef HAVE_NSCD_FLUSH_CACHE      /* flush NSCD cache, else later calls could get obsolete data.  */      nscd_flush_cache ("group");#endif    }  if (use_service == NULL || strcmp (use_service, "files") == 0)    ulckpwdf ();  return retval;}

⌨️ 快捷键说明

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