summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authormarkm <markm@FreeBSD.org>2001-07-09 18:14:43 +0000
committermarkm <markm@FreeBSD.org>2001-07-09 18:14:43 +0000
commit1b8cb1cd38833815186cfb8cb20c2f5628992d82 (patch)
tree4be47053e4fbe71b772b0186a5f90e96b81162bc /lib
parent5df25064461f5ca22954749947b42936989a0dcb (diff)
downloadFreeBSD-src-1b8cb1cd38833815186cfb8cb20c2f5628992d82.zip
FreeBSD-src-1b8cb1cd38833815186cfb8cb20c2f5628992d82.tar.gz
Almost completely rewrite the PAM module options processing
routines, and provide a more extended API for doing this. Provide an API for debug logging. Audit and clean up the code.
Diffstat (limited to 'lib')
-rw-r--r--lib/libpam/libpam/Makefile2
-rw-r--r--lib/libpam/libpam/pam_debug_log.c96
-rw-r--r--lib/libpam/libpam/pam_get_pass.c43
-rw-r--r--lib/libpam/libpam/pam_mod_misc.h50
-rw-r--r--lib/libpam/libpam/pam_prompt.c13
-rw-r--r--lib/libpam/libpam/pam_std_option.c162
-rw-r--r--lib/libpam/libpam/security/pam_mod_misc.h50
7 files changed, 334 insertions, 82 deletions
diff --git a/lib/libpam/libpam/Makefile b/lib/libpam/libpam/Makefile
index 49186d3..ee3e5ce 100644
--- a/lib/libpam/libpam/Makefile
+++ b/lib/libpam/libpam/Makefile
@@ -61,7 +61,7 @@ SRCS+= help_env.c misc_conv.c xstrdup.c
HDRS2= pam_misc.h
# Files from ${.CURDIR}:
-SRCS+= pam_get_pass.c pam_prompt.c pam_std_option.c
+SRCS+= pam_get_pass.c pam_prompt.c pam_std_option.c pam_debug_log.c
HDRS3= pam_mod_misc.h
# Static PAM modules:
diff --git a/lib/libpam/libpam/pam_debug_log.c b/lib/libpam/libpam/pam_debug_log.c
new file mode 100644
index 0000000..0e39a2d
--- /dev/null
+++ b/lib/libpam/libpam/pam_debug_log.c
@@ -0,0 +1,96 @@
+/*-
+ * Copyright 2001 Mark R V Murray
+ * 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.
+ *
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#include <security/pam_modules.h>
+#include <libgen.h>
+#include <stdarg.h>
+#include <string.h>
+#include <syslog.h>
+
+#include "pam_mod_misc.h"
+
+#define FMTBUFSIZ 256
+
+/* Log a debug message, including the function name and a
+ * cleaned up filename.
+ */
+void
+_pam_log(struct options *options, const char *file, const char *function,
+ const char *format, ...)
+{
+ va_list ap;
+ char *period;
+ char fmtbuf[FMTBUFSIZ];
+
+ if (pam_test_option(options, PAM_OPT_DEBUG, NULL)) {
+ strncpy(fmtbuf, basename(file), FMTBUFSIZ);
+ period = strchr(fmtbuf, '.');
+ if (period != NULL)
+ *period = '\0';
+ strncat(fmtbuf, ": ", FMTBUFSIZ);
+ strncat(fmtbuf, function, FMTBUFSIZ);
+ strncat(fmtbuf, ": ", FMTBUFSIZ);
+ strncat(fmtbuf, format, FMTBUFSIZ);
+ va_start(ap, format);
+ vsyslog(LOG_DEBUG, fmtbuf, ap);
+ va_end(ap);
+ }
+}
+
+/* Log a return value, including the function name and a
+ * cleaned up filename.
+ */
+void
+_pam_log_retval(struct options *options, const char *file, const char *function,
+ int retval)
+{
+ char *period;
+ char fmtbuf[FMTBUFSIZ];
+
+ if (pam_test_option(options, PAM_OPT_DEBUG, NULL)) {
+ strncpy(fmtbuf, basename(file), FMTBUFSIZ);
+ period = strchr(fmtbuf, '.');
+ if (period != NULL)
+ *period = '\0';
+ strncat(fmtbuf, ": ", FMTBUFSIZ);
+ strncat(fmtbuf, function, FMTBUFSIZ);
+ switch (retval) {
+ case PAM_SUCCESS:
+ strncat(fmtbuf, ": returning PAM_SUCCESS", FMTBUFSIZ);
+ syslog(LOG_DEBUG, fmtbuf);
+ break;
+ case PAM_AUTH_ERR:
+ strncat(fmtbuf, ": returning PAM_AUTH_ERR", FMTBUFSIZ);
+ syslog(LOG_DEBUG, fmtbuf);
+ break;
+ default:
+ strncat(fmtbuf, ": returning %d", FMTBUFSIZ);
+ syslog(LOG_DEBUG, fmtbuf, retval);
+ }
+ }
+}
diff --git a/lib/libpam/libpam/pam_get_pass.c b/lib/libpam/libpam/pam_get_pass.c
index 78ef75a..ba55b28 100644
--- a/lib/libpam/libpam/pam_get_pass.c
+++ b/lib/libpam/libpam/pam_get_pass.c
@@ -26,34 +26,35 @@
* $FreeBSD$
*/
+#include <stdlib.h>
#include <security/pam_modules.h>
#include "pam_mod_misc.h"
-static int pam_conv_pass(pam_handle_t *, const char *, int);
+static int pam_conv_pass(pam_handle_t *, const char *, struct options *);
static int
-pam_conv_pass(pam_handle_t *pamh, const char *prompt, int options)
+pam_conv_pass(pam_handle_t *pamh, const char *prompt, struct options *options)
{
- int retval;
- const void *item;
const struct pam_conv *conv;
struct pam_message msg;
const struct pam_message *msgs[1];
struct pam_response *resp;
+ const void *item;
+ int retval;
- if ((retval = pam_get_item(pamh, PAM_CONV, &item)) !=
- PAM_SUCCESS)
+ retval = pam_get_item(pamh, PAM_CONV, &item);
+ if (retval != PAM_SUCCESS)
return retval;
conv = (const struct pam_conv *)item;
- msg.msg_style = options & PAM_OPT_ECHO_PASS ?
+ msg.msg_style = pam_test_option(options, PAM_OPT_ECHO_PASS, NULL) ?
PAM_PROMPT_ECHO_ON : PAM_PROMPT_ECHO_OFF;
msg.msg = prompt;
msgs[0] = &msg;
- if ((retval = conv->conv(1, msgs, &resp, conv->appdata_ptr)) !=
- PAM_SUCCESS)
+ retval = conv->conv(1, msgs, &resp, conv->appdata_ptr);
+ if (retval != PAM_SUCCESS)
return retval;
- if ((retval = pam_set_item(pamh, PAM_AUTHTOK, resp[0].resp)) !=
- PAM_SUCCESS)
+ retval = pam_set_item(pamh, PAM_AUTHTOK, resp[0].resp);
+ if (retval != PAM_SUCCESS)
return retval;
memset(resp[0].resp, 0, strlen(resp[0].resp));
free(resp[0].resp);
@@ -63,7 +64,7 @@ pam_conv_pass(pam_handle_t *pamh, const char *prompt, int options)
int
pam_get_pass(pam_handle_t *pamh, const char **passp, const char *prompt,
- int options)
+ struct options *options)
{
int retval;
const void *item = NULL;
@@ -71,21 +72,23 @@ pam_get_pass(pam_handle_t *pamh, const char **passp, const char *prompt,
/*
* Grab the already-entered password if we might want to use it.
*/
- if (options & (PAM_OPT_TRY_FIRST_PASS | PAM_OPT_USE_FIRST_PASS)) {
- if ((retval = pam_get_item(pamh, PAM_AUTHTOK, &item)) !=
- PAM_SUCCESS)
+ if (pam_test_option(options, PAM_OPT_TRY_FIRST_PASS, NULL) ||
+ pam_test_option(options, PAM_OPT_USE_FIRST_PASS, NULL)) {
+ retval = pam_get_item(pamh, PAM_AUTHTOK, &item);
+ if (retval != PAM_SUCCESS)
return retval;
}
if (item == NULL) {
/* The user hasn't entered a password yet. */
- if (options & PAM_OPT_USE_FIRST_PASS)
+ if (pam_test_option(options, PAM_OPT_USE_FIRST_PASS, NULL))
return PAM_AUTH_ERR;
/* Use the conversation function to get a password. */
- if ((retval = pam_conv_pass(pamh, prompt, options)) !=
- PAM_SUCCESS ||
- (retval = pam_get_item(pamh, PAM_AUTHTOK, &item)) !=
- PAM_SUCCESS)
+ retval = pam_conv_pass(pamh, prompt, options);
+ if (retval != PAM_SUCCESS)
+ return retval;
+ retval = pam_get_item(pamh, PAM_AUTHTOK, &item);
+ if (retval != PAM_SUCCESS)
return retval;
}
*passp = (const char *)item;
diff --git a/lib/libpam/libpam/pam_mod_misc.h b/lib/libpam/libpam/pam_mod_misc.h
index ff4dfa5..cefc052 100644
--- a/lib/libpam/libpam/pam_mod_misc.h
+++ b/lib/libpam/libpam/pam_mod_misc.h
@@ -31,22 +31,44 @@
#include <sys/cdefs.h>
-/* Options */
-#define PAM_OPT_DEBUG 0x0001
-#define PAM_OPT_NO_WARN 0x0002
-#define PAM_OPT_USE_FIRST_PASS 0x0004
-#define PAM_OPT_TRY_FIRST_PASS 0x0008
-#define PAM_OPT_USE_MAPPED_PASS 0x0010
-#define PAM_OPT_ECHO_PASS 0x0020
-#define PAM_OPT_AUTH_AS_SELF 0x0040
-#define PAM_OPT_NULLOK 0x0080
-#define PAM_OPT_NO_ANON 0x0100
-#define PAM_OPT_IGNORE 0x0200
+/* Standard options
+ */
+enum opt { PAM_OPT_DEBUG, PAM_OPT_NO_WARN, PAM_OPT_ECHO_PASS,
+ PAM_OPT_USE_FIRST_PASS, PAM_OPT_TRY_FIRST_PASS, PAM_OPT_USE_MAPPED_PASS,
+ PAM_OPT_EXPOSE_ACCOUNT, PAM_OPT_STD_MAX /* XXX */ };
+
+#define PAM_MAX_OPTIONS 20
+
+struct opttab {
+ const char *name;
+ int value;
+};
+
+struct options {
+ struct {
+ int bool;
+ char *arg;
+ } opt[PAM_MAX_OPTIONS];
+};
__BEGIN_DECLS
-int pam_get_pass(pam_handle_t *, const char **, const char *, int);
-int pam_prompt(pam_handle_t *, int, const char *, char **);
-int pam_std_option(int *, const char *);
+int pam_get_pass(pam_handle_t *, const char **, const char *, struct options *);
+int pam_prompt(pam_handle_t *, int, const char *, char **);
+void pam_std_option(struct options *, struct opttab *, int, const char **);
+int pam_test_option(struct options *, enum opt, char **);
+void pam_set_option(struct options *, enum opt);
+void pam_clear_option(struct options *, enum opt);
+void _pam_log(struct options *, const char *, const char *, const char *, ...);
+void _pam_log_retval(struct options *, const char *, const char *, int);
__END_DECLS
+#define PAM_LOG(args...) \
+ _pam_log(&options, __FILE__, __FUNCTION__, ##args)
+
+#define PAM_RETURN(arg) \
+ do { \
+ _pam_log_retval(&options, __FILE__, __FUNCTION__, arg); \
+ return arg; \
+ } while (0)
+
#endif
diff --git a/lib/libpam/libpam/pam_prompt.c b/lib/libpam/libpam/pam_prompt.c
index 220616e..7d80745 100644
--- a/lib/libpam/libpam/pam_prompt.c
+++ b/lib/libpam/libpam/pam_prompt.c
@@ -27,6 +27,7 @@
*/
#include <security/pam_modules.h>
+#include <stdlib.h>
#include "pam_mod_misc.h"
/*
@@ -36,22 +37,22 @@
int
pam_prompt(pam_handle_t *pamh, int style, const char *prompt, char **user_msg)
{
- int retval;
- const void *item;
const struct pam_conv *conv;
struct pam_message msg;
const struct pam_message *msgs[1];
struct pam_response *resp;
+ const void *item;
+ int retval;
- if ((retval = pam_get_item(pamh, PAM_CONV, &item)) !=
- PAM_SUCCESS)
+ retval = pam_get_item(pamh, PAM_CONV, &item);
+ if (retval != PAM_SUCCESS)
return retval;
conv = (const struct pam_conv *)item;
msg.msg_style = style;
msg.msg = prompt != NULL ? prompt : "";
msgs[0] = &msg;
- if ((retval = conv->conv(1, msgs, &resp, conv->appdata_ptr)) !=
- PAM_SUCCESS)
+ retval = conv->conv(1, msgs, &resp, conv->appdata_ptr);
+ if (retval != PAM_SUCCESS)
return retval;
if (user_msg != NULL)
*user_msg = resp[0].resp;
diff --git a/lib/libpam/libpam/pam_std_option.c b/lib/libpam/libpam/pam_std_option.c
index 266514e..4388197 100644
--- a/lib/libpam/libpam/pam_std_option.c
+++ b/lib/libpam/libpam/pam_std_option.c
@@ -27,40 +27,148 @@
*/
#include <security/pam_modules.h>
+#include <stdio.h>
#include <string.h>
+#include <syslog.h>
#include "pam_mod_misc.h"
-/*
- * If the given name is a standard option, set the corresponding flag in
- * the options word and return 0. Else return -1.
+/* Everyone has to have these options. It is not an error to
+ * specify them and then not use them.
*/
+static struct opttab std_options[PAM_MAX_OPTIONS] = {
+ { "debug", PAM_OPT_DEBUG },
+ { "no_warn", PAM_OPT_NO_WARN },
+ { "echo_pass", PAM_OPT_ECHO_PASS },
+ { "use_first_pass", PAM_OPT_USE_FIRST_PASS },
+ { "try_first_pass", PAM_OPT_TRY_FIRST_PASS },
+ { "use_mapped_pass", PAM_OPT_USE_MAPPED_PASS },
+ { "expose_account", PAM_OPT_EXPOSE_ACCOUNT },
+ { NULL, 0 }
+};
+
+/* Populate the options structure, syslogging all errors */
+void
+pam_std_option(struct options *options, struct opttab other_options[],
+ int argc, const char **argv)
+{
+ struct opttab *oo;
+ int i, j, arglen, found;
+
+ j = 0;
+ for (i = 0; i < PAM_MAX_OPTIONS; i++) {
+ options->opt[i].bool = 0;
+ options->opt[i].arg = NULL;
+ if (j == 0 && std_options[i].name == NULL)
+ j = i;
+ /* XXX Bad juju happens if loop exits with j == 0 */
+ }
+ if (other_options)
+ for (oo = other_options; oo->name != NULL; oo++) {
+ if (oo == NULL || oo->name == NULL)
+ break;
+ std_options[j].name = oo->name;
+ std_options[j].value = oo->value;
+ j++;
+ }
+ if (j < PAM_MAX_OPTIONS) {
+ std_options[j].name = NULL;
+ std_options[j].value = 0;
+ }
+ for (j = 0; j < argc; j++) {
+#ifdef DEBUG
+ syslog(LOG_DEBUG, "Doing arg %s ", argv[j]);
+#endif
+ found = 0;
+ for (i = 0; i < PAM_MAX_OPTIONS; i++) {
+ if (std_options[i].name == NULL)
+ break;
+ if (strcmp(argv[j], std_options[i].name) == 0) {
+ options->opt[std_options[i].value].bool = 1;
+ found = 1;
+ break;
+ }
+ else {
+ arglen = strlen(std_options[i].name);
+ if (strncmp(argv[j], std_options[i].name,
+ arglen) == 0
+ && argv[j][arglen] == '=') {
+ options->opt[std_options[i].value].bool
+ = 1;
+ options->opt[std_options[i].value].arg =
+ strdup(&argv[j][arglen + 1]);
+ found = 1;
+ break;
+ }
+ }
+ }
+ if (!found)
+ syslog(LOG_WARNING, "PAM option: %s invalid", argv[j]);
+ }
+}
+
+/* Test if option is set in options */
+int
+pam_test_option(struct options *options, enum opt option, char **arg)
+{
+ if (arg != NULL)
+ *arg = options->opt[option].arg;
+ return options->opt[option].bool;
+}
+
+/* Set option in options, errors to syslog */
+void
+pam_set_option(struct options *options, enum opt option)
+{
+ if (option < PAM_OPT_STD_MAX)
+ options->opt[option].bool = 1;
+#ifdef DEBUG
+ else
+ syslog(LOG_DEBUG, "PAM options: attempt to set option %d",
+ option);
+#endif
+}
+
+/* Clear option in options, errors to syslog */
+void
+pam_clear_option(struct options *options, enum opt option)
+{
+ if (option < PAM_OPT_STD_MAX)
+ options->opt[option].bool = 0;
+#ifdef DEBUG
+ else
+ syslog(LOG_DEBUG, "PAM options: attempt to clear option %d",
+ option);
+#endif
+}
+
+#if DEBUG1
+enum { PAM_OPT_FOO=PAM_OPT_STD_MAX, PAM_OPT_BAR, PAM_OPT_BAZ, PAM_OPT_QUX };
+
+struct opttab other_options[] = {
+ { "foo", PAM_OPT_FOO },
+ { "bar", PAM_OPT_BAR },
+ { "baz", PAM_OPT_BAZ },
+ { "qux", PAM_OPT_QUX },
+ { NULL, 0 }
+};
+
int
-pam_std_option(int *options, const char *name)
+main(int argc, const char *argv[])
{
- struct opttab {
- const char *name;
- int value;
- };
- static struct opttab std_options[] = {
- { "debug", PAM_OPT_DEBUG },
- { "no_warn", PAM_OPT_NO_WARN },
- { "use_first_pass", PAM_OPT_USE_FIRST_PASS },
- { "try_first_pass", PAM_OPT_TRY_FIRST_PASS },
- { "use_mapped_pass", PAM_OPT_USE_MAPPED_PASS },
- { "echo_pass", PAM_OPT_ECHO_PASS },
- { "auth_as_self", PAM_OPT_AUTH_AS_SELF },
- { "nullok", PAM_OPT_NULLOK },
- { "no_anon", PAM_OPT_NO_ANON },
- { "ignore", PAM_OPT_IGNORE },
- { NULL, 0 }
- };
- struct opttab *p;
+ struct options options;
+ int i, opt;
+ char *arg;
- for (p = std_options; p->name != NULL; p++) {
- if (strcmp(name, p->name) == 0) {
- *options |= p->value;
- return 0;
+ pam_std_option(&options, other_options, argc, argv);
+ for (i = 0; i < PAM_MAX_OPTIONS; i++) {
+ opt = pam_test_option(&options, i, &arg);
+ if (opt) {
+ if (arg == NULL)
+ printf("%d []\n", i);
+ else
+ printf("%d [%s]\n", i, arg);
}
}
- return -1;
+ return 0;
}
+#endif
diff --git a/lib/libpam/libpam/security/pam_mod_misc.h b/lib/libpam/libpam/security/pam_mod_misc.h
index ff4dfa5..cefc052 100644
--- a/lib/libpam/libpam/security/pam_mod_misc.h
+++ b/lib/libpam/libpam/security/pam_mod_misc.h
@@ -31,22 +31,44 @@
#include <sys/cdefs.h>
-/* Options */
-#define PAM_OPT_DEBUG 0x0001
-#define PAM_OPT_NO_WARN 0x0002
-#define PAM_OPT_USE_FIRST_PASS 0x0004
-#define PAM_OPT_TRY_FIRST_PASS 0x0008
-#define PAM_OPT_USE_MAPPED_PASS 0x0010
-#define PAM_OPT_ECHO_PASS 0x0020
-#define PAM_OPT_AUTH_AS_SELF 0x0040
-#define PAM_OPT_NULLOK 0x0080
-#define PAM_OPT_NO_ANON 0x0100
-#define PAM_OPT_IGNORE 0x0200
+/* Standard options
+ */
+enum opt { PAM_OPT_DEBUG, PAM_OPT_NO_WARN, PAM_OPT_ECHO_PASS,
+ PAM_OPT_USE_FIRST_PASS, PAM_OPT_TRY_FIRST_PASS, PAM_OPT_USE_MAPPED_PASS,
+ PAM_OPT_EXPOSE_ACCOUNT, PAM_OPT_STD_MAX /* XXX */ };
+
+#define PAM_MAX_OPTIONS 20
+
+struct opttab {
+ const char *name;
+ int value;
+};
+
+struct options {
+ struct {
+ int bool;
+ char *arg;
+ } opt[PAM_MAX_OPTIONS];
+};
__BEGIN_DECLS
-int pam_get_pass(pam_handle_t *, const char **, const char *, int);
-int pam_prompt(pam_handle_t *, int, const char *, char **);
-int pam_std_option(int *, const char *);
+int pam_get_pass(pam_handle_t *, const char **, const char *, struct options *);
+int pam_prompt(pam_handle_t *, int, const char *, char **);
+void pam_std_option(struct options *, struct opttab *, int, const char **);
+int pam_test_option(struct options *, enum opt, char **);
+void pam_set_option(struct options *, enum opt);
+void pam_clear_option(struct options *, enum opt);
+void _pam_log(struct options *, const char *, const char *, const char *, ...);
+void _pam_log_retval(struct options *, const char *, const char *, int);
__END_DECLS
+#define PAM_LOG(args...) \
+ _pam_log(&options, __FILE__, __FUNCTION__, ##args)
+
+#define PAM_RETURN(arg) \
+ do { \
+ _pam_log_retval(&options, __FILE__, __FUNCTION__, arg); \
+ return arg; \
+ } while (0)
+
#endif
OpenPOWER on IntegriCloud