Blame nss/nss_test1.c

Packit 6c4009
/* Template generic NSS service provider.  See nss_test.h for usage.
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
#include <errno.h>
Packit 6c4009
#include <nss.h>
Packit 6c4009
#include <pthread.h>
Packit 6c4009
#include <string.h>
Packit 6c4009
#include <stdio.h>
Packit 6c4009
#include <alloc_buffer.h>
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* We need to be able to handle NULLs "properly" within the testsuite,
Packit 6c4009
   to test known bad data.  */
Packit 6c4009
#define alloc_buffer_maybe_copy_string(b,s) s ? alloc_buffer_copy_string (b, s) : NULL;
Packit 6c4009
Packit 6c4009
/* This file is the master template.  Other instances of this test
Packit 6c4009
   module should define NAME(x) to have their name instead of "test1",
Packit 6c4009
   then include this file.
Packit 6c4009
*/
Packit 6c4009
#define NAME_(x,n) _nss_##n##_##x
Packit 6c4009
#ifndef NAME
Packit 6c4009
#define NAME(x) NAME_(x,test1)
Packit 6c4009
#endif
Packit 6c4009
#define NAMESTR__(x) #x
Packit 6c4009
#define NAMESTR_(x) NAMESTR__(x)
Packit 6c4009
#define NAMESTR(x) NAMESTR_(NAME(x))
Packit 6c4009
Packit 6c4009
#include "nss_test.h"
Packit 6c4009
Packit 6c4009
/* -------------------------------------------------- */
Packit 6c4009
/* Default Data.  */
Packit 6c4009
Packit 6c4009
static struct passwd default_pwd_data[] =
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
    PWD (30),
Packit 6c4009
    PWD (100),
Packit 6c4009
    PWD (200),
Packit 6c4009
    PWD (60),
Packit 6c4009
    PWD (20000)
Packit 6c4009
  };
Packit 6c4009
#define default_npwd_data \
Packit 6c4009
  (sizeof (default_pwd_data) / sizeof (default_pwd_data[0]))
Packit 6c4009
Packit 6c4009
static struct passwd *pwd_data = default_pwd_data;
Packit 6c4009
static int npwd_data = default_npwd_data;
Packit 6c4009
Packit 6c4009
static struct group *grp_data = NULL;
Packit 6c4009
static int ngrp_data = 0;
Packit 6c4009
Packit 6c4009
/* This function will get called, and once per session, look back into
Packit 6c4009
   the test case's executable for an init hook function, and call
Packit 6c4009
   it.  */
