blob: 09a2cd62bc319b269ac0431f9a6bfbd01adeba87 [file] [log] [blame]
/*
* testpam_preload.c
*
* Fake test environment to run PAM tests unprivileged.
*/
#include "config.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <dlfcn.h>
#include <pwd.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#ifdef __APPLE__
# define _PATH_LIBC "libc.dylib"
#elif defined(__linux__)
# define _PATH_LIBC "libc.so.6"
#else
# define _PATH_LIBC "libc.so"
#endif
static void _preload_init(void) __attribute((constructor));
int (*_sys_open)(const char *pathname, int flags, ...);
int (*_sys_open64)(const char *pathname, int flags, ...);
FILE *(*_sys_fopen)(const char *filename, const char *mode);
FILE *(*_sys_fopen64)(const char *filename, const char *mode);
char *(*_sys_inet_ntoa)(struct in_addr in);
static void
_fatal(const char *msg)
{
perror(msg);
exit(1);
}
static void
_preload_init(void)
{
void *libc;
#ifndef DL_LAZY
# define DL_LAZY RTLD_LAZY
#endif
if (!(libc = dlopen(_PATH_LIBC, DL_LAZY))) {
_fatal("couldn't dlopen " _PATH_LIBC);
} else if (!(_sys_open = dlsym(libc, "open"))) {
_fatal("couldn't dlsym 'open'");
#ifdef HAVE_OPEN64
} else if (!(_sys_open = dlsym(libc, "open64"))) {
_fatal("couldn't dlsym 'open64'");
#endif
} else if (!(_sys_fopen = dlsym(libc, "fopen"))) {
_fatal("couldn't dlsym 'fopen'");
#ifdef HAVE_FOPEN64
} else if (!(_sys_fopen64 = dlsym(libc, "fopen64"))) {
_fatal("couldn't dlsym 'fopen64'");
#endif
}
}
const char *
_replace(const char *filename)
{
if (strcmp(filename, "/etc/pam.d/testpam") == 0 ||
strcmp(filename, "/etc/pam.conf") == 0) {
return (getenv("PAM_CONF"));
}
return (filename);
}
int
_isfallback(void)
{
char *t = getenv("FALLBACK");
return (t ? atoi(t) : 0);
}
int
open(const char *filename, int flags, ...)
{
return ((*_sys_open)(_replace(filename), flags));
}
int
open64(const char *filename, int flags, ...)
{
return ((*_sys_open64)(_replace(filename), flags));
}
FILE *
fopen(const char *filename, const char *mode)
{
return ((*_sys_fopen)(_replace(filename), mode));
}
FILE *
fopen64(const char *filename, const char *mode)
{
return ((*_sys_fopen64)(_replace(filename), mode));
}
char *
inet_ntoa(struct in_addr in)
{
if (_isfallback()) {
return "1.2.3.4";
}
else {
_sys_inet_ntoa = dlsym(RTLD_NEXT, "inet_ntoa");
return (*_sys_inet_ntoa)(in);
}
}
struct passwd *
getpwnam(const char *name)
{
// Tests rely on the username being correctly set.
static char username[1024];
strncpy(username, name, 1024);
username[1024 - 1] = '\0';
static struct passwd ret;
memcpy(&ret, getpwuid(getuid()), sizeof(struct passwd));
ret.pw_name = username;
return &ret;
}