hjl / source-git / glibc

Forked from source-git/glibc 3 years ago
Clone

Blame nss/nss_test.h

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