Blame nscd/nscd_conf.c

Packit 6c4009
/* Copyright (c) 1998-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
   Contributed by Thorsten Kukuk <kukuk@suse.de>, 1998.
Packit 6c4009
Packit 6c4009
   This program is free software; you can redistribute it and/or modify
Packit 6c4009
   it under the terms of the GNU General Public License as published
Packit 6c4009
   by the Free Software Foundation; version 2 of the License, or
Packit 6c4009
   (at your option) any later version.
Packit 6c4009
Packit 6c4009
   This program is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 6c4009
   GNU General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU General Public License
Packit 6c4009
   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
#include <ctype.h>
Packit 6c4009
#include <errno.h>
Packit 6c4009
#include <error.h>
Packit 6c4009
#include <libintl.h>
Packit 6c4009
#include <malloc.h>
Packit 6c4009
#include <pwd.h>
Packit 6c4009
#include <stdio.h>
Packit 6c4009
#include <stdio_ext.h>
Packit 6c4009
#include <stdlib.h>
Packit 6c4009
#include <string.h>
Packit 6c4009
#include <unistd.h>
Packit 6c4009
#include <sys/param.h>
Packit 6c4009
#include <sys/types.h>
Packit 6c4009
Packit 6c4009
#include "dbg_log.h"
Packit 6c4009
#include "nscd.h"
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Names of the databases.  */
Packit 6c4009
const char *const dbnames[lastdb] =
Packit 6c4009
{
Packit 6c4009
  [pwddb] = "passwd",
Packit 6c4009
  [grpdb] = "group",
Packit 6c4009
  [hstdb] = "hosts",
Packit 6c4009
  [servdb] = "services",
Packit 6c4009
  [netgrdb] = "netgroup"
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
Packit 6c4009
static int
Packit 6c4009
find_db (const char *name)
Packit 6c4009
{
Packit 6c4009
  for (int cnt = 0; cnt < lastdb; ++cnt)
Packit 6c4009
    if (strcmp (name, dbnames[cnt]) == 0)
Packit 6c4009
      return cnt;
Packit 6c4009
Packit 6c4009
  error (0, 0, _("database %s is not supported"), name);
Packit 6c4009
  return -1;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
int
Packit 6c4009
nscd_parse_file (const char *fname, struct database_dyn dbs[lastdb])
Packit 6c4009
{
Packit 6c4009
  FILE *fp;
Packit 6c4009
  char *line, *cp, *entry, *arg1, *arg2;
Packit 6c4009
  size_t len;
Packit 6c4009
  int cnt;
Packit 6c4009
  const unsigned int initial_error_message_count = error_message_count;
Packit 6c4009
Packit 6c4009
  /* Open the configuration file.  */
Packit 6c4009
  fp = fopen (fname, "r");
Packit 6c4009
  if (fp == NULL)
Packit 6c4009
    return -1;
Packit 6c4009
Packit 6c4009
  /* The stream is not used by more than one thread.  */
Packit 6c4009
  (void) __fsetlocking (fp, FSETLOCKING_BYCALLER);
Packit 6c4009
Packit 6c4009
  line = NULL;
Packit 6c4009
  len = 0;
Packit 6c4009
Packit 6c4009
  do
Packit 6c4009
    {
Packit 6c4009
      ssize_t n = getline (&line, &len, fp);
Packit 6c4009
      if (n < 0)
Packit 6c4009
	break;
Packit 6c4009
      if (line[n - 1] == '\n')
Packit 6c4009
	line[n - 1] = '\0';
Packit 6c4009
Packit 6c4009
      /* Because the file format does not know any form of quoting we
Packit 6c4009
	 can search forward for the next '#' character and if found
Packit 6c4009
	 make it terminating the line.  */
Packit 6c4009
      *strchrnul (line, '#') = '\0';
Packit 6c4009
Packit 6c4009
      /* If the line is blank it is ignored.  */
Packit 6c4009
      if (line[0] == '\0')
Packit 6c4009
	continue;
Packit 6c4009
Packit 6c4009
      entry = line;
Packit 6c4009
      while (isspace (*entry) && *entry != '\0')
Packit 6c4009
	++entry;
Packit 6c4009
      cp = entry;
Packit 6c4009
      while (!isspace (*cp) && *cp != '\0')
Packit 6c4009
	++cp;
Packit 6c4009
      arg1 = cp;
Packit 6c4009
      ++arg1;
Packit 6c4009
      *cp = '\0';
Packit 6c4009
      if (strlen (entry) == 0)
Packit 6c4009
	error (0, 0, _("Parse error: %s"), line);
Packit 6c4009
      while (isspace (*arg1) && *arg1 != '\0')
Packit 6c4009
	++arg1;
Packit 6c4009
      cp = arg1;
Packit 6c4009
      while (!isspace (*cp) && *cp != '\0')
Packit 6c4009
	++cp;
Packit 6c4009
      arg2 = cp;
Packit 6c4009
      ++arg2;
Packit 6c4009
      *cp = '\0';
Packit 6c4009
      if (strlen (arg2) > 0)
Packit 6c4009
	{
Packit 6c4009
	  while (isspace (*arg2) && *arg2 != '\0')
Packit 6c4009
	    ++arg2;
Packit 6c4009
	  cp = arg2;
Packit 6c4009
	  while (!isspace (*cp) && *cp != '\0')
Packit 6c4009
	    ++cp;
Packit 6c4009
	  *cp = '\0';
Packit 6c4009
	}
Packit 6c4009
Packit 6c4009
      if (strcmp (entry, "positive-time-to-live") == 0)
Packit 6c4009
	{
Packit 6c4009
	  int idx = find_db (arg1);
Packit 6c4009
	  if (idx >= 0)
Packit 6c4009
	    dbs[idx].postimeout = atol (arg2);
Packit 6c4009
	}
Packit 6c4009
      else if (strcmp (entry, "negative-time-to-live") == 0)
Packit 6c4009
	{
Packit 6c4009
	  int idx = find_db (arg1);
Packit 6c4009
	  if (idx >= 0)
Packit 6c4009
	    dbs[idx].negtimeout = atol (arg2);
Packit 6c4009
	}
Packit 6c4009
      else if (strcmp (entry, "suggested-size") == 0)
Packit 6c4009
	{
Packit 6c4009
	  int idx = find_db (arg1);
Packit 6c4009
	  if (idx >= 0)
Packit 6c4009
	    dbs[idx].suggested_module
Packit 6c4009
	      = atol (arg2) ?: DEFAULT_SUGGESTED_MODULE;
Packit 6c4009
	}
Packit 6c4009
      else if (strcmp (entry, "enable-cache") == 0)
Packit 6c4009
	{
Packit 6c4009
	  int idx = find_db (arg1);
Packit 6c4009
	  if (idx >= 0)
Packit 6c4009
	    {
Packit 6c4009
	      if (strcmp (arg2, "no") == 0)
Packit 6c4009
		dbs[idx].enabled = 0;
Packit 6c4009
	      else if (strcmp (arg2, "yes") == 0)
Packit 6c4009
		dbs[idx].enabled = 1;
Packit 6c4009
	    }
Packit 6c4009
	}
Packit 6c4009
      else if (strcmp (entry, "check-files") == 0)
Packit 6c4009
	{
Packit 6c4009
	  int idx = find_db (arg1);
Packit 6c4009
	  if (idx >= 0)
Packit 6c4009
	    {
Packit 6c4009
	      if (strcmp (arg2, "no") == 0)
Packit 6c4009
		dbs[idx].check_file = 0;
Packit 6c4009
	      else if (strcmp (arg2, "yes") == 0)
Packit 6c4009
		dbs[idx].check_file = 1;
Packit 6c4009
	    }
Packit 6c4009
	}
Packit 6c4009
      else if (strcmp (entry, "max-db-size") == 0)
Packit 6c4009
	{
Packit 6c4009
	  int idx = find_db (arg1);
Packit 6c4009
	  if (idx >= 0)
Packit 6c4009
	    dbs[idx].max_db_size = atol (arg2) ?: DEFAULT_MAX_DB_SIZE;
Packit 6c4009
	}
Packit 6c4009
      else if (strcmp (entry, "logfile") == 0)
Packit 6c4009
	set_logfile (arg1);
Packit 6c4009
      else if (strcmp (entry, "debug-level") == 0)
Packit 6c4009
	{
Packit 6c4009
	  int level = atoi (arg1);
Packit 6c4009
	  if (level > 0)
Packit 6c4009
	    debug_level = level;
Packit 6c4009
	}
Packit 6c4009
      else if (strcmp (entry, "threads") == 0)
Packit 6c4009
	{
Packit 6c4009
	  if (nthreads == -1)
Packit 6c4009
	    nthreads = MAX (atol (arg1), lastdb);
Packit 6c4009
	}
Packit 6c4009
      else if (strcmp (entry, "max-threads") == 0)
Packit 6c4009
	{
Packit 6c4009
	  max_nthreads = MAX (atol (arg1), lastdb);
Packit 6c4009
	}
Packit 6c4009
      else if (strcmp (entry, "server-user") == 0)
Packit 6c4009
	{
Packit 6c4009
	  if (!arg1)
Packit 6c4009
	    error (0, 0, _("Must specify user name for server-user option"));
Packit 6c4009
	  else
Packit Bot 0c2104
	    server_user = xstrdup (arg1);
Packit 6c4009
	}
Packit 6c4009
      else if (strcmp (entry, "stat-user") == 0)
Packit 6c4009
	{
Packit 6c4009
	  if (arg1 == NULL)
Packit 6c4009
	    error (0, 0, _("Must specify user name for stat-user option"));
Packit 6c4009
	  else
Packit 6c4009
	    {
Packit 6c4009
	      stat_user = xstrdup (arg1);
Packit 6c4009
Packit 6c4009
	      struct passwd *pw = getpwnam (stat_user);
Packit 6c4009
	      if (pw != NULL)
Packit 6c4009
		stat_uid = pw->pw_uid;
Packit 6c4009
	    }
Packit 6c4009
	}
Packit 6c4009
      else if (strcmp (entry, "persistent") == 0)
Packit 6c4009
	{
Packit 6c4009
	  int idx = find_db (arg1);
Packit 6c4009
	  if (idx >= 0)
Packit 6c4009
	    {
Packit 6c4009
	      if (strcmp (arg2, "no") == 0)
Packit 6c4009
		dbs[idx].persistent = 0;
Packit 6c4009
	      else if (strcmp (arg2, "yes") == 0)
Packit 6c4009
		dbs[idx].persistent = 1;
Packit 6c4009
	    }
Packit 6c4009
	}
Packit 6c4009
      else if (strcmp (entry, "shared") == 0)
Packit 6c4009
	{
Packit 6c4009
	  int idx = find_db (arg1);
Packit 6c4009
	  if (idx >= 0)
Packit 6c4009
	    {
Packit 6c4009
	      if (strcmp (arg2, "no") == 0)
Packit 6c4009
		dbs[idx].shared = 0;
Packit 6c4009
	      else if (strcmp (arg2, "yes") == 0)
Packit 6c4009
		dbs[idx].shared = 1;
Packit 6c4009
	    }
Packit 6c4009
	}
Packit 6c4009
      else if (strcmp (entry, "reload-count") == 0)
Packit 6c4009
	{
Packit 6c4009
	  if (strcasecmp (arg1, "unlimited") == 0)
Packit 6c4009
	    reload_count = UINT_MAX;
Packit 6c4009
	  else
Packit 6c4009
	    {
Packit 6c4009
	      unsigned long int count = strtoul (arg1, NULL, 0);
Packit 6c4009
	      if (count > UINT8_MAX - 1)
Packit 6c4009
		reload_count = UINT_MAX;
Packit 6c4009
	      else
Packit 6c4009
		reload_count = count;
Packit 6c4009
	    }
Packit 6c4009
	}
Packit 6c4009
      else if (strcmp (entry, "paranoia") == 0)
Packit 6c4009
	{
Packit 6c4009
	  if (strcmp (arg1, "no") == 0)
Packit 6c4009
	    paranoia = 0;
Packit 6c4009
	  else if (strcmp (arg1, "yes") == 0)
Packit 6c4009
	    paranoia = 1;
Packit 6c4009
	}
Packit 6c4009
      else if (strcmp (entry, "restart-interval") == 0)
Packit 6c4009
	{
Packit 6c4009
	  if (arg1 != NULL)
Packit 6c4009
	    restart_interval = atol (arg1);
Packit 6c4009
	  else
Packit 6c4009
	    error (0, 0, _("Must specify value for restart-interval option"));
Packit 6c4009
	}
Packit 6c4009
      else if (strcmp (entry, "auto-propagate") == 0)
Packit 6c4009
	{
Packit 6c4009
	  int idx = find_db (arg1);
Packit 6c4009
	  if (idx >= 0)
Packit 6c4009
	    {
Packit 6c4009
	      if (strcmp (arg2, "no") == 0)
Packit 6c4009
		dbs[idx].propagate = 0;
Packit 6c4009
	      else if (strcmp (arg2, "yes") == 0)
Packit 6c4009
		dbs[idx].propagate = 1;
Packit 6c4009
	    }
Packit 6c4009
	}
Packit 6c4009
      else
Packit 6c4009
	error (0, 0, _("Unknown option: %s %s %s"), entry, arg1, arg2);
Packit 6c4009
    }
Packit 6c4009
  while (!feof_unlocked (fp));
Packit 6c4009
Packit 6c4009
  if (paranoia)
Packit 6c4009
    {
Packit 6c4009
      restart_time = time (NULL) + restart_interval;
Packit 6c4009
Packit 6c4009
      /* Save the old current workding directory if we are in paranoia
Packit 6c4009
	 mode.  We have to change back to it.  */
Packit 6c4009
      oldcwd = get_current_dir_name ();
Packit 6c4009
      if (oldcwd == NULL)
Packit 6c4009
	{
Packit 6c4009
	  error (0, 0, _("\
Packit 6c4009
cannot get current working directory: %s; disabling paranoia mode"),
Packit 6c4009
		   strerror (errno));
Packit 6c4009
	  paranoia = 0;
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  /* Enforce sanity.  */
Packit 6c4009
  if (max_nthreads < nthreads)
Packit 6c4009
    max_nthreads = nthreads;
Packit 6c4009
Packit 6c4009
  for (cnt = 0; cnt < lastdb; ++cnt)
Packit 6c4009
    {
Packit 6c4009
      size_t datasize = (sizeof (struct database_pers_head)
Packit 6c4009
			 + roundup (dbs[cnt].suggested_module
Packit 6c4009
				    * sizeof (ref_t), ALIGN)
Packit 6c4009
			 + (dbs[cnt].suggested_module
Packit 6c4009
			    * DEFAULT_DATASIZE_PER_BUCKET));
Packit 6c4009
      if (datasize > dbs[cnt].max_db_size)
Packit 6c4009
	{
Packit 6c4009
	  error (0, 0, _("maximum file size for %s database too small"),
Packit 6c4009
		   dbnames[cnt]);
Packit 6c4009
	  dbs[cnt].max_db_size = datasize;
Packit 6c4009
	}
Packit 6c4009
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  /* Free the buffer.  */
Packit 6c4009
  free (line);
Packit 6c4009
  /* Close configuration file.  */
Packit 6c4009
  fclose (fp);
Packit 6c4009
Packit 6c4009
  return error_message_count != initial_error_message_count;
Packit 6c4009
}