/*
* Interface for fake PAM library, used for testing.
*
* This contains the basic public interfaces for the fake PAM library, used
* for testing, and some general utility functions.
*
* The canonical version of this file is maintained in the rra-c-util package,
* which can be found at .
*
* Written by Russ Allbery
* Copyright 2010-2011, 2014
* The Board of Trustees of the Leland Stanford Junior University
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* SPDX-License-Identifier: MIT
*/
#include
#include
#include
#include
#include
#include
/* Stores the static struct passwd returned by getpwnam if the name matches. */
static struct passwd *pwd_info = NULL;
/* Used for unused parameters to silence gcc warnings. */
#define UNUSED __attribute__((__unused__))
/*
* Initializes the pam_handle_t data structure. This function is only called
* from test programs, not from any of the module code. We can put anything
* we want in this structure, since it's opaque to the regular code.
*/
int
pam_start(const char *service_name, const char *user,
const struct pam_conv *pam_conversation, pam_handle_t **pamh)
{
struct pam_handle *handle;
handle = calloc(1, sizeof(struct pam_handle));
if (handle == NULL)
return PAM_BUF_ERR;
handle->service = service_name;
handle->user = user;
handle->conversation = pam_conversation;
*pamh = handle;
return PAM_SUCCESS;
}
/*
* Free the pam_handle_t data structure and related resources. This is
* important to test the data cleanups. Freeing the memory is not strictly
* required since it's only used for testing, but it helps keep our memory
* usage clean so that we can run the test suite under valgrind.
*/
int
pam_end(pam_handle_t *pamh, int status)
{
struct fakepam_data *item, *next;
size_t i;
if (pamh->environ != NULL) {
for (i = 0; pamh->environ[i] != NULL; i++)
free(pamh->environ[i]);
free(pamh->environ);
}
free(pamh->authtok);
free(pamh->oldauthtok);
free(pamh->rhost);
free(pamh->ruser);
free(pamh->tty);
for (item = pamh->data; item != NULL;) {
if (item->cleanup != NULL)
item->cleanup(pamh, item->data, status);
free(item->name);
next = item->next;
free(item);
item = next;
}
free(pamh);
return PAM_SUCCESS;
}
/*
* Interface specific to this fake PAM library to set the struct passwd that's
* returned by getpwnam queries if the name matches.
*/
void
pam_set_pwd(struct passwd *pwd)
{
pwd_info = pwd;
}
/*
* For testing purposes, we want to be able to intercept getpwnam. This is
* fairly easy on platforms that have pam_modutil_getpwnam, since then our
* code will always call that function and we can provide an implementation
* that does whatever we want. For platforms that don't have that function,
* we'll try to intercept the C library getpwnam function.
*
* We store only one struct passwd data structure statically. If the user
* we're looking up matches that, we return it; otherwise, we return NULL.
*/
#ifdef HAVE_PAM_MODUTIL_GETPWNAM
struct passwd *
pam_modutil_getpwnam(pam_handle_t *pamh UNUSED, const char *name)
{
if (pwd_info != NULL && strcmp(pwd_info->pw_name, name) == 0)
return pwd_info;
else {
errno = 0;
return NULL;
}
}
#else
struct passwd *
getpwnam(const char *name)
{
if (pwd_info != NULL && strcmp(pwd_info->pw_name, name) == 0)
return pwd_info;
else {
errno = 0;
return NULL;
}
}
#endif