Packit 6c4009
Packit 6c4009
static int initted = 0;
Packit 6c4009
static void
Packit 6c4009
init(void)
Packit 6c4009
{
Packit 6c4009
  test_tables t;
Packit 6c4009
  int i;
Packit 6c4009
Packit 6c4009
  if (initted)
Packit 6c4009
    return;
Packit 6c4009
  if (NAME(init_hook))
Packit 6c4009
    {
Packit 6c4009
      memset (&t, 0, sizeof(t));
Packit 6c4009
      NAME(init_hook)(&t);
Packit 6c4009
Packit 6c4009
      if (t.pwd_table)
Packit 6c4009
	{
Packit 6c4009
	  pwd_data = t.pwd_table;
Packit 6c4009
	  for (i=0; ! PWD_ISLAST(& pwd_data[i]); i++)
Packit 6c4009
	    ;
Packit 6c4009
	  npwd_data = i;
Packit 6c4009
	}
Packit 6c4009
Packit 6c4009
      if (t.grp_table)
Packit 6c4009
	{
Packit 6c4009
	  grp_data = t.grp_table;
Packit 6c4009
	  for (i=0; ! GRP_ISLAST(& grp_data[i]); i++)
Packit 6c4009
	    ;
Packit 6c4009
	  ngrp_data = i;
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
  initted = 1;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* -------------------------------------------------- */
Packit 6c4009
/* Password handling.  */
Packit 6c4009
Packit 6c4009
static size_t pwd_iter;
Packit 6c4009
#define CURPWD pwd_data[pwd_iter]
Packit 6c4009
Packit 6c4009
static pthread_mutex_t pwd_lock = PTHREAD_MUTEX_INITIALIZER;
Packit 6c4009
Packit 6c4009
enum nss_status
Packit 6c4009
NAME(setpwent) (int stayopen)
Packit 6c4009
{
Packit 6c4009
  init();
Packit 6c4009
  pwd_iter = 0;
Packit 6c4009
  return NSS_STATUS_SUCCESS;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
enum nss_status
Packit 6c4009
NAME(endpwent) (void)
Packit 6c4009
{
Packit 6c4009
  init();
Packit 6c4009
  return NSS_STATUS_SUCCESS;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static enum nss_status
Packit 6c4009
copy_passwd (struct passwd *result, struct passwd *local,
Packit 6c4009
	    char *buffer, size_t buflen, int *errnop)
Packit 6c4009
{
Packit 6c4009
  struct alloc_buffer buf = alloc_buffer_create (buffer, buflen);
Packit 6c4009
Packit 6c4009
  result->pw_name = alloc_buffer_maybe_copy_string (&buf, local->pw_name);
Packit 6c4009
  result->pw_passwd = alloc_buffer_maybe_copy_string (&buf, local->pw_passwd);
Packit 6c4009
  result->pw_uid = local->pw_uid;
Packit 6c4009
  result->pw_gid = local->pw_gid;
Packit 6c4009
  result->pw_gecos = alloc_buffer_maybe_copy_string (&buf, local->pw_gecos);
Packit 6c4009
  result->pw_dir = alloc_buffer_maybe_copy_string (&buf, local->pw_dir);
Packit 6c4009
  result->pw_shell = alloc_buffer_maybe_copy_string (&buf, local->pw_shell);
Packit 6c4009
Packit 6c4009
  if (alloc_buffer_has_failed (&buf))
Packit 6c4009
    {
Packit 6c4009
      *errnop = ERANGE;
Packit 6c4009
      return NSS_STATUS_TRYAGAIN;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  return NSS_STATUS_SUCCESS;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
enum nss_status
Packit 6c4009
NAME(getpwent_r) (struct passwd *result, char *buffer, size_t buflen,
Packit 6c4009
		       int *errnop)
Packit 6c4009
{
Packit 6c4009
  int res = NSS_STATUS_SUCCESS;
Packit 6c4009
Packit 6c4009
  init();
Packit 6c4009
  pthread_mutex_lock (&pwd_lock);
Packit 6c4009
Packit 6c4009
  if (pwd_iter >= npwd_data)
Packit 6c4009
    res = NSS_STATUS_NOTFOUND;
Packit 6c4009
  else
Packit 6c4009
    {
Packit 6c4009
      res = copy_passwd (result, &CURPWD, buffer, buflen, errnop);
Packit 6c4009
      ++pwd_iter;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  pthread_mutex_unlock (&pwd_lock);
Packit 6c4009
Packit 6c4009
  return res;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
enum nss_status
Packit 6c4009
NAME(getpwuid_r) (uid_t uid, struct passwd *result, char *buffer,
Packit 6c4009
		       size_t buflen, int *errnop)
Packit 6c4009
{
Packit 6c4009
  init();
Packit 6c4009
  for (size_t idx = 0; idx < npwd_data; ++idx)
Packit 6c4009
    if (pwd_data[idx].pw_uid == uid)
Packit 6c4009
      return copy_passwd (result, &pwd_data[idx], buffer, buflen, errnop);
Packit 6c4009
Packit 6c4009
  return NSS_STATUS_NOTFOUND;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
enum nss_status
Packit 6c4009
NAME(getpwnam_r) (const char *name, struct passwd *result, char *buffer,
Packit 6c4009
		       size_t buflen, int *errnop)
Packit 6c4009
{
Packit 6c4009
  init();
Packit 6c4009
  for (size_t idx = 0; idx < npwd_data; ++idx)
Packit 6c4009
    if (strcmp (pwd_data[idx].pw_name, name) == 0)
Packit 6c4009
      return copy_passwd (result, &pwd_data[idx], buffer, buflen, errnop);
Packit 6c4009
Packit 6c4009
  return NSS_STATUS_NOTFOUND;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* -------------------------------------------------- */
Packit 6c4009
/* Group handling.  */
Packit 6c4009
Packit 6c4009
static size_t grp_iter;
Packit 6c4009
#define CURGRP grp_data[grp_iter]
Packit 6c4009
Packit 6c4009
static pthread_mutex_t grp_lock = PTHREAD_MUTEX_INITIALIZER;
Packit 6c4009
Packit 6c4009
enum nss_status
Packit 6c4009
NAME(setgrent) (int stayopen)
Packit 6c4009
{
Packit 6c4009
  init();
Packit 6c4009
  grp_iter = 0;
Packit 6c4009
  return NSS_STATUS_SUCCESS;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
enum nss_status
Packit 6c4009
NAME(endgrent) (void)
Packit 6c4009
{
Packit 6c4009
  init();
Packit 6c4009
  return NSS_STATUS_SUCCESS;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static enum nss_status
Packit 6c4009
copy_group (struct group *result, struct group *local,
Packit 6c4009
	    char *buffer, size_t buflen, int *errnop)
Packit 6c4009
{
Packit 6c4009
  struct alloc_buffer buf = alloc_buffer_create (buffer, buflen);
Packit 6c4009
  char **memlist;
Packit 6c4009
  int i;
Packit 6c4009
Packit 6c4009
  if (local->gr_mem)
Packit 6c4009
    {
Packit 6c4009
      i = 0;
Packit 6c4009
      while (local->gr_mem[i])
Packit 6c4009
	++i;
Packit 6c4009
Packit 6c4009
      memlist = alloc_buffer_alloc_array (&buf, char *, i + 1);
Packit 6c4009
Packit 6c4009
      if (memlist) {
Packit 6c4009
	for (i = 0; local->gr_mem[i]; ++i)
Packit 6c4009
	  memlist[i] = alloc_buffer_maybe_copy_string (&buf, local->gr_mem[i]);
Packit 6c4009
	memlist[i] = NULL;
Packit 6c4009
      }
Packit 6c4009
Packit 6c4009
      result->gr_mem = memlist;
Packit 6c4009
    }
Packit 6c4009
  else
Packit 6c4009
    result->gr_mem = NULL;
Packit 6c4009
Packit 6c4009
  result->gr_name = alloc_buffer_maybe_copy_string (&buf, local->gr_name);
Packit 6c4009
  result->gr_passwd = alloc_buffer_maybe_copy_string (&buf, local->gr_passwd);
Packit 6c4009
  result->gr_gid = local->gr_gid;
Packit 6c4009
Packit 6c4009
  if (alloc_buffer_has_failed (&buf))
Packit 6c4009
    {
Packit 6c4009
      *errnop = ERANGE;
Packit 6c4009
      return NSS_STATUS_TRYAGAIN;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  return NSS_STATUS_SUCCESS;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
enum nss_status
Packit 6c4009
NAME(getgrent_r) (struct group *result, char *buffer, size_t buflen,
Packit 6c4009
		       int *errnop)
Packit 6c4009
{
Packit 6c4009
  int res = NSS_STATUS_SUCCESS;
Packit 6c4009
Packit 6c4009
  init();
Packit 6c4009
  pthread_mutex_lock (&grp_lock);
Packit 6c4009
Packit 6c4009
  if (grp_iter >= ngrp_data)
Packit 6c4009
    res = NSS_STATUS_NOTFOUND;
Packit 6c4009
  else
Packit 6c4009
    {
Packit 6c4009
      res = copy_group (result, &CURGRP, buffer, buflen, errnop);
Packit 6c4009
      ++grp_iter;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  pthread_mutex_unlock (&pwd_lock);
Packit 6c4009
Packit 6c4009
  return res;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
enum nss_status
Packit 6c4009
NAME(getgrgid_r) (gid_t gid, struct group *result, char *buffer,
Packit 6c4009
		  size_t buflen, int *errnop)
Packit 6c4009
{
Packit 6c4009
  init();
Packit 6c4009
  for (size_t idx = 0; idx < ngrp_data; ++idx)
Packit 6c4009
    if (grp_data[idx].gr_gid == gid)
Packit 6c4009
      return copy_group (result, &grp_data[idx], buffer, buflen, errnop);
Packit 6c4009
Packit 6c4009
  return NSS_STATUS_NOTFOUND;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
enum nss_status
Packit 6c4009
NAME(getgrnam_r) (const char *name, struct group *result, char *buffer,
Packit 6c4009
		       size_t buflen, int *errnop)
Packit 6c4009
{
Packit 6c4009
  init();
Packit 6c4009
  for (size_t idx = 0; idx < ngrp_data; ++idx)
Packit 6c4009
    if (strcmp (pwd_data[idx].pw_name, name) == 0)
Packit 6c4009
      {
Packit 6c4009
	return copy_group (result, &grp_data[idx], buffer, buflen, errnop);
Packit 6c4009
      }
Packit 6c4009
Packit 6c4009
  return NSS_STATUS_NOTFOUND;
Packit 6c4009
}