aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Hrozek <jakub.hrozek@posteo.se>2015-09-29 14:01:13 +0200
committerJakub Hrozek <jhrozek@redhat.com>2015-09-29 14:31:49 +0200
commitdfd164d2b43e5912f8a65569c6ab6b0d82ce3220 (patch)
treefbe57bca068ad74d01952b2ace14f2e4a67d2ce3
parente412f1c592703ad43e2516e38827a75da89a42ab (diff)
downloadpam_wrapper-dfd164d2b43e5912f8a65569c6ab6b0d82ce3220.tar.gz
pam_wrapper-dfd164d2b43e5912f8a65569c6ab6b0d82ce3220.tar.xz
pam_wrapper-dfd164d2b43e5912f8a65569c6ab6b0d82ce3220.zip
pwrap: Wrap prompting functions
-rw-r--r--src/pam_wrapper.c57
-rw-r--r--tests/test_pam_wrapper.c100
2 files changed, 157 insertions, 0 deletions
diff --git a/src/pam_wrapper.c b/src/pam_wrapper.c
index 87b49d5..141253d 100644
--- a/src/pam_wrapper.c
+++ b/src/pam_wrapper.c
@@ -38,6 +38,7 @@
#include <security/pam_appl.h>
#endif
#include <security/pam_modules.h>
+#include <security/pam_ext.h>
#ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
# define PWRAP_THREAD __thread
@@ -211,6 +212,12 @@ typedef int (*__libpam_pam_set_data)(pam_handle_t *pamh,
void *data,
int error_status));
+typedef int (*__libpam_pam_vprompt)(pam_handle_t *pamh,
+ int style,
+ char **response,
+ const char *fmt,
+ va_list args);
+
#define PWRAP_SYMBOL_ENTRY(i) \
union { \
__libpam_##i f; \
@@ -233,6 +240,7 @@ struct pwrap_libpam_symbols {
PWRAP_SYMBOL_ENTRY(pam_set_item);
PWRAP_SYMBOL_ENTRY(pam_get_data);
PWRAP_SYMBOL_ENTRY(pam_set_data);
+ PWRAP_SYMBOL_ENTRY(pam_vprompt);
};
struct pwrap {
@@ -460,6 +468,21 @@ static int libpam_pam_set_data(pam_handle_t *pamh,
cleanup);
}
+static int libpam_pam_vprompt(pam_handle_t *pamh,
+ int style,
+ char **response,
+ const char *fmt,
+ va_list args)
+{
+ pwrap_bind_symbol_libpam(pam_vprompt);
+
+ return pwrap.libpam.symbols._libpam_pam_vprompt.f(pamh,
+ style,
+ response,
+ fmt,
+ args);
+}
+
/*********************************************************
* PWRAP INIT
*********************************************************/
@@ -952,6 +975,40 @@ int pam_set_data(pam_handle_t *pamh,
return pwrap_pam_set_data(pamh, module_data_name, data, cleanup);
}
+static int pwrap_pam_vprompt(pam_handle_t *pamh,
+ int style,
+ char **response,
+ const char *fmt,
+ va_list args)
+{
+ PWRAP_LOG(PWRAP_LOG_TRACE, "pwrap_pam_vprompt called");
+ return libpam_pam_vprompt(pamh, style, response, fmt, args);
+}
+
+int pam_vprompt(pam_handle_t *pamh,
+ int style,
+ char **response,
+ const char *fmt,
+ va_list args)
+{
+ return pwrap_pam_vprompt(pamh, style, response, fmt, args);
+}
+
+int pam_prompt(pam_handle_t *pamh,
+ int style,
+ char **response,
+ const char *fmt, ...)
+{
+ va_list args;
+ int rv;
+
+ va_start(args, fmt);
+ rv = pwrap_pam_vprompt(pamh, style, response, fmt, args);
+ va_end(args);
+
+ return rv;
+}
+
/****************************
* DESTRUCTOR
***************************/
diff --git a/tests/test_pam_wrapper.c b/tests/test_pam_wrapper.c
index e83f5c5..5e68c13 100644
--- a/tests/test_pam_wrapper.c
+++ b/tests/test_pam_wrapper.c
@@ -11,6 +11,7 @@
#include <errno.h>
#include <unistd.h>
#include <security/pam_appl.h>
+#include <security/pam_ext.h>
struct pwrap_test_ctx {
struct pam_conv conv;
@@ -432,6 +433,102 @@ static void test_pam_item_functions(void **state)
assert_int_equal(rv, PAM_BAD_ITEM);
}
+static int add_to_reply(struct pam_response *res,
+ const char *s1,
+ const char *s2)
+{
+ size_t res_len;
+ int rv;
+
+ res_len = strlen(s1) + strlen(s2) + 1;
+
+ res->resp = calloc(res_len, sizeof(char));
+ if (res->resp == NULL) {
+ return ENOMEM;
+ }
+
+ rv = snprintf(res->resp, res_len, "%s%s", s1, s2);
+ if (rv < 0) {
+ return EIO;
+ }
+
+ return 0;
+}
+
+static int pwrap_echo_conv(int num_msg,
+ const struct pam_message **msgm,
+ struct pam_response **response,
+ void *appdata_ptr)
+{
+ int i;
+ struct pam_response *reply;
+ int *resp_array = appdata_ptr;
+
+ reply = (struct pam_response *) calloc(num_msg, sizeof(struct pam_response));
+ if (reply == NULL) {
+ return PAM_CONV_ERR;
+ }
+
+ for (i=0; i < num_msg; i++) {
+ switch (msgm[i]->msg_style) {
+ case PAM_PROMPT_ECHO_OFF:
+ add_to_reply(&reply[i], "echo off: ", msgm[i]->msg);
+ break;
+ case PAM_PROMPT_ECHO_ON:
+ add_to_reply(&reply[i], "echo on: ", msgm[i]->msg);
+ break;
+ case PAM_TEXT_INFO:
+ resp_array[0] = 1;
+ break;
+ case PAM_ERROR_MSG:
+ resp_array[1] = 1;
+ break;
+ default:
+ break;
+ }
+ }
+
+ *response = reply;
+ return PAM_SUCCESS;
+}
+
+static void test_pam_prompt(void **state)
+{
+ struct pwrap_test_ctx *test_ctx;
+ int rv;
+ char *response;
+ int resp_array[2];
+
+ test_ctx = (struct pwrap_test_ctx *) *state;
+
+ memset(resp_array, 0, sizeof(resp_array));
+
+ test_ctx->conv.conv = pwrap_echo_conv;
+ test_ctx->conv.appdata_ptr = resp_array;
+
+ rv = pam_start("pwrap_pam", "testuser",
+ &test_ctx->conv, &test_ctx->ph);
+ assert_int_equal(rv, PAM_SUCCESS);
+
+ rv = pam_prompt(test_ctx->ph, PAM_PROMPT_ECHO_OFF, &response, "no echo");
+ assert_int_equal(rv, PAM_SUCCESS);
+ assert_string_equal(response, "echo off: no echo");
+ free(response);
+
+ rv = pam_prompt(test_ctx->ph, PAM_PROMPT_ECHO_ON, &response, "echo");
+ assert_int_equal(rv, PAM_SUCCESS);
+ assert_string_equal(response, "echo on: echo");
+ free(response);
+
+ assert_int_equal(resp_array[0], 0);
+ pam_info(test_ctx->ph, "info");
+ assert_int_equal(resp_array[0], 1);
+
+ assert_int_equal(resp_array[1], 0);
+ pam_error(test_ctx->ph, "error");
+ assert_int_equal(resp_array[1], 1);
+}
+
int main(void) {
int rc;
@@ -469,6 +566,9 @@ int main(void) {
cmocka_unit_test_setup_teardown(test_pam_item_functions,
setup_noconv,
teardown),
+ cmocka_unit_test_setup_teardown(test_pam_prompt,
+ setup_ctx_only,
+ teardown),
};
rc = cmocka_run_group_tests(init_tests, NULL, NULL);