Fix an off-by-one bug in pam_getenv() which was inadvertantly
introduced when pam_getenv() was (needlessly) rewritten as part of r913. Rewrite pam_getenv() again (but correctly, this time) to reduce the number of times we iterate over the same string. Add a few unit tests for pam_{get,put,set}env(), including one which would have caught the bug. Credit goes to Tim Creech <tcreech@tcreech.com> for discovering and reporting the bug. git-svn-id: svn+ssh://svn.openpam.org/svn/openpam/trunk@943 185d5e19-27fe-0310-9dcf-9bff6b9f3609
This commit is contained in:
parent
1dce53245b
commit
9bdf428c5a
6 changed files with 320 additions and 11 deletions
1
CREDITS
1
CREDITS
|
@ -49,5 +49,6 @@ ideas:
|
|||
Sebastian Krahmer <sebastian.krahmer@gmail.com>
|
||||
Solar Designer <solar@openwall.com>
|
||||
Takanori Saneto <sanewo@ba2.so-net.ne.jp>
|
||||
Tim Creech <tcreech@tcreech.com>
|
||||
Wojciech A. Koszek <wkoszek@freebsd.org>
|
||||
Yar Tikhiy <yar@freebsd.org>
|
||||
|
|
|
@ -58,19 +58,20 @@ const char *
|
|||
pam_getenv(pam_handle_t *pamh,
|
||||
const char *name)
|
||||
{
|
||||
char *str;
|
||||
size_t len;
|
||||
int i;
|
||||
|
||||
ENTERS(name);
|
||||
if (strchr(name, '=') != NULL) {
|
||||
errno = EINVAL;
|
||||
RETURNS(NULL);
|
||||
for (len = 0; name[len] != '\0'; ++len) {
|
||||
if (name[len] == '=') {
|
||||
errno = EINVAL;
|
||||
RETURNS(NULL);
|
||||
}
|
||||
}
|
||||
if ((i = openpam_findenv(pamh, name, strlen(name))) < 0)
|
||||
if ((i = openpam_findenv(pamh, name, len)) < 0)
|
||||
RETURNS(NULL);
|
||||
if ((str = strchr(pamh->env[i], '=')) == NULL)
|
||||
RETURNS("");
|
||||
RETURNS(str);
|
||||
/* assert(pamh->env[i][len] == '='); */
|
||||
RETURNS(pamh->env[i] + len + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -8,19 +8,19 @@ AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/lib/libpam \
|
|||
AM_TESTS_ENVIRONMENT = \
|
||||
PAM_RETURN_SO=$(abs_top_builddir)/modules/pam_return/.libs/pam_return.so
|
||||
|
||||
noinst_HEADERS = t_pam_conv.h
|
||||
|
||||
# tests
|
||||
TESTS =
|
||||
TESTS += t_openpam_ctype
|
||||
TESTS += t_openpam_dispatch
|
||||
TESTS += t_openpam_readword
|
||||
TESTS += t_openpam_readlinev
|
||||
TESTS += t_pam_env
|
||||
check_PROGRAMS = $(TESTS)
|
||||
|
||||
# libt - common support code
|
||||
check_LIBRARIES = libt.a
|
||||
libt_a_SOURCES = t_pam_conv.c
|
||||
libt_a_SOURCES = t_pam_conv.c t_pam_err.c
|
||||
noinst_HEADERS = t_pam_conv.h t_pam_err.h
|
||||
|
||||
# link with libpam and test framework
|
||||
LDADD = $(CRYB_TEST_LIBS) libt.a
|
||||
|
|
200
t/t_pam_env.c
Normal file
200
t/t_pam_env.c
Normal file
|
@ -0,0 +1,200 @@
|
|||
/*-
|
||||
* Copyright (c) 2018 Dag-Erling Smørgrav
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $OpenPAM$
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cryb/test.h>
|
||||
|
||||
#include <security/pam_appl.h>
|
||||
#include <security/openpam.h>
|
||||
|
||||
#include "t_pam_err.h"
|
||||
|
||||
#define T_ENV_NAME "MAGIC_WORDS"
|
||||
#define T_ENV_VALUE "SQUEAMISH OSSIFRAGE"
|
||||
#define T_ENV_NAMEVALUE T_ENV_NAME "=" T_ENV_VALUE
|
||||
|
||||
struct pam_conv t_null_pamc;
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* Tests
|
||||
*/
|
||||
|
||||
static int
|
||||
t_env_empty(char **desc CRYB_UNUSED, void *arg CRYB_UNUSED)
|
||||
{
|
||||
pam_handle_t *pamh;
|
||||
char **envlist;
|
||||
int pam_err, ret;
|
||||
|
||||
ret = 1;
|
||||
pam_err = pam_start("t_pam_env", "test", &t_null_pamc, &pamh);
|
||||
t_assert(pam_err == PAM_SUCCESS);
|
||||
envlist = pam_getenvlist(pamh);
|
||||
ret &= t_is_not_null(envlist);
|
||||
if (envlist != NULL) {
|
||||
ret &= t_is_null(*envlist);
|
||||
openpam_free_envlist(envlist);
|
||||
}
|
||||
pam_end(pamh, pam_err);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
t_putenv_simple(char **desc CRYB_UNUSED, void *arg CRYB_UNUSED)
|
||||
{
|
||||
pam_handle_t *pamh;
|
||||
char **envlist;
|
||||
int pam_err, ret;
|
||||
|
||||
ret = 1;
|
||||
pam_err = pam_start("t_pam_env", "test", &t_null_pamc, &pamh);
|
||||
t_assert(pam_err == PAM_SUCCESS);
|
||||
pam_err = pam_putenv(pamh, T_ENV_NAMEVALUE);
|
||||
ret &= t_compare_pam_err(PAM_SUCCESS, pam_err);
|
||||
envlist = pam_getenvlist(pamh);
|
||||
ret &= t_is_not_null(envlist);
|
||||
if (envlist != NULL) {
|
||||
ret &= t_compare_str(T_ENV_NAMEVALUE, envlist[0])
|
||||
& t_is_null(envlist[1]);
|
||||
openpam_free_envlist(envlist);
|
||||
}
|
||||
pam_end(pamh, pam_err);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
t_setenv_simple(char **desc CRYB_UNUSED, void *arg CRYB_UNUSED)
|
||||
{
|
||||
pam_handle_t *pamh;
|
||||
char **envlist;
|
||||
int pam_err, ret;
|
||||
|
||||
ret = 1;
|
||||
pam_err = pam_start("t_pam_env", "test", &t_null_pamc, &pamh);
|
||||
t_assert(pam_err == PAM_SUCCESS);
|
||||
pam_err = pam_setenv(pamh, T_ENV_NAME, T_ENV_VALUE, 0);
|
||||
ret &= t_compare_pam_err(PAM_SUCCESS, pam_err);
|
||||
envlist = pam_getenvlist(pamh);
|
||||
ret &= t_is_not_null(envlist);
|
||||
if (envlist != NULL) {
|
||||
ret &= t_compare_str(T_ENV_NAMEVALUE, envlist[0])
|
||||
& t_is_null(envlist[1]);
|
||||
openpam_free_envlist(envlist);
|
||||
}
|
||||
pam_end(pamh, pam_err);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
t_getenv_empty(char **desc CRYB_UNUSED, void *arg CRYB_UNUSED)
|
||||
{
|
||||
pam_handle_t *pamh;
|
||||
const char *value;
|
||||
int pam_err, ret;
|
||||
|
||||
ret = 1;
|
||||
pam_err = pam_start("t_pam_env", "test", &t_null_pamc, &pamh);
|
||||
t_assert(pam_err == PAM_SUCCESS);
|
||||
value = pam_getenv(pamh, T_ENV_NAME);
|
||||
ret &= t_compare_str(NULL, value);
|
||||
pam_end(pamh, pam_err);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
t_getenv_simple_miss(char **desc CRYB_UNUSED, void *arg CRYB_UNUSED)
|
||||
{
|
||||
pam_handle_t *pamh;
|
||||
const char *value;
|
||||
int pam_err, ret;
|
||||
|
||||
ret = 1;
|
||||
pam_err = pam_start("t_pam_env", "test", &t_null_pamc, &pamh);
|
||||
t_assert(pam_err == PAM_SUCCESS);
|
||||
pam_err = pam_setenv(pamh, T_ENV_NAME, T_ENV_VALUE, 0);
|
||||
t_assert(pam_err == PAM_SUCCESS);
|
||||
value = pam_getenv(pamh, "XYZZY");
|
||||
ret &= t_compare_str(NULL, value);
|
||||
pam_end(pamh, pam_err);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
t_getenv_simple_hit(char **desc CRYB_UNUSED, void *arg CRYB_UNUSED)
|
||||
{
|
||||
pam_handle_t *pamh;
|
||||
const char *value;
|
||||
int pam_err, ret;
|
||||
|
||||
ret = 1;
|
||||
pam_err = pam_start("t_pam_env", "test", &t_null_pamc, &pamh);
|
||||
t_assert(pam_err == PAM_SUCCESS);
|
||||
pam_err = pam_setenv(pamh, T_ENV_NAME, T_ENV_VALUE, 0);
|
||||
t_assert(pam_err == PAM_SUCCESS);
|
||||
value = pam_getenv(pamh, T_ENV_NAME);
|
||||
ret &= t_compare_str(T_ENV_VALUE, value);
|
||||
pam_end(pamh, pam_err);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* Boilerplate
|
||||
*/
|
||||
|
||||
static int
|
||||
t_prepare(int argc CRYB_UNUSED, char *argv[] CRYB_UNUSED)
|
||||
{
|
||||
|
||||
t_add_test(t_env_empty, NULL, "initially empty");
|
||||
t_add_test(t_putenv_simple, NULL, "put - simple");
|
||||
t_add_test(t_setenv_simple, NULL, "set - simple");
|
||||
t_add_test(t_getenv_empty, NULL, "get - empty");
|
||||
t_add_test(t_getenv_simple_miss, NULL, "get - simple (miss)");
|
||||
t_add_test(t_getenv_simple_hit, NULL, "get - simple (hit)");
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
t_main(t_prepare, NULL, argc, argv);
|
||||
}
|
63
t/t_pam_err.c
Normal file
63
t/t_pam_err.c
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*-
|
||||
* Copyright (c) 2018 Dag-Erling Smørgrav
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $OpenPAM$
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cryb/test.h>
|
||||
|
||||
#include <security/pam_appl.h>
|
||||
#include <security/openpam.h>
|
||||
|
||||
#include "openpam_impl.h"
|
||||
|
||||
#include "t_pam_err.h"
|
||||
|
||||
int
|
||||
t_compare_pam_err(int expected, int received)
|
||||
{
|
||||
|
||||
if (expected == received)
|
||||
return (1);
|
||||
if (expected >= 0 && expected < PAM_NUM_ERRORS)
|
||||
t_printv("expected %s, ", pam_err_name[expected]);
|
||||
else
|
||||
t_printv("expected %d, ", expected);
|
||||
if (received >= 0 && received < PAM_NUM_ERRORS)
|
||||
t_printv("received %s\n", pam_err_name[received]);
|
||||
else
|
||||
t_printv("received %d\n", received);
|
||||
return (0);
|
||||
}
|
44
t/t_pam_err.h
Normal file
44
t/t_pam_err.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*-
|
||||
* Copyright (c) 2018 Dag-Erling Smørgrav
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $OpenPAM$
|
||||
*/
|
||||
|
||||
#ifndef T_PAM_ERR_H_INCLUDED
|
||||
#define T_PAM_ERR_H_INCLUDED
|
||||
|
||||
int t_compare_pam_err(int, int);
|
||||
|
||||
static inline int
|
||||
t_pam_success(int received)
|
||||
{
|
||||
|
||||
return t_compare_pam_err(PAM_SUCCESS, received);
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue