summaryrefslogtreecommitdiff
path: root/third_party
diff options
context:
space:
mode:
authorAndreas Schneider <asn@cryptomilk.org>2021-10-28 10:50:30 +0200
committerJeremy Allison <jra@samba.org>2021-10-28 19:03:04 +0000
commit7f6f4777b4081dbfcd875bf6dcbbab03a1fa413d (patch)
treea1dfb4409718f63cad80e674a096a0fc8aa5e650 /third_party
parent6ed71ad7e6aa98a34cfde95d7d62c46694d58469 (diff)
downloadsamba-7f6f4777b4081dbfcd875bf6dcbbab03a1fa413d.tar.gz
third_party: Update pam_wrapper to version 1.1.4
Signed-off-by: Andreas Schneider <asn@cryptomilk.org> Reviewed-by: Jeremy Allison <jra@samba.org> Autobuild-User(master): Jeremy Allison <jra@samba.org> Autobuild-Date(master): Thu Oct 28 19:03:04 UTC 2021 on sn-devel-184
Diffstat (limited to 'third_party')
-rw-r--r--third_party/pam_wrapper/libpamtest.c19
-rw-r--r--third_party/pam_wrapper/libpamtest.h30
-rw-r--r--third_party/pam_wrapper/pam_wrapper.c142
-rw-r--r--third_party/pam_wrapper/python/pypamtest.c192
-rw-r--r--third_party/pam_wrapper/wscript7
5 files changed, 230 insertions, 160 deletions
diff --git a/third_party/pam_wrapper/libpamtest.c b/third_party/pam_wrapper/libpamtest.c
index 4474736d688..6033d5a5b7e 100644
--- a/third_party/pam_wrapper/libpamtest.c
+++ b/third_party/pam_wrapper/libpamtest.c
@@ -66,7 +66,8 @@ enum pamtest_err _pamtest_conv(const char *service,
pam_conv_fn conv_fn,
void *conv_userdata,
struct pam_testcase test_cases[],
- size_t num_test_cases)
+ size_t num_test_cases,
+ pam_handle_t *pam_handle)
{
int rv;
pam_handle_t *ph;
@@ -82,9 +83,13 @@ enum pamtest_err _pamtest_conv(const char *service,
return PAMTEST_ERR_INTERNAL;
}
- rv = pam_start(service, user, &conv, &ph);
- if (rv != PAM_SUCCESS) {
- return PAMTEST_ERR_START;
+ if (pam_handle == NULL) {
+ rv = pam_start(service, user, &conv, &ph);
+ if (rv != PAM_SUCCESS) {
+ return PAMTEST_ERR_START;
+ }
+ } else {
+ ph = pam_handle;
}
for (tcindex = 0; tcindex < num_test_cases; tcindex++) {
@@ -322,7 +327,8 @@ enum pamtest_err _pamtest(const char *service,
const char *user,
struct pamtest_conv_data *conv_data,
struct pam_testcase test_cases[],
- size_t num_test_cases)
+ size_t num_test_cases,
+ pam_handle_t *pam_handle)
{
struct pamtest_conv_ctx cctx = {
.data = conv_data,
@@ -332,5 +338,6 @@ enum pamtest_err _pamtest(const char *service,
pamtest_simple_conv,
&cctx,
test_cases,
- num_test_cases);
+ num_test_cases,
+ pam_handle);
}
diff --git a/third_party/pam_wrapper/libpamtest.h b/third_party/pam_wrapper/libpamtest.h
index 0307a2663af..4b4a50ecd56 100644
--- a/third_party/pam_wrapper/libpamtest.h
+++ b/third_party/pam_wrapper/libpamtest.h
@@ -19,6 +19,7 @@
#ifndef __LIBPAMTEST_H_
#define __LIBPAMTEST_H_
+#include <stddef.h>
#include <stdint.h>
#include <security/pam_appl.h>
@@ -128,12 +129,11 @@ struct pamtest_conv_data {
* an index internally.
*/
const char **in_echo_on;
-
- /** Captures messages through PAM_TEXT_INFO. The test caller is
+ /** Captures messages through PAM_ERROR_MSG. The test caller is
* responsible for allocating enough space in the array.
*/
char **out_err;
- /** Captures messages through PAM_ERROR_MSG. The test caller is
+ /** Captures messages through PAM_TEXT_INFO. The test caller is
* responsible for allocating enough space in the array.
*/
char **out_info;
@@ -156,6 +156,8 @@ struct pamtest_conv_data {
* @param[in] test_cases List of libpamtest test cases. Must end with
* PAMTEST_CASE_SENTINEL
*
+ * @param[in] pam_handle The PAM handle to use to run the tests
+ *
* @code
* int main(void) {
* int rc;
@@ -175,10 +177,11 @@ enum pamtest_err run_pamtest_conv(const char *service,
const char *user,
pam_conv_fn conv_fn,
void *conv_userdata,
- struct pam_testcase test_cases[]);
+ struct pam_testcase test_cases[],
+ pam_handle_t *pam_handle);
#else
-#define run_pamtest_conv(service, user, conv_fn, conv_data, test_cases) \
- _pamtest_conv(service, user, conv_fn, conv_data, test_cases, sizeof(test_cases)/sizeof(test_cases[0])
+#define run_pamtest_conv(service, user, conv_fn, conv_data, test_cases, pam_handle) \
+ _pamtest_conv(service, user, conv_fn, conv_data, test_cases, sizeof(test_cases)/sizeof(test_cases[0], pam_handle)
#endif
#ifdef DOXYGEN
@@ -196,6 +199,8 @@ enum pamtest_err run_pamtest_conv(const char *service,
* @param[in] test_cases List of libpamtest test cases. Must end with
* PAMTEST_CASE_SENTINEL
*
+ * @param[in] pam_handle The PAM handle to use to run the tests
+ *
* @code
* int main(void) {
* int rc;
@@ -214,10 +219,11 @@ enum pamtest_err run_pamtest_conv(const char *service,
enum pamtest_err run_pamtest(const char *service,
const char *user,
struct pamtest_conv_data *conv_data,
- struct pam_testcase test_cases[]);
+ struct pam_testcase test_cases[],
+ pam_handle_t *pam_handle);
#else
-#define run_pamtest(service, user, conv_data, test_cases) \
- _pamtest(service, user, conv_data, test_cases, sizeof(test_cases)/sizeof(test_cases[0]))
+#define run_pamtest(service, user, conv_data, test_cases, pam_handle) \
+ _pamtest(service, user, conv_data, test_cases, sizeof(test_cases)/sizeof(test_cases[0]), pam_handle)
#endif
#ifdef DOXYGEN
@@ -262,13 +268,15 @@ enum pamtest_err _pamtest_conv(const char *service,
pam_conv_fn conv_fn,
void *conv_userdata,
struct pam_testcase test_cases[],
- size_t num_test_cases);
+ size_t num_test_cases,
+ pam_handle_t *pam_handle);
enum pamtest_err _pamtest(const char *service,
const char *user,
struct pamtest_conv_data *conv_data,
struct pam_testcase test_cases[],
- size_t num_test_cases);
+ size_t num_test_cases,
+ pam_handle_t *pam_handle);
const struct pam_testcase *_pamtest_failed_case(struct pam_testcase test_cases[],
size_t num_test_cases);
diff --git a/third_party/pam_wrapper/pam_wrapper.c b/third_party/pam_wrapper/pam_wrapper.c
index dd69c43f021..da2c7381656 100644
--- a/third_party/pam_wrapper/pam_wrapper.c
+++ b/third_party/pam_wrapper/pam_wrapper.c
@@ -311,7 +311,14 @@ static struct pwrap pwrap;
*********************************************************/
bool pam_wrapper_enabled(void);
+#if ! defined(HAVE_CONSTRUCTOR_ATTRIBUTE) && defined(HAVE_PRAGMA_INIT)
+/* xlC and other oldschool compilers support (only) this */
+#pragma init (pwrap_constructor)
+#endif
void pwrap_constructor(void) CONSTRUCTOR_ATTRIBUTE;
+#if ! defined(HAVE_DESTRUCTOR_ATTRIBUTE) && defined(HAVE_PRAGMA_FINI)
+#pragma fini (pwrap_destructor)
+#endif
void pwrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
/*********************************************************
@@ -784,14 +791,20 @@ static void pwrap_clean_stale_dirs(const char *dir)
buf[sizeof(buf) - 1] = '\0';
tmp = strtol(buf, NULL, 10);
- if (tmp == 0 || tmp > 0xFFFF || errno == ERANGE) {
+ if (tmp == 0 || errno == ERANGE) {
PWRAP_LOG(PWRAP_LOG_ERROR,
"Failed to parse pid, buf=%s",
buf);
return;
}
- pid = (pid_t)(tmp & 0xFFFF);
+ pid = (pid_t)tmp;
+ /* Check if we are out of pid_t range on this system */
+ if ((long)pid != tmp) {
+ PWRAP_LOG(PWRAP_LOG_ERROR,
+ "pid out of range: %ld", tmp);
+ return;
+ }
rc = kill(pid, 0);
if (rc == -1) {
@@ -935,130 +948,6 @@ static void pwrap_init(void)
#else /* HAVE_PAM_START_CONFDIR */
-#ifdef HAVE_PAM_MODUTIL_SEARCH_KEY
-/*
- * This is needed to workaround Tumbleweed which packages a libpam git version.
- */
-static int pso_copy(const char *src, const char *dst, const char *pdir, mode_t mode)
-{
-#define PSO_COPY_READ_SIZE 16
- int srcfd = -1;
- int dstfd = -1;
- int rc = -1;
- ssize_t bread, bwritten;
- struct stat sb;
- char buf[PSO_COPY_READ_SIZE + 1];
- size_t pso_copy_read_size = PSO_COPY_READ_SIZE;
- int cmp;
- size_t to_read;
- bool found_slash;
-
- cmp = strcmp(src, dst);
- if (cmp == 0) {
- return -1;
- }
-
- srcfd = open(src, O_RDONLY, 0);
- if (srcfd < 0) {
- return -1;
- }
-
- if (mode == 0) {
- rc = fstat(srcfd, &sb);
- if (rc != 0) {
- rc = -1;
- goto out;
- }
- mode = sb.st_mode;
- }
-
- dstfd = open(dst, O_CREAT|O_WRONLY|O_TRUNC, mode);
- if (dstfd < 0) {
- rc = -1;
- goto out;
- }
-
- found_slash = false;
- to_read = 1;
-
- for (;;) {
- bread = read(srcfd, buf, to_read);
- if (bread == 0) {
- /* done */
- break;
- } else if (bread < 0) {
- errno = EIO;
- rc = -1;
- goto out;
- }
-
- to_read = 1;
- if (!found_slash && buf[0] == '/') {
- found_slash = true;
- to_read = pso_copy_read_size;
- }
-
- if (found_slash && bread == PSO_COPY_READ_SIZE) {
- cmp = memcmp(buf, "usr/etc/pam.d/%s", 16);
- if (cmp == 0) {
- char tmp[16] = {0};
-
- snprintf(tmp, sizeof(tmp), "%s/%%s", pdir + 1);
-
- memcpy(buf, tmp, 12);
- memset(&buf[12], '\0', 4);
-
- /*
- * If we found this string, we need to reduce
- * the read size to not miss, the next one.
- */
- pso_copy_read_size = 13;
- } else {
- cmp = memcmp(buf, "usr/etc/pam.d", 13);
- if (cmp == 0) {
- memcpy(buf, pdir + 1, 9);
- memset(&buf[9], '\0', 4);
- } else {
- cmp = memcmp(buf, "etc/pam.d", 9);
- if (cmp == 0) {
- memcpy(buf, pdir + 1, 9);
- }
- }
- }
- found_slash = false;
- }
-
- bwritten = write(dstfd, buf, bread);
- if (bwritten < 0) {
- errno = EIO;
- rc = -1;
- goto out;
- }
-
- if (bread != bwritten) {
- errno = EFAULT;
- rc = -1;
- goto out;
- }
- }
-
- rc = 0;
-out:
- if (srcfd != -1) {
- close(srcfd);
- }
- if (dstfd != -1) {
- close(dstfd);
- }
- if (rc < 0) {
- unlink(dst);
- }
-
- return rc;
-#undef PSO_COPY_READ_SIZE
-}
-#else /* HAVE_PAM_MODUTIL_SEARCH_KEY */
-
static int pso_copy(const char *src, const char *dst, const char *pdir, mode_t mode)
{
#define PSO_COPY_READ_SIZE 9
@@ -1154,7 +1043,6 @@ out:
return rc;
#undef PSO_COPY_READ_SIZE
}
-#endif /* HAVE_PAM_MODUTIL_SEARCH_KEY */
static void pwrap_init(void)
{
diff --git a/third_party/pam_wrapper/python/pypamtest.c b/third_party/pam_wrapper/python/pypamtest.c
index 8de05e9c39b..008a85fd778 100644
--- a/third_party/pam_wrapper/python/pypamtest.c
+++ b/third_party/pam_wrapper/python/pypamtest.c
@@ -58,8 +58,14 @@ typedef struct {
enum pamtest_ops pam_operation;
int expected_rv;
int flags;
+
+ PyObject *pam_handle;
+ PyObject *pam_env;
} TestCaseObject;
+#define PyTestCase_AsTestCaseObject(py_obj) \
+ (TestCaseObject *)(py_obj)
+
/**********************************************************
*** module-specific exceptions
**********************************************************/
@@ -461,6 +467,22 @@ static PyMemberDef pypamtest_test_case_members[] = {
discard_const_p(char, "Additional flags for the PAM operation"),
},
+ {
+ discard_const_p(char, "pam_handle"),
+ T_OBJECT_EX,
+ offsetof(TestCaseObject, pam_handle),
+ READONLY,
+ discard_const_p(char, "Pam handle"),
+ },
+
+ {
+ discard_const_p(char, "pam_env"),
+ T_OBJECT_EX,
+ offsetof(TestCaseObject, pam_env),
+ READONLY,
+ discard_const_p(char, "Pam env"),
+ },
+
{ NULL, 0, 0, 0, NULL } /* Sentinel */
};
@@ -773,6 +795,8 @@ static int py_testcase_to_cstruct(PyObject *py_test, struct pam_testcase *test)
int rc;
long value;
+ memset(test, 0, sizeof(struct pam_testcase));
+
rc = py_testcase_get(py_test, "pam_operation", &value);
if (rc != 0) {
return rc;
@@ -903,6 +927,84 @@ static int py_tc_list_to_cstruct_list(PyObject *py_test_list,
return 0;
}
+static int cstruct_to_py_testcase(PyObject *pytest, struct pam_testcase *ctest)
+{
+ TestCaseObject *t = PyTestCase_AsTestCaseObject(pytest);
+ size_t i;
+ int rc;
+
+ switch (t->pam_operation) {
+ case PAMTEST_GETENVLIST:
+ if (ctest->case_out.envlist == NULL) {
+ break;
+ }
+
+ t->pam_env = PyDict_New();
+ if (t->pam_env == NULL) {
+ return ENOMEM;
+ }
+ for (i = 0; ctest->case_out.envlist[i] != NULL; i++) {
+ char *key = NULL;
+ char *val = NULL;
+ key = strdup(ctest->case_out.envlist[i]);
+ if (key == NULL) {
+ return ENOMEM;
+ }
+ val = strrchr(key, '=');
+ if (val == NULL) {
+ PyErr_Format(PyExc_IOError,
+ "Failed to parse PAM environment "
+ "variable");
+ free(key);
+ return EINVAL;
+ }
+ *val = '\0';
+ rc = PyDict_SetItem(t->pam_env,
+ PyUnicode_FromString(key),
+ PyUnicode_FromString(val + 1));
+ free(key);
+ if (rc == -1) {
+ return rc;
+ }
+ }
+ break;
+ case PAMTEST_KEEPHANDLE:
+ t->pam_handle = PyCapsule_New(ctest->case_out.ph, NULL, NULL);
+ if (t->pam_handle == NULL) {
+ return ENOMEM;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int cstruct_list_to_py_tc_list(PyObject *py_test_list,
+ Py_ssize_t num_tests,
+ struct pam_testcase *test_list)
+{
+ Py_ssize_t i;
+ PyObject *py_test = NULL;
+ int rc;
+
+ for (i = 0; i < num_tests; i++) {
+ py_test = PySequence_GetItem(py_test_list, i);
+ if (py_test == NULL) {
+ return EIO;
+ }
+
+ rc = cstruct_to_py_testcase(py_test, &test_list[i]);
+ Py_DECREF(py_test);
+ if (rc != 0) {
+ return EIO;
+ }
+ }
+
+ return 0;
+}
+
PyDoc_STRVAR(RunPamTest__doc__,
"Run PAM tests\n\n"
"This function runs PAM test cases and reports result\n"
@@ -917,7 +1019,9 @@ PyDoc_STRVAR(RunPamTest__doc__,
"conversation for PAM_PROMPT_ECHO_ON input.\n"
);
-static PyObject *pypamtest_run_pamtest(PyObject *module, PyObject *args)
+static PyObject *pypamtest_run_pamtest(PyObject *module,
+ PyObject *args,
+ PyObject *kwargs)
{
int ok;
int rc;
@@ -926,21 +1030,33 @@ static PyObject *pypamtest_run_pamtest(PyObject *module, PyObject *args)
PyObject *py_test_list;
PyObject *py_echo_off = NULL;
PyObject *py_echo_on = NULL;
+ PyObject *py_pam_handle = NULL;
Py_ssize_t num_tests;
struct pam_testcase *test_list;
enum pamtest_err perr;
struct pamtest_conv_data conv_data;
+ pam_handle_t *pam_handle = NULL;
TestResultObject *result = NULL;
+ const char * const kwnames[] = { "username",
+ "service",
+ "tests",
+ "echo_off",
+ "echo_on",
+ "handle",
+ NULL };
(void) module; /* unused */
- ok = PyArg_ParseTuple(args,
- discard_const_p(char, "ssO|OO"),
- &username,
- &service,
- &py_test_list,
- &py_echo_off,
- &py_echo_on);
+ ok = PyArg_ParseTupleAndKeywords(args,
+ kwargs,
+ discard_const_p(char, "ssO|OOO"),
+ discard_const_p(char *, kwnames),
+ &username,
+ &service,
+ &py_test_list,
+ &py_echo_off,
+ &py_echo_on,
+ &py_pam_handle);
if (!ok) {
return NULL;
}
@@ -976,7 +1092,23 @@ static PyObject *pypamtest_run_pamtest(PyObject *module, PyObject *args)
return NULL;
}
- perr = _pamtest(service, username, &conv_data, test_list, num_tests);
+ if (py_pam_handle != NULL) {
+ pam_handle = (pam_handle_t *)PyCapsule_GetPointer(py_pam_handle,
+ NULL);
+ if (pam_handle == NULL) {
+ PyMem_Free(test_list);
+ PyErr_Format(PyExc_IOError,
+ "Failed to get the pam handle pointer");
+ return NULL;
+ }
+ }
+
+ perr = _pamtest(service,
+ username,
+ &conv_data,
+ test_list,
+ num_tests,
+ pam_handle);
if (perr != PAMTEST_ERR_OK) {
free_conv_data(&conv_data);
set_pypamtest_exception(PyExc_PamTestError,
@@ -986,6 +1118,18 @@ static PyObject *pypamtest_run_pamtest(PyObject *module, PyObject *args)
PyMem_Free(test_list);
return NULL;
}
+
+ rc = cstruct_list_to_py_tc_list(py_test_list, num_tests, test_list);
+ if (rc != 0) {
+ if (rc == ENOMEM) {
+ PyErr_NoMemory();
+ return NULL;
+ } else {
+ PyErr_Format(PyExc_IOError,
+ "Cannot convert C structure to python");
+ return NULL;
+ }
+ }
PyMem_Free(test_list);
result = construct_test_conv_result(conv_data.out_info,
@@ -1003,7 +1147,7 @@ static PyMethodDef pypamtest_module_methods[] = {
{
discard_const_p(char, "run_pamtest"),
(PyCFunction) pypamtest_run_pamtest,
- METH_VARARGS,
+ METH_VARARGS | METH_KEYWORDS,
RunPamTest__doc__,
},
@@ -1115,6 +1259,34 @@ PyMODINIT_FUNC initpypamtest(void)
RETURN_ON_ERROR;
}
+ ret = PyModule_AddIntConstant(m,
+ "PAMTEST_FLAG_DELETE_CRED",
+ PAM_DELETE_CRED);
+ if (ret == -1) {
+ RETURN_ON_ERROR;
+ }
+
+ ret = PyModule_AddIntConstant(m,
+ "PAMTEST_FLAG_ESTABLISH_CRED",
+ PAM_ESTABLISH_CRED);
+ if (ret == -1) {
+ RETURN_ON_ERROR;
+ }
+
+ ret = PyModule_AddIntConstant(m,
+ "PAMTEST_FLAG_REINITIALIZE_CRED",
+ PAM_REINITIALIZE_CRED);
+ if (ret == -1) {
+ RETURN_ON_ERROR;
+ }
+
+ ret = PyModule_AddIntConstant(m,
+ "PAMTEST_FLAG_REFRESH_CRED",
+ PAM_REFRESH_CRED);
+ if (ret == -1) {
+ RETURN_ON_ERROR;
+ }
+
pypam_object.type_obj = &pypamtest_test_case;
if (PyType_Ready(pypam_object.type_obj) < 0) {
RETURN_ON_ERROR;
diff --git a/third_party/pam_wrapper/wscript b/third_party/pam_wrapper/wscript
index fb57800587a..28d003d9fab 100644
--- a/third_party/pam_wrapper/wscript
+++ b/third_party/pam_wrapper/wscript
@@ -2,7 +2,7 @@
import os
-VERSION="1.1.2"
+VERSION="1.1.4"
def find_library(library_names, lookup_paths):
for directory in lookup_paths:
@@ -56,11 +56,6 @@ def configure(conf):
checklibc=False,
headers='security/pam_appl.h')
- conf.CHECK_FUNCS_IN('pam_modutil_search_key',
- 'pam',
- checklibc=False,
- headers='security/pam_modutil.h')
-
conf.CHECK_C_PROTOTYPE('pam_vprompt',
'int pam_vprompt(const pam_handle_t *_pamh, int _style, char **_resp, const char *_fmt, va_list _ap)',
define='HAVE_PAM_VPROMPT_CONST', headers='stdio.h sys/types.h security/pam_appl.h security/pam_modules.h')