Blame nss/nss_test.h

Packit Service 82fcde
/* Common code for NSS test cases.
Packit Service 82fcde
   Copyright (C) 2017-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; if not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* There are two (or more) NSS test modules named nss_test1,
Packit Service 82fcde
   nss_test2, etc.  Each one will call a function IN THE TEST CASE
Packit Service 82fcde
   called _nss_test1_init_hook(test_tables *) (or _nss_test2_*, etc).
Packit Service 82fcde
Packit Service 82fcde
   In your copy of the hook function, you may change the *_table
Packit Service 82fcde
   pointers in the passed struct to point to static tables in your
Packit Service 82fcde
   test case, and the test modules will use that table instead.
Packit Service 82fcde
Packit Service 82fcde
   Your tables MUST end with an entry that has a *_LAST() macro.
Packit Service 82fcde
   Use the *_ISLAST() macro to test for end of list.
Packit Service 82fcde
Packit Service 82fcde
   Use __nss_configure_lookup("passwd", "test1 test2") (for example) to
Packit Service 82fcde
   configure NSS to use the test modules.  */
Packit Service 82fcde
Packit Service 82fcde
#include <pwd.h>
Packit Service 82fcde
#include <grp.h>
Packit Service 82fcde
Packit Service 82fcde
typedef struct test_tables {
Packit Service 82fcde
  struct passwd *pwd_table;
Packit Service 82fcde
  struct group *grp_table;
Packit Service 82fcde
} test_tables;
Packit Service 82fcde
Packit Service 82fcde
extern void _nss_test1_init_hook (test_tables *) __attribute__((weak));
Packit Service 82fcde
extern void _nss_test2_init_hook (test_tables *) __attribute__((weak));
Packit Service 82fcde
Packit Service 82fcde
#define PWD_LAST()    { .pw_name = NULL, .pw_uid = 0 }
Packit Service 82fcde
#define GRP_LAST()    { .gr_name = NULL, .gr_gid = 0 }
Packit Service 82fcde
Packit Service 82fcde
#define PWD_ISLAST(p)    ((p)->pw_name == NULL && (p)->pw_uid == 0)
Packit Service 82fcde
#define GRP_ISLAST(g)    ((g)->gr_name == NULL && (g)->gr_gid == 0)
Packit Service 82fcde
Packit Service 82fcde
/* Macros to fill in the tables easily.  */
Packit Service 82fcde
Packit Service 82fcde
/* Note that the "unparameterized" fields are not magic; they're just
Packit Service 82fcde
   arbitrary values.  Tests which need to verify those fields should
Packit Service 82fcde
   fill them in explicitly.  */
Packit Service 82fcde
Packit Service 82fcde
#define PWD(u) \
Packit Service 82fcde
    { .pw_name = (char *) "name" #u, .pw_passwd = (char *) "*", .pw_uid = u,  \
Packit Service 82fcde
      .pw_gid = 100, .pw_gecos = (char *) "*", .pw_dir = (char *) "*",	      \
Packit Service 82fcde
      .pw_shell = (char *) "*" }
Packit Service 82fcde
Packit Service 82fcde
#define PWD_N(u,n)								\
Packit Service 82fcde
    { .pw_name = (char *) n, .pw_passwd = (char *) "*", .pw_uid = u,  \
Packit Service 82fcde
      .pw_gid = 100, .pw_gecos = (char *) "*", .pw_dir = (char *) "*",	      \
Packit Service 82fcde
      .pw_shell = (char *) "*" }
