diff options
author | Bastien Nocera <hadess@hadess.net> | 2020-01-22 12:17:03 +0100 |
---|---|---|
committer | Andreas Schneider <asn@samba.org> | 2020-03-19 12:43:28 +0100 |
commit | 6a12a712bf7b7b8be33d0410c5ddd48713580012 (patch) | |
tree | 5191d34fbe27023771aec683c5ffcef7553e2022 | |
parent | c24b23c628079c7d64386270968209339d29b78c (diff) | |
download | pam_wrapper-6a12a712bf7b7b8be33d0410c5ddd48713580012.tar.gz pam_wrapper-6a12a712bf7b7b8be33d0410c5ddd48713580012.tar.xz pam_wrapper-6a12a712bf7b7b8be33d0410c5ddd48713580012.zip |
modules: Add pam_chatty module
Add a simple PAM module that will output "num_lines" lines of PAM info
and/or error output.
Signed-off-by: Bastien Nocera <hadess@hadess.net>
Reviewed-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
-rw-r--r-- | src/modules/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/modules/pam_chatty.c | 163 |
2 files changed, 164 insertions, 1 deletions
diff --git a/src/modules/CMakeLists.txt b/src/modules/CMakeLists.txt index e7b2604..93bb7d2 100644 --- a/src/modules/CMakeLists.txt +++ b/src/modules/CMakeLists.txt @@ -1,6 +1,6 @@ project(pam_wrapper-modules C) -set(PAM_MODULES pam_matrix pam_get_items pam_set_items) +set(PAM_MODULES pam_matrix pam_get_items pam_set_items pam_chatty) set(PAM_LIBRARIES pam) if (HAVE_PAM_MISC) diff --git a/src/modules/pam_chatty.c b/src/modules/pam_chatty.c new file mode 100644 index 0000000..ba9f65c --- /dev/null +++ b/src/modules/pam_chatty.c @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2015 Andreas Schneider <asn@samba.org> + * Copyright (c) 2015 Jakub Hrozek <jakub.hrozek@posteo.se> + * Copyright (c) 2020 Bastien Nocera <hadess@hadess.net> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "config.h" + +#include <sys/param.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include <pwd.h> +#include <stdlib.h> +#include <stdio.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> +#include <ctype.h> +#include <errno.h> +#include <time.h> +#include <stdint.h> + +#ifndef discard_const +#define discard_const(ptr) ((void *)((uintptr_t)(ptr))) +#endif + +#ifndef discard_const_p +#define discard_const_p(type, ptr) ((type *)discard_const(ptr)) +#endif + +#ifdef HAVE_SECURITY_PAM_APPL_H +#include <security/pam_appl.h> +#endif +#ifdef HAVE_SECURITY_PAM_MODULES_H +#include <security/pam_modules.h> +#endif +#ifdef HAVE_SECURITY_PAM_EXT_H +#include <security/pam_ext.h> +#endif + +#include "pwrap_compat.h" + +#define ERROR_KEY "error" +#define INFO_KEY "info" +#define NUM_LINES_KEY "num_lines=" + +#define DEFAULT_NUM_LINES 3 + +/* We only return up to 16 messages from the PAM conversation. + * Value from src/python/pypamtest.c */ +#define PAM_CONV_MSG_MAX 16 + +#define PAM_CHATTY_FLG_ERROR (1 << 0) +#define PAM_CHATTY_FLG_INFO (1 << 1) + +static int pam_chatty_conv(pam_handle_t *pamh, + const int msg_style, + const char *msg) +{ + int ret; + const struct pam_conv *conv = NULL; + const struct pam_message *mesg[1]; + struct pam_response *r = NULL; + struct pam_message *pam_msg = NULL; + + ret = pam_get_item(pamh, PAM_CONV, (const void **) &conv); + if (ret != PAM_SUCCESS) { + return ret; + } + + pam_msg = calloc(sizeof(struct pam_message), 1); + if (pam_msg == NULL) { + return PAM_BUF_ERR; + } + + pam_msg->msg_style = msg_style; + pam_msg->msg = discard_const_p(char, msg); + + mesg[0] = (const struct pam_message *) pam_msg; + ret = conv->conv(1, mesg, &r, conv->appdata_ptr); + free(pam_msg); + + return ret; +} + +/* Evaluate command line arguments and store info about them in the + * pam_matrix context + */ +static uint32_t parse_args(int argc, + const char *argv[], + unsigned int *num_lines) +{ + uint32_t flags = 0; + + *num_lines = DEFAULT_NUM_LINES; + + for (; argc-- > 0; ++argv) { + if (strncmp(*argv, NUM_LINES_KEY, strlen(NUM_LINES_KEY)) == 0) { + if (*(*argv+strlen(NUM_LINES_KEY)) != '\0') { + *num_lines = atoi(*argv+strlen(NUM_LINES_KEY)); + if (*num_lines <= DEFAULT_NUM_LINES) + *num_lines = DEFAULT_NUM_LINES; + if (*num_lines > PAM_CONV_MSG_MAX) + *num_lines = PAM_CONV_MSG_MAX; + } + } else if (strncmp(*argv, ERROR_KEY, + strlen(ERROR_KEY)) == 0) { + flags |= PAM_CHATTY_FLG_ERROR; + } else if (strncmp(*argv, INFO_KEY, + strlen(INFO_KEY)) == 0) { + flags |= PAM_CHATTY_FLG_INFO; + } + } + + return flags; +} + +PAM_EXTERN int +pam_sm_authenticate(pam_handle_t *pamh, int flags, + int argc, const char *argv[]) +{ + uint32_t optflags; + unsigned int num_lines; + + (void) flags; /* unused */ + + optflags = parse_args (argc, argv, &num_lines); + if (optflags & PAM_CHATTY_FLG_INFO) { + unsigned int i; + + for (i = 0; i < num_lines; i++) { + pam_chatty_conv(pamh, + PAM_TEXT_INFO, + "Authentication succeeded"); + } + } + + if (optflags & PAM_CHATTY_FLG_ERROR) { + unsigned int i; + + for (i = 0; i < num_lines; i++) { + pam_chatty_conv(pamh, + PAM_ERROR_MSG, + "Authentication generated an error"); + } + } + + return PAM_SUCCESS; +} |