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

📄 user.c

📁 pwdutils是一套密码管理工具
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Copyright (C) 2002, 2003, 2004, 2005 Thorsten Kukuk   Author: Thorsten Kukuk <kukuk@thkukuk.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 <nss.h>#include <dlfcn.h>#include <errno.h>#include <unistd.h>#include <sys/stat.h>#include <rpcsvc/yp_prot.h>#include <rpcsvc/ypclnt.h>#ifdef USE_LDAP#ifdef HAVE_LDAP_H#include <ldap.h>#endif#include "libldap.h"#endif#include "nsw.h"#include "i18n.h"#include "public.h"#include "yppasswd.h"#include "read-files.h"char *files_etc_dir = "/etc";const char *nsw2str (service_t service){  switch (service)    {    case S_LOCAL:      return "files";      break;    case S_YP:      return "NIS";      break;    case S_NISPLUS:      return "NIS+";      break;#ifdef USE_LDAP    case S_LDAP:      return "LDAP";      break;#endif    default:      return "unknown";      break;    }}char *getnismaster (void){  char *master, *domainname;  int port, err;  yp_get_default_domain (&domainname);  if ((err = yp_master (domainname, "passwd.byname", &master)) != 0)    {      fprintf (stderr, _("Can't find the NIS master server: %s\n"),	       yperr_string (err));      return NULL;    }  port = getrpcport (master, YPPASSWDPROG, YPPASSWDPROC_UPDATE, IPPROTO_UDP);  if (port == 0)    {      fprintf (stderr, _("rpc.yppasswdd not running on NIS master %s.\n"), master);      return NULL;    }  if (port >= IPPORT_RESERVED)    {      fprintf (stderr,	       _("rpc.yppasswdd running on illegal port on NIS master %s.\n"),	       master);      return NULL;    }  return master;}voidfree_user_t (user_t *data){  if (data == NULL)    return;  if (data->pwdbuffer)    free (data->pwdbuffer);  if (data->spwbuffer)    free (data->spwbuffer);  if (data->newpassword)    free (data->newpassword);  if (data->new_name)    free (data->new_name);  if (data->new_shell)    free (data->new_shell);  if (data->new_gecos)    free (data->new_gecos);  if (data->new_home)    free (data->new_home);  if (data->oldclearpwd)    free (data->oldclearpwd);  if (data->binddn)    free (data->binddn);  free (data);}user_t *do_getpwnam (const char *user, const char *use_service){  enum nss_status (*nss_getpwnam_r)(const char *name, struct passwd *pwd,                                    char *buffer, size_t buflen, int *errnop);  enum nss_status (*nss_getspnam_r)(const char *name, struct spwd *sp,                                    char *buffer, size_t buflen, int *errnop);  enum nss_status status;  void *nss_handle = NULL;  user_t *data;  struct nsw *nswp;  int i;  data = calloc (1, sizeof (user_t));  if (data == NULL)    return NULL;  data->service = S_NONE;  /* UNIX passwords area */  if (use_service)    {      nswp = calloc (1, sizeof (struct nsw));      if (nswp == NULL)	return data;      nswp->name = strdup ("passwd");      nswp->orderc = 1;      nswp->orders = calloc (2, sizeof (char *));      nswp->orders[0] = strdup (use_service);      nswp->orders[1] = NULL;    }  else    nswp = _getnswbyname ("passwd");  if (nswp == NULL)    return data;  for (i = 0; i < nswp->orderc; ++i)    {      const char *cmpptr = nswp->orders[i];    again:      if (nswp->orders[i][0] == '[')	continue;      if (strcasecmp ("files", cmpptr) == 0 ||	  strcasecmp ("compat", cmpptr) == 0)	{          nss_getpwnam_r = files_getpwnam_r;	  /* Get password file entry... */	  do {            errno = 0;	    data->pwdbuflen += 1024;	    data->pwdbuffer = realloc (data->pwdbuffer, data->pwdbuflen);	    status = (*nss_getpwnam_r)(user, &data->pw, data->pwdbuffer,				       data->pwdbuflen, &errno);	  } while (status == NSS_STATUS_TRYAGAIN && errno == ERANGE);	  if (status != NSS_STATUS_SUCCESS)	    {	      free (data->pwdbuffer);	      data->pwdbuffer = NULL;	      data->pwdbuflen = 0;	      if (strcasecmp ("compat", cmpptr) == 0)		{		  struct nsw *nswp2 = _getnswbyname ("passwd_compat");		  if (nswp2 == NULL)		    cmpptr = "nis";		  else		    {		      char *cp = alloca (strlen (nswp2->orders[0]) + 1);		      strcpy (cp, nswp2->orders[0]);		      cmpptr = cp;		      nsw_free (nswp2);		    }		  goto again;		}	    }	  else	    {	      data->service = S_LOCAL;	      break;	    }	}      else if (strcasecmp ("nis", cmpptr) == 0 ||	       strcasecmp ("yp", cmpptr) == 0)	{          nss_handle = dlopen ("libnss_nis.so.2", RTLD_NOW);          if (!nss_handle)            continue;          nss_getpwnam_r = dlsym (nss_handle, "_nss_nis_getpwnam_r");          if (dlerror () != NULL)            {              dlclose (nss_handle);              continue;            }	  /* Get NIS passwd entry... */	  do {            errno = 0;	    data->pwdbuflen += 1024;	    data->pwdbuffer = realloc (data->pwdbuffer, data->pwdbuflen);	    status = (*nss_getpwnam_r)(user, &data->pw, data->pwdbuffer,				       data->pwdbuflen, &errno);	  } while (status == NSS_STATUS_TRYAGAIN && errno == ERANGE);	  if (status != NSS_STATUS_SUCCESS)	    {	      dlclose (nss_handle);	      free (data->pwdbuffer);	      data->pwdbuffer = NULL;	      data->pwdbuflen = 0;	    }	  else	    {	      data->service = S_YP;	      break;	    }	}      else if (strcasecmp ("nisplus", cmpptr) == 0 ||	       strcasecmp ("nis+", cmpptr) == 0)	{	  nss_handle = dlopen ("libnss_nisplus.so.2", RTLD_NOW);          if (!nss_handle)            continue;          nss_getpwnam_r = dlsym (nss_handle, "_nss_nisplus_getpwnam_r");          if (dlerror () != NULL)            {              dlclose (nss_handle);              continue;            }	  /* Get password NIS+ entry... */	  do {            errno = 0;	    data->pwdbuflen += 1024;	    data->pwdbuffer = realloc (data->pwdbuffer, data->pwdbuflen);	    status = (*nss_getpwnam_r)(user, &data->pw, data->pwdbuffer,				       data->pwdbuflen, &errno);	  } while (status == NSS_STATUS_TRYAGAIN && errno == ERANGE);	  if (status != NSS_STATUS_SUCCESS)	    {	      dlclose (nss_handle);	      free (data->pwdbuffer);	      data->pwdbuffer = NULL;	      data->pwdbuflen = 0;	    }	  else	    {	      data->service = S_NISPLUS;	      break;	    }	}#ifdef USE_LDAP      else if (strcasecmp ("ldap", cmpptr) == 0)	{	  nss_handle = dlopen ("libnss_ldap.so.2", RTLD_NOW);          if (!nss_handle)            continue;          nss_getpwnam_r = dlsym (nss_handle, "_nss_ldap_getpwnam_r");          if (dlerror () != NULL)            {              dlclose (nss_handle);              continue;            }	  /* Get LDAP passwd entry... */	  do {            errno = 0;	    data->pwdbuflen += 1024;	    data->pwdbuffer = realloc (data->pwdbuffer, data->pwdbuflen);	    status = (*nss_getpwnam_r)(user, &data->pw, data->pwdbuffer,				       data->pwdbuflen, &errno);	  } while (status == NSS_STATUS_TRYAGAIN && errno == ERANGE);	  if (status != NSS_STATUS_SUCCESS)	    {	      dlclose (nss_handle);	      free (data->pwdbuffer);	      data->pwdbuffer = NULL;	      data->pwdbuflen = 0;	    }	  else	    {	      data->service = S_LDAP;	      break;	    }	}#endif    }  nsw_free (nswp);  if (data->service == S_NONE)    return data;  nss_getspnam_r = NULL;  status = NSS_STATUS_NOTFOUND;  if (data->service == S_LOCAL)    {      nss_getspnam_r = files_getspnam_r;    }  else if (data->service == S_YP)    {      nss_getspnam_r = dlsym (nss_handle, "_nss_nis_getspnam_r");      if (dlerror () != NULL)        {          data->service = S_NONE;          free (data->pwdbuffer);          data->pwdbuffer = NULL;          data->pwdbuflen = 0;          dlclose (nss_handle);          return data;        }    }  else if (data->service == S_NISPLUS)    {      nss_getspnam_r = dlsym (nss_handle, "_nss_nisplus_getspnam_r");      if (dlerror () != NULL)        {          data->service = S_NONE;          free (data->pwdbuffer);          data->pwdbuffer = NULL;          data->pwdbuflen = 0;          dlclose (nss_handle);          return data;        }    }#ifdef USE_LDAP  else if (data->service == S_LDAP)    {      nss_getspnam_r = dlsym (nss_handle, "_nss_ldap_getspnam_r");      if (dlerror () != NULL)        {          data->service = S_NONE;          free (data->pwdbuffer);          data->pwdbuffer = NULL;          data->pwdbuflen = 0;          dlclose (nss_handle);          return data;        }    }#endif  if (nss_getspnam_r)    {      do {        errno = 0;        data->spwbuflen += 1024;        data->spwbuffer = realloc (data->spwbuffer, data->spwbuflen);        status = (*nss_getspnam_r)(user, &data->sp, data->spwbuffer,                                   data->spwbuflen, &errno);      } while (status == NSS_STATUS_TRYAGAIN && errno == ERANGE);    }  if (data->service != S_LOCAL && data->service != S_NONE)    dlclose (nss_handle);  if (status == NSS_STATUS_SUCCESS)    {      data->use_shadow = TRUE;      data->spn = data->sp;      data->sp_changed = FALSE;    }  else    memset (&(data->sp), 0, sizeof (struct spwd));  return data;}intwrite_user_data (user_t *data, int is_locked){  int retval = 0;  if (data->service == S_LOCAL)    {      if (!is_locked && lock_database() != 0)        {	  fputs (_("Cannot lock password file: already locked.\n"), stderr);	  retval = -1;        }      else if ((data->newpassword && !data->use_shadow) ||	       data->new_shell || data->new_gecos || data->new_home ||	       data->have_new_uid || data->have_new_gid || data->new_name ||	       data->todo == DO_CREATE || data->todo == DO_DELETE)	{	  /* Only run through /etc/passwd if we really have something to	     change.  */	  const char *file_tmp = "/passwd.tmpXXXXXX";	  char *passwd_tmp = alloca (strlen (files_etc_dir) + strlen (file_tmp) + 1);	  char *passwd_orig = alloca (strlen (files_etc_dir) + 8);	  char *passwd_old = alloca (strlen (files_etc_dir) + 12);	  struct stat passwd_stat;	  struct passwd *pw; /* passwd struct obtained from fgetpwent() */	  FILE *oldpf, *newpf;	  int gotit, newpf_fd;	  char *cp;	  cp = stpcpy (passwd_tmp, files_etc_dir);	  strcpy (cp, file_tmp);	  cp = stpcpy (passwd_orig, files_etc_dir);	  strcpy (cp, "/passwd");	  cp = stpcpy (passwd_old, passwd_orig);	  strcpy (cp, ".old");	  if ((oldpf = fopen (passwd_orig, "r")) == NULL)	    {	      fprintf (stderr, _("Can't open `%s': %m\n"), passwd_orig);	      retval = -1;	      goto error_passwd;	    }          if (fstat (fileno (oldpf), &passwd_stat) < 0)            {	      fprintf (stderr, _("Can't stat `%s': %m\n"), passwd_orig);              fclose (oldpf);	      retval = -1;              goto error_passwd;            }#ifdef WITH_SELINUX          security_context_t prev_context;          if (set_default_context (passwd_orig, &prev_context) < 0)            {              fclose (oldpf);              retval = -1;              goto error_passwd;            }#endif	  /* Open a temp passwd file */	  newpf_fd = mkstemp (passwd_tmp);#ifdef WITH_SELINUX          if (restore_default_context (prev_context) < 0)	    {	      if (newpf_fd >= 0)		close (newpf_fd);              fclose (oldpf);              retval = -1;              goto error_passwd;	    }#endif	  if (newpf_fd == -1)	    {	      fprintf (stderr, _("Can't create `%s': %m\n"),		       passwd_orig);	      fclose (oldpf);	      retval = -1;	      goto error_passwd;	    }          if (fchmod (newpf_fd, passwd_stat.st_mode) < 0)	    {	      fprintf (stderr,		       _("Cannot change permissions for `%s': %s\n"),		       passwd_tmp, strerror (errno));	      fclose (oldpf);	      close (newpf_fd);	      unlink (passwd_tmp);	      retval = -1;	      goto error_passwd;	    }          if (fchown (newpf_fd, passwd_stat.st_uid, passwd_stat.st_gid) < 0)	    {	      fprintf (stderr,		       _("Cannot change owner/group for `%s': %s\n"),		       passwd_tmp, strerror (errno));	      fclose (oldpf);	      close (newpf_fd);	      unlink (passwd_tmp);	      retval = -1;	      goto error_passwd;	    }	  if (copy_xattr (passwd_orig, passwd_tmp) != 0)	    {	      fclose (oldpf);	      close (newpf_fd);	      unlink (passwd_tmp);	      retval = -1;	      goto error_passwd;	    }	  newpf = fdopen (newpf_fd, "w+");	  if (newpf == NULL)	    {	      fprintf (stderr, _("Can't open `%s': %m\n"), passwd_tmp);	      fclose (oldpf);	      close (newpf_fd);	      unlink (passwd_tmp);	      retval = -1;	      goto error_passwd;	    }	  gotit = 0;	  /* Loop over all passwd entries */	  while ((pw = fgetpwent (oldpf)) != NULL)	    {	      if (data->todo == DO_CREATE)		{		  /* insert the new user before we find a user with a		     higher UID or before we find a +/- character. */		  if (!gotit &&		      (/* data->pw.pw_uid < pw->pw_uid || XXX not yet? */

⌨️ 快捷键说明

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