Packit Service 82fcde
Packit Service 82fcde
#define GRP(u) \
Packit Service 82fcde
    { .gr_name = (char *) "name" #u, .gr_passwd = (char *) "*", .gr_gid = u, \
Packit Service 82fcde
      .gr_mem = (char **) group_##u }
Packit Service 82fcde
Packit Service 82fcde
#define GRP_N(u,n,m)						     \
Packit Service 82fcde
    { .gr_name = (char *) n, .gr_passwd = (char *) "*", .gr_gid = u, \
Packit Service 82fcde
      .gr_mem = (char **) m }
Packit Service 82fcde
Packit Service 82fcde
/*------------------------------------------------------------*/
Packit Service 82fcde
Packit Service 82fcde
/* Helper functions for testing passwd entries.  Call
Packit Service 82fcde
   compare_passwds() passing a test index, the passwd entry you got,
Packit Service 82fcde
   and the expected passwd entry.  The function will return the number
Packit Service 82fcde
   of mismatches, or zero of the two records are the same.  */
Packit Service 82fcde
Packit Service 82fcde
static void __attribute__((used))
Packit Service 82fcde
print_passwd (struct passwd *p)
Packit Service 82fcde
{
Packit Service 82fcde
  printf ("    passwd %u.%s (%s) :", p->pw_uid, p->pw_name, p->pw_passwd);
Packit Service 82fcde
  printf (" %u, %s, %s, %s\n", p->pw_gid, p->pw_gecos, p->pw_dir, p->pw_shell);
Packit Service 82fcde
  printf ("\n");
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
static int  __attribute__((used))
Packit Service 82fcde
compare_passwd_field (int i, struct passwd *p, const char *got,
Packit Service 82fcde
		      const char *exp, const char *name)
Packit Service 82fcde
{
Packit Service 82fcde
  /* Does the entry have a value?  */
Packit Service 82fcde
  if (got == NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      printf ("[%d] passwd %s for %u.%s was (null)\n",
Packit Service 82fcde
	      i, name,
Packit Service 82fcde
	      p->pw_uid, p->pw_name);
Packit Service 82fcde
      return 1;
Packit Service 82fcde
    }
Packit Service 82fcde
  /* Does the entry have an unexpected name?  */
Packit Service 82fcde
  else if (exp == NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      printf ("[%d] passwd %s for %u.(null) was %s\n",
Packit Service 82fcde
	      i, name,
Packit Service 82fcde
	      p->pw_uid, got);
Packit Service 82fcde
      return 1;
Packit Service 82fcde
    }
Packit Service 82fcde
  /* And is it correct?  */
Packit Service 82fcde
  else if (got && strcmp (got, exp) != 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      printf("[%d] passwd entry %u.%s had %s \"%s\" (expected \"%s\") \n",
Packit Service 82fcde
	     i,
Packit Service 82fcde
	     p->pw_uid, p->pw_name, name,
Packit Service 82fcde
	     got, exp);
Packit Service 82fcde
      return 1;
Packit Service 82fcde
    }
Packit Service 82fcde
  return 0;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
#define COMPARE_PWD_FIELD(f) \
Packit Service 82fcde
  retval += compare_passwd_field (i, e, p->f, e->f, #f)
Packit Service 82fcde
Packit Service 82fcde
/* Compare passwd to expected passwd, return number of "problems".
Packit Service 82fcde
   "I" is the index into the testcase data.  */
Packit Service 82fcde
static int  __attribute__((used))
Packit Service 82fcde
compare_passwds (int i, struct passwd *p, struct passwd *e)
Packit Service 82fcde
{
Packit Service 82fcde
  int retval = 0;
Packit Service 82fcde
Packit Service 82fcde
  /* Did we get the expected uid?  */
Packit Service 82fcde
  if (p->pw_uid != e->pw_uid)
Packit Service 82fcde
    {
Packit Service 82fcde
      printf("[%d] passwd entry %u.%s had uid %u\n", i,
Packit Service 82fcde
	     e->pw_uid, e->pw_name,
Packit Service 82fcde
	     p->pw_uid);
Packit Service 82fcde
      ++retval;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Did we get the expected gid?  */
Packit Service 82fcde
  if (p->pw_gid != e->pw_gid)
Packit Service 82fcde
    {
Packit Service 82fcde
      printf("[%d] passwd entry %u.%s had gid %u (expected %u)\n", i,
Packit Service 82fcde
	     e->pw_uid, e->pw_name,
Packit Service 82fcde
	     p->pw_gid, e->pw_gid);
Packit Service 82fcde
      ++retval;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  COMPARE_PWD_FIELD (pw_name);
Packit Service 82fcde
  COMPARE_PWD_FIELD (pw_passwd);
Packit Service 82fcde
  COMPARE_PWD_FIELD (pw_gecos);
Packit Service 82fcde
  COMPARE_PWD_FIELD (pw_dir);
Packit Service 82fcde
  COMPARE_PWD_FIELD (pw_shell);
Packit Service 82fcde
Packit Service 82fcde
  if (retval > 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* Left in for debugging later, if needed.  */
Packit Service 82fcde
      print_passwd (p);
Packit Service 82fcde
      print_passwd (e);
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  return retval;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/*------------------------------------------------------------*/
Packit Service 82fcde
Packit Service 82fcde
/* Helpers for checking group entries.  See passwd helper comment
Packit Service 82fcde
   above for details.  */
Packit Service 82fcde
Packit Service 82fcde
static void __attribute__((used))
Packit Service 82fcde
print_group (struct group *g)
Packit Service 82fcde
{
Packit Service 82fcde
  int j;
Packit Service 82fcde
Packit Service 82fcde
  printf ("    group %u.%s (%s) :", g->gr_gid, g->gr_name, g->gr_passwd);
Packit Service 82fcde
  if (g->gr_mem)
Packit Service 82fcde
    for (j=0; g->gr_mem[j]; j++)
Packit Service 82fcde
      printf ("%s%s", j==0 ? " " : ", ", g->gr_mem[j]);
Packit Service 82fcde
  printf ("\n");
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Compare group to expected group, return number of "problems".  "I"
Packit Service 82fcde
   is the index into the testcase data.  */
Packit Service 82fcde
static int  __attribute__((used))
Packit Service 82fcde
compare_groups (int i, struct group *g, struct group *e)
Packit Service 82fcde
{
Packit Service 82fcde
  int j;
Packit Service 82fcde
  int retval = 0;
Packit Service 82fcde
Packit Service 82fcde
  /* Did we get the expected gid?  */
Packit Service 82fcde
  if (g->gr_gid != e->gr_gid)
Packit Service 82fcde
    {
Packit Service 82fcde
      printf("[%d] group entry %u.%s had gid %u\n", i,
Packit Service 82fcde
	     e->gr_gid, e->gr_name,
Packit Service 82fcde
	     g->gr_gid);
Packit Service 82fcde
      ++retval;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Does the entry have a name?  */
Packit Service 82fcde
  if (g->gr_name == NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      printf ("[%d] group name for %u.%s was (null)\n", i,
Packit Service 82fcde
	      e->gr_gid, e->gr_name);
Packit Service 82fcde
      ++retval;
Packit Service 82fcde
    }
Packit Service 82fcde
  /* Does the entry have an unexpected name?  */
Packit Service 82fcde
  else if (e->gr_name == NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      printf ("[%d] group name for %u.(null) was %s\n", i,
Packit Service 82fcde
	      e->gr_gid, g->gr_name);
Packit Service 82fcde
      ++retval;
Packit Service 82fcde
    }
Packit Service 82fcde
  /* And is it correct?  */
Packit Service 82fcde
  else if (strcmp (g->gr_name, e->gr_name) != 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      printf("[%d] group entry %u.%s had name \"%s\"\n", i,
Packit Service 82fcde
	     e->gr_gid, e->gr_name,
Packit Service 82fcde
	     g->gr_name);
Packit Service 82fcde
      ++retval;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Does the entry have a password?  */
Packit Service 82fcde
  if (g->gr_passwd == NULL && e->gr_passwd != NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      printf ("[%d] group password for %u.%s was NULL\n", i,
Packit Service 82fcde
	      e->gr_gid, e->gr_name);
Packit Service 82fcde
      ++retval;
Packit Service 82fcde
    }
Packit Service 82fcde
  else if (g->gr_passwd != NULL && e->gr_passwd == NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      printf ("[%d] group password for %u.%s was not NULL\n", i,
Packit Service 82fcde
	      e->gr_gid, e->gr_name);
Packit Service 82fcde
      ++retval;
Packit Service 82fcde
    }
Packit Service 82fcde
  /* And is it correct?  */
Packit Service 82fcde
  else if (g->gr_passwd && strcmp (g->gr_passwd, e->gr_passwd) != 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      printf("[%d] group entry %u.%s had password \"%s\" (not \"%s\")\n", i,
Packit Service 82fcde
	     e->gr_gid, e->gr_name,
Packit Service 82fcde
	     g->gr_passwd, e->gr_passwd);
Packit Service 82fcde
      ++retval;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Now compare group members... */
Packit Service 82fcde
Packit Service 82fcde
  if (e->gr_mem != NULL && g->gr_mem == NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      printf("[%d] group entry %u.%s missing member list\n", i,
Packit Service 82fcde
	     e->gr_gid, e->gr_name);
Packit Service 82fcde
      ++retval;
Packit Service 82fcde
    }
Packit Service 82fcde
  else if (e->gr_mem == NULL && g->gr_mem != NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      printf("[%d] group entry %u.%s has unexpected member list\n", i,
Packit Service 82fcde
	     e->gr_gid, e->gr_name);
Packit Service 82fcde
      ++retval;
Packit Service 82fcde
    }
Packit Service 82fcde
  else if (e->gr_mem == NULL && g->gr_mem == NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* This case is OK.  */
Packit Service 82fcde
    }
Packit Service 82fcde
  else
Packit Service 82fcde
    {
Packit Service 82fcde
      /* Compare two existing lists.  */
Packit Service 82fcde
      j = 0;
Packit Service 82fcde
      for (;;)
Packit Service 82fcde
	{
Packit Service 82fcde
	  if (g->gr_mem[j] == NULL && e->gr_mem[j] == NULL)
Packit Service 82fcde
	    {
Packit Service 82fcde
	      /* Matching end-of-lists.  */
Packit Service 82fcde
	      break;
Packit Service 82fcde
	    }
Packit Service 82fcde
	  if (g->gr_mem[j] == NULL)
Packit Service 82fcde
	    {
Packit Service 82fcde
	      printf ("[%d] group member list for %u.%s is too short.\n", i,
Packit Service 82fcde
		      e->gr_gid, e->gr_name);
Packit Service 82fcde
	      ++retval;
Packit Service 82fcde
	      break;
Packit Service 82fcde
	    }
Packit Service 82fcde
	  if (e->gr_mem[j] == NULL)
Packit Service 82fcde
	    {
Packit Service 82fcde
	      printf ("[%d] group member list for %u.%s is too long.\n", i,
Packit Service 82fcde
		      e->gr_gid, e->gr_name);
Packit Service 82fcde
	      ++retval;
Packit Service 82fcde
	      break;
Packit Service 82fcde
	    }
Packit Service 82fcde
	  if (strcmp (g->gr_mem[j], e->gr_mem[j]) != 0)
Packit Service 82fcde
	    {
Packit Service 82fcde
	      printf ("[%d] group member list for %u.%s differs: %s vs %s.\n", i,
Packit Service 82fcde
		      e->gr_gid, e->gr_name,
Packit Service 82fcde
		      e->gr_mem[j], g->gr_mem[j]);
Packit Service 82fcde
	      ++retval;
Packit Service 82fcde
	    }
Packit Service 82fcde
Packit Service 82fcde
	  j++;
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  if (retval > 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* Left in for debugging later, if needed.  */
Packit Service 82fcde
      print_group (g);
Packit Service 82fcde
      print_group (e);
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  return retval;
Packit Service 82fcde
}