summaryrefslogtreecommitdiffstats
path: root/contrib/openpam/lib
diff options
context:
space:
mode:
authordes <des@FreeBSD.org>2012-05-26 17:10:16 +0000
committerdes <des@FreeBSD.org>2012-05-26 17:10:16 +0000
commite591108b4ff3b509a90d50646dac489bd3586c83 (patch)
tree8db8bd736c680a375326928576df3d5395b6a4f3 /contrib/openpam/lib
parent14a6c41ca7a3722b33e2208c83fb8b4a009b0ecf (diff)
parent4d990f74cc8d1f6788d9e35ce8ada48cc0b5f41f (diff)
downloadFreeBSD-src-e591108b4ff3b509a90d50646dac489bd3586c83.zip
FreeBSD-src-e591108b4ff3b509a90d50646dac489bd3586c83.tar.gz
Update to OpenPAM Micrampelis.
Diffstat (limited to 'contrib/openpam/lib')
-rw-r--r--contrib/openpam/lib/Makefile.am11
-rw-r--r--contrib/openpam/lib/Makefile.in29
-rw-r--r--contrib/openpam/lib/openpam_check_owner_perms.c23
-rw-r--r--contrib/openpam/lib/openpam_configure.c595
-rw-r--r--contrib/openpam/lib/openpam_constants.h9
-rw-r--r--contrib/openpam/lib/openpam_ctype.h68
-rw-r--r--contrib/openpam/lib/openpam_debug.h45
-rw-r--r--contrib/openpam/lib/openpam_dynamic.c81
-rw-r--r--contrib/openpam/lib/openpam_features.c69
-rw-r--r--contrib/openpam/lib/openpam_features.h48
-rw-r--r--contrib/openpam/lib/openpam_get_feature.c99
-rw-r--r--contrib/openpam/lib/openpam_get_option.c3
-rw-r--r--contrib/openpam/lib/openpam_impl.h18
-rw-r--r--contrib/openpam/lib/openpam_load.c6
-rw-r--r--contrib/openpam/lib/openpam_log.c14
-rw-r--r--contrib/openpam/lib/openpam_readline.c52
-rw-r--r--contrib/openpam/lib/openpam_readlinev.c156
-rw-r--r--contrib/openpam/lib/openpam_readword.c207
-rw-r--r--contrib/openpam/lib/openpam_set_feature.c75
-rw-r--r--contrib/openpam/lib/openpam_set_option.c3
-rw-r--r--contrib/openpam/lib/openpam_straddch.c111
-rw-r--r--contrib/openpam/lib/openpam_strlcat.h54
-rw-r--r--contrib/openpam/lib/openpam_strlcmp.h5
-rw-r--r--contrib/openpam/lib/openpam_strlcpy.h7
-rw-r--r--contrib/openpam/lib/openpam_subst.c5
-rw-r--r--contrib/openpam/lib/openpam_ttyconv.c12
-rw-r--r--contrib/openpam/lib/pam_get_authtok.c12
-rw-r--r--contrib/openpam/lib/pam_putenv.c4
-rw-r--r--contrib/openpam/lib/pam_setenv.c4
29 files changed, 1355 insertions, 470 deletions
diff --git a/contrib/openpam/lib/Makefile.am b/contrib/openpam/lib/Makefile.am
index 3a2e60e..9ce2d2f 100644
--- a/contrib/openpam/lib/Makefile.am
+++ b/contrib/openpam/lib/Makefile.am
@@ -1,4 +1,4 @@
-# $Id: Makefile.am 499 2011-11-22 11:51:50Z des $
+# $Id: Makefile.am 602 2012-04-15 17:31:15Z des $
NULL =
@@ -8,8 +8,11 @@ lib_LTLIBRARIES = libpam.la
noinst_HEADERS = \
openpam_constants.h \
+ openpam_ctype.h \
openpam_debug.h \
+ openpam_features.h \
openpam_impl.h \
+ openpam_strlcat.h \
openpam_strlcmp.h \
openpam_strlcpy.h
@@ -20,17 +23,23 @@ libpam_la_SOURCES = \
openpam_constants.c \
openpam_dispatch.c \
openpam_dynamic.c \
+ openpam_features.c \
openpam_findenv.c \
openpam_free_data.c \
openpam_free_envlist.c \
+ openpam_get_feature.c \
openpam_get_option.c \
openpam_load.c \
openpam_log.c \
openpam_nullconv.c \
openpam_readline.c \
+ openpam_readlinev.c \
+ openpam_readword.c \
openpam_restore_cred.c \
openpam_set_option.c \
+ openpam_set_feature.c \
openpam_static.c \
+ openpam_straddch.c \
openpam_subst.c \
openpam_ttyconv.c \
pam_acct_mgmt.c \
diff --git a/contrib/openpam/lib/Makefile.in b/contrib/openpam/lib/Makefile.in
index 0052ce2..353fbab 100644
--- a/contrib/openpam/lib/Makefile.in
+++ b/contrib/openpam/lib/Makefile.in
@@ -15,7 +15,7 @@
@SET_MAKE@
-# $Id: Makefile.am 499 2011-11-22 11:51:50Z des $
+# $Id: Makefile.am 602 2012-04-15 17:31:15Z des $
VPATH = @srcdir@
@@ -76,11 +76,13 @@ am__objects_1 =
am_libpam_la_OBJECTS = openpam_borrow_cred.lo \
openpam_check_owner_perms.lo openpam_configure.lo \
openpam_constants.lo openpam_dispatch.lo openpam_dynamic.lo \
- openpam_findenv.lo openpam_free_data.lo \
- openpam_free_envlist.lo openpam_get_option.lo openpam_load.lo \
- openpam_log.lo openpam_nullconv.lo openpam_readline.lo \
- openpam_restore_cred.lo openpam_set_option.lo \
- openpam_static.lo openpam_subst.lo openpam_ttyconv.lo \
+ openpam_features.lo openpam_findenv.lo openpam_free_data.lo \
+ openpam_free_envlist.lo openpam_get_feature.lo \
+ openpam_get_option.lo openpam_load.lo openpam_log.lo \
+ openpam_nullconv.lo openpam_readline.lo openpam_readlinev.lo \
+ openpam_readword.lo openpam_restore_cred.lo \
+ openpam_set_option.lo openpam_set_feature.lo openpam_static.lo \
+ openpam_straddch.lo openpam_subst.lo openpam_ttyconv.lo \
pam_acct_mgmt.lo pam_authenticate.lo pam_chauthtok.lo \
pam_close_session.lo pam_end.lo pam_error.lo \
pam_get_authtok.lo pam_get_data.lo pam_get_item.lo \
@@ -234,8 +236,11 @@ INCLUDES = -I$(top_srcdir)/include
lib_LTLIBRARIES = libpam.la
noinst_HEADERS = \
openpam_constants.h \
+ openpam_ctype.h \
openpam_debug.h \
+ openpam_features.h \
openpam_impl.h \
+ openpam_strlcat.h \
openpam_strlcmp.h \
openpam_strlcpy.h
@@ -246,17 +251,23 @@ libpam_la_SOURCES = \
openpam_constants.c \
openpam_dispatch.c \
openpam_dynamic.c \
+ openpam_features.c \
openpam_findenv.c \
openpam_free_data.c \
openpam_free_envlist.c \
+ openpam_get_feature.c \
openpam_get_option.c \
openpam_load.c \
openpam_log.c \
openpam_nullconv.c \
openpam_readline.c \
+ openpam_readlinev.c \
+ openpam_readword.c \
openpam_restore_cred.c \
openpam_set_option.c \
+ openpam_set_feature.c \
openpam_static.c \
+ openpam_straddch.c \
openpam_subst.c \
openpam_ttyconv.c \
pam_acct_mgmt.c \
@@ -387,17 +398,23 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openpam_constants.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openpam_dispatch.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openpam_dynamic.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openpam_features.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openpam_findenv.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openpam_free_data.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openpam_free_envlist.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openpam_get_feature.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openpam_get_option.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openpam_load.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openpam_log.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openpam_nullconv.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openpam_readline.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openpam_readlinev.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openpam_readword.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openpam_restore_cred.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openpam_set_feature.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openpam_set_option.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openpam_static.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openpam_straddch.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openpam_subst.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openpam_ttyconv.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pam_acct_mgmt.Plo@am__quote@
diff --git a/contrib/openpam/lib/openpam_check_owner_perms.c b/contrib/openpam/lib/openpam_check_owner_perms.c
index 9d64ed6..d3b2ca9 100644
--- a/contrib/openpam/lib/openpam_check_owner_perms.c
+++ b/contrib/openpam/lib/openpam_check_owner_perms.c
@@ -11,6 +11,9 @@
* 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
@@ -24,7 +27,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: openpam_check_owner_perms.c 499 2011-11-22 11:51:50Z des $
+ * $Id: openpam_check_owner_perms.c 543 2012-03-31 22:11:34Z des $
*/
#ifdef HAVE_CONFIG_H
@@ -67,6 +70,12 @@ openpam_check_desc_owner_perms(const char *name, int fd)
errno = serrno;
return (-1);
}
+ if (!S_ISREG(sb.st_mode)) {
+ openpam_log(PAM_LOG_ERROR,
+ "%s: not a regular file", name);
+ errno = EINVAL;
+ return (-1);
+ }
if ((sb.st_uid != root && sb.st_uid != arbitrator) ||
(sb.st_mode & (S_IWGRP|S_IWOTH)) != 0) {
openpam_log(PAM_LOG_ERROR,
@@ -84,7 +93,7 @@ openpam_check_desc_owner_perms(const char *name, int fd)
* up to it are owned by either root or the arbitrator and that they are
* not writable by group or other.
*
- * Note that openpam_check_file_owner_perms() should be used instead if
+ * Note that openpam_check_desc_owner_perms() should be used instead if
* possible to avoid a race between the ownership / permission check and
* the actual open().
*/
@@ -95,8 +104,9 @@ openpam_check_path_owner_perms(const char *path)
uid_t root, arbitrator;
char pathbuf[PATH_MAX];
struct stat sb;
- int len, serrno;
+ int len, serrno, tip;
+ tip = 1;
root = 0;
arbitrator = geteuid();
if (realpath(path, pathbuf) == NULL)
@@ -111,6 +121,12 @@ openpam_check_path_owner_perms(const char *path)
}
return (-1);
}
+ if (tip && !S_ISREG(sb.st_mode)) {
+ openpam_log(PAM_LOG_ERROR,
+ "%s: not a regular file", pathbuf);
+ errno = EINVAL;
+ return (-1);
+ }
if ((sb.st_uid != root && sb.st_uid != arbitrator) ||
(sb.st_mode & (S_IWGRP|S_IWOTH)) != 0) {
openpam_log(PAM_LOG_ERROR,
@@ -120,6 +136,7 @@ openpam_check_path_owner_perms(const char *path)
}
while (--len > 0 && pathbuf[len] != '/')
pathbuf[len] = '\0';
+ tip = 0;
}
return (0);
}
diff --git a/contrib/openpam/lib/openpam_configure.c b/contrib/openpam/lib/openpam_configure.c
index bef7817..778bec8 100644
--- a/contrib/openpam/lib/openpam_configure.c
+++ b/contrib/openpam/lib/openpam_configure.c
@@ -1,6 +1,6 @@
/*-
* Copyright (c) 2001-2003 Networks Associates Technology, Inc.
- * Copyright (c) 2004-2011 Dag-Erling Smørgrav
+ * Copyright (c) 2004-2012 Dag-Erling Smørgrav
* All rights reserved.
*
* This software was developed for the FreeBSD Project by ThinkSec AS and
@@ -32,13 +32,15 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: openpam_configure.c 500 2011-11-22 12:07:03Z des $
+ * $Id: openpam_configure.c 601 2012-04-14 20:37:45Z des $
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
+#include <sys/param.h>
+
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
@@ -48,389 +50,183 @@
#include <security/pam_appl.h>
#include "openpam_impl.h"
-#include "openpam_strlcmp.h"
+#include "openpam_ctype.h"
+#include "openpam_strlcat.h"
+#include "openpam_strlcpy.h"
static int openpam_load_chain(pam_handle_t *, const char *, pam_facility_t);
/*
- * Evaluates to non-zero if the argument is a linear whitespace character.
- */
-#define is_lws(ch) \
- (ch == ' ' || ch == '\t')
-
-/*
- * Evaluates to non-zero if the argument is a printable ASCII character.
- * Assumes that the execution character set is a superset of ASCII.
- */
-#define is_p(ch) \
- (ch >= '!' && ch <= '~')
-
-/*
- * Returns non-zero if the argument belongs to the POSIX Portable Filename
- * Character Set. Assumes that the execution character set is a superset
- * of ASCII.
- */
-#define is_pfcs(ch) \
- ((ch >= '0' && ch <= '9') || \
- (ch >= 'A' && ch <= 'Z') || \
- (ch >= 'a' && ch <= 'z') || \
- ch == '.' || ch == '_' || ch == '-')
-
-/*
- * Parse the service name.
- *
- * Returns the length of the service name, or 0 if the end of the string
- * was reached or a disallowed non-whitespace character was encountered.
+ * Validate a service name.
*
- * If parse_service_name() is successful, it updates *service to point to
- * the first character of the service name and *line to point one
- * character past the end. If it reaches the end of the string, it
- * updates *line to point to the terminating NUL character and leaves
- * *service unmodified. In all other cases, it leaves both *line and
- * *service unmodified.
- *
- * Allowed characters are all characters in the POSIX portable filename
- * character set.
+ * Returns a non-zero value if the argument points to a NUL-terminated
+ * string consisting entirely of characters in the POSIX portable filename
+ * character set, excluding the path separator character.
*/
static int
-parse_service_name(char **line, char **service)
+valid_service_name(const char *name)
{
- char *b, *e;
+ const char *p;
- for (b = *line; *b && is_lws(*b); ++b)
- /* nothing */ ;
- if (!*b) {
- *line = b;
- return (0);
+ if (OPENPAM_FEATURE(RESTRICT_SERVICE_NAME)) {
+ /* path separator not allowed */
+ for (p = name; *p != '\0'; ++p)
+ if (!is_pfcs(*p))
+ return (0);
+ } else {
+ /* path separator allowed */
+ for (p = name; *p != '\0'; ++p)
+ if (!is_pfcs(*p) && *p != '/')
+ return (0);
}
- for (e = b; *e && !is_lws(*e); ++e)
- if (!is_pfcs(*e))
- return (0);
- if (e == b)
- return (0);
- *line = e;
- *service = b;
- return (e - b);
+ return (1);
}
/*
* Parse the facility name.
*
- * Returns the corresponding pam_facility_t value, or -1 if the end of the
- * string was reached, a disallowed non-whitespace character was
- * encountered, or the first word was not a recognized facility name.
- *
- * If parse_facility_name() is successful, it updates *line to point one
- * character past the end of the facility name. If it reaches the end of
- * the string, it updates *line to point to the terminating NUL character.
- * In all other cases, it leaves *line unmodified.
+ * Returns the corresponding pam_facility_t value, or -1 if the argument
+ * is not a valid facility name.
*/
static pam_facility_t
-parse_facility_name(char **line)
+parse_facility_name(const char *name)
{
- char *b, *e;
int i;
- for (b = *line; *b && is_lws(*b); ++b)
- /* nothing */ ;
- if (!*b) {
- *line = b;
- return ((pam_facility_t)-1);
- }
- for (e = b; *e && !is_lws(*e); ++e)
- /* nothing */ ;
- if (e == b)
- return ((pam_facility_t)-1);
for (i = 0; i < PAM_NUM_FACILITIES; ++i)
- if (strlcmp(pam_facility_name[i], b, e - b) == 0)
- break;
- if (i == PAM_NUM_FACILITIES)
- return ((pam_facility_t)-1);
- *line = e;
- return (i);
-}
-
-/*
- * Parse the word "include".
- *
- * If the next word on the line is "include", parse_include() updates
- * *line to point one character past "include" and returns 1. Otherwise,
- * it leaves *line unmodified and returns 0.
- */
-static int
-parse_include(char **line)
-{
- char *b, *e;
-
- for (b = *line; *b && is_lws(*b); ++b)
- /* nothing */ ;
- if (!*b) {
- *line = b;
- return (-1);
- }
- for (e = b; *e && !is_lws(*e); ++e)
- /* nothing */ ;
- if (e == b)
- return (0);
- if (strlcmp("include", b, e - b) != 0)
- return (0);
- *line = e;
- return (1);
+ if (strcmp(pam_facility_name[i], name) == 0)
+ return (i);
+ return ((pam_facility_t)-1);
}
/*
* Parse the control flag.
*
- * Returns the corresponding pam_control_t value, or -1 if the end of the
- * string was reached, a disallowed non-whitespace character was
- * encountered, or the first word was not a recognized control flag.
- *
- * If parse_control_flag() is successful, it updates *line to point one
- * character past the end of the control flag. If it reaches the end of
- * the string, it updates *line to point to the terminating NUL character.
- * In all other cases, it leaves *line unmodified.
+ * Returns the corresponding pam_control_t value, or -1 if the argument is
+ * not a valid control flag name.
*/
static pam_control_t
-parse_control_flag(char **line)
+parse_control_flag(const char *name)
{
- char *b, *e;
int i;
- for (b = *line; *b && is_lws(*b); ++b)
- /* nothing */ ;
- if (!*b) {
- *line = b;
- return ((pam_control_t)-1);
- }
- for (e = b; *e && !is_lws(*e); ++e)
- /* nothing */ ;
- if (e == b)
- return ((pam_control_t)-1);
for (i = 0; i < PAM_NUM_CONTROL_FLAGS; ++i)
- if (strlcmp(pam_control_flag_name[i], b, e - b) == 0)
- break;
- if (i == PAM_NUM_CONTROL_FLAGS)
- return ((pam_control_t)-1);
- *line = e;
- return (i);
+ if (strcmp(pam_control_flag_name[i], name) == 0)
+ return (i);
+ return ((pam_control_t)-1);
}
/*
- * Parse a file name.
- *
- * Returns the length of the file name, or 0 if the end of the string was
- * reached or a disallowed non-whitespace character was encountered.
+ * Validate a file name.
*
- * If parse_filename() is successful, it updates *filename to point to the
- * first character of the filename and *line to point one character past
- * the end. If it reaches the end of the string, it updates *line to
- * point to the terminating NUL character and leaves *filename unmodified.
- * In all other cases, it leaves both *line and *filename unmodified.
- *
- * Allowed characters are all characters in the POSIX portable filename
- * character set, plus the path separator (forward slash).
+ * Returns a non-zero value if the argument points to a NUL-terminated
+ * string consisting entirely of characters in the POSIX portable filename
+ * character set, including the path separator character.
*/
static int
-parse_filename(char **line, char **filename)
+valid_module_name(const char *name)
{
- char *b, *e;
-
- for (b = *line; *b && is_lws(*b); ++b)
- /* nothing */ ;
- if (!*b) {
- *line = b;
- return (0);
- }
- for (e = b; *e && !is_lws(*e); ++e)
- if (!is_pfcs(*e) && *e != '/')
- return (0);
- if (e == b)
- return (0);
- *line = e;
- *filename = b;
- return (e - b);
-}
+ const char *p;
-/*
- * Parse an option.
- *
- * Returns a dynamically allocated string containing the next module
- * option, or NULL if the end of the string was reached or a disallowed
- * non-whitespace character was encountered.
- *
- * If parse_option() is successful, it updates *line to point one
- * character past the end of the option. If it reaches the end of the
- * string, it updates *line to point to the terminating NUL character. In
- * all other cases, it leaves *line unmodified.
- *
- * If parse_option() fails to allocate memory, it will return NULL and set
- * errno to a non-zero value.
- *
- * Allowed characters for option names are all characters in the POSIX
- * portable filename character set. Allowed characters for option values
- * are any printable non-whitespace characters. The option value may be
- * quoted in either single or double quotes, in which case space
- * characters and whichever quote character was not used are allowed.
- * Note that the entire value must be quoted, not just part of it.
- */
-static char *
-parse_option(char **line)
-{
- char *nb, *ne, *vb, *ve;
- unsigned char q = 0;
- char *option;
- size_t size;
-
- errno = 0;
- for (nb = *line; *nb && is_lws(*nb); ++nb)
- /* nothing */ ;
- if (!*nb) {
- *line = nb;
- return (NULL);
- }
- for (ne = nb; *ne && !is_lws(*ne) && *ne != '='; ++ne)
- if (!is_pfcs(*ne))
- return (NULL);
- if (ne == nb)
- return (NULL);
- if (*ne == '=') {
- vb = ne + 1;
- if (*vb == '"' || *vb == '\'')
- q = *vb++;
- for (ve = vb;
- *ve && *ve != q && (is_p(*ve) || (q && is_lws(*ve)));
- ++ve)
- /* nothing */ ;
- if (q && *ve != q)
- /* non-printable character or missing endquote */
- return (NULL);
- if (q && *(ve + 1) && !is_lws(*(ve + 1)))
- /* garbage after value */
- return (NULL);
+ if (OPENPAM_FEATURE(RESTRICT_MODULE_NAME)) {
+ /* path separator not allowed */
+ for (p = name; *p != '\0'; ++p)
+ if (!is_pfcs(*p))
+ return (0);
} else {
- vb = ve = ne;
+ /* path separator allowed */
+ for (p = name; *p != '\0'; ++p)
+ if (!is_pfcs(*p) && *p != '/')
+ return (0);
}
- size = (ne - nb) + 1;
- if (ve > vb)
- size += (ve - vb) + 1;
- if ((option = malloc(size)) == NULL)
- return (NULL);
- strncpy(option, nb, ne - nb);
- if (ve > vb) {
- option[ne - nb] = '=';
- strncpy(option + (ne - nb) + 1, vb, ve - vb);
- }
- option[size - 1] = '\0';
- *line = q ? ve + 1 : ve;
- return (option);
-}
-
-/*
- * Consume trailing whitespace.
- *
- * If there are no non-whitespace characters left on the line, parse_eol()
- * updates *line to point at the terminating NUL character and returns 0.
- * Otherwise, it leaves *line unmodified and returns a non-zero value.
- */
-static int
-parse_eol(char **line)
-{
- char *p;
-
- for (p = *line; *p && is_lws(*p); ++p)
- /* nothing */ ;
- if (*p)
- return ((unsigned char)*p);
- *line = p;
- return (0);
+ return (1);
}
typedef enum { pam_conf_style, pam_d_style } openpam_style_t;
/*
* Extracts given chains from a policy file.
+ *
+ * Returns the number of policy entries which were found for the specified
+ * service and facility, or -1 if a system error occurred or a syntax
+ * error was encountered.
*/
static int
openpam_parse_chain(pam_handle_t *pamh,
const char *service,
pam_facility_t facility,
+ FILE *f,
const char *filename,
openpam_style_t style)
{
pam_chain_t *this, **next;
pam_facility_t fclt;
pam_control_t ctlf;
- char *line0, *line, *str, *name;
- char *option, **optv;
- int len, lineno, ret;
- FILE *f;
+ char *name, *servicename, *modulename;
+ int count, lineno, ret, serrno;
+ char **wordv, *word;
+ int i, wordc;
- if ((f = fopen(filename, "r")) == NULL) {
- openpam_log(errno == ENOENT ? PAM_LOG_DEBUG : PAM_LOG_NOTICE,
- "%s: %m", filename);
- return (PAM_SUCCESS);
- }
- if (openpam_check_desc_owner_perms(filename, fileno(f)) != 0) {
- fclose(f);
- return (PAM_SYSTEM_ERR);
- }
+ count = 0;
this = NULL;
name = NULL;
lineno = 0;
- while ((line0 = line = openpam_readline(f, &lineno, NULL)) != NULL) {
- /* get service name if necessary */
- if (style == pam_conf_style) {
- if ((len = parse_service_name(&line, &str)) == 0) {
- openpam_log(PAM_LOG_NOTICE,
- "%s(%d): invalid service name (ignored)",
- filename, lineno);
- FREE(line0);
- continue;
- }
- if (strlcmp(service, str, len) != 0) {
- FREE(line0);
- continue;
- }
+ wordc = 0;
+ wordv = NULL;
+ while ((wordv = openpam_readlinev(f, &lineno, &wordc)) != NULL) {
+ /* blank line? */
+ if (wordc == 0) {
+ FREEV(wordc, wordv);
+ continue;
}
+ i = 0;
- /* get facility name */
- if ((fclt = parse_facility_name(&line)) == (pam_facility_t)-1) {
+ /* check service name if necessary */
+ if (style == pam_conf_style &&
+ strcmp(wordv[i++], service) != 0) {
+ FREEV(wordc, wordv);
+ continue;
+ }
+
+ /* check facility name */
+ if ((word = wordv[i++]) == NULL ||
+ (fclt = parse_facility_name(word)) == (pam_facility_t)-1) {
openpam_log(PAM_LOG_ERROR,
"%s(%d): missing or invalid facility",
filename, lineno);
goto fail;
}
if (facility != fclt && facility != PAM_FACILITY_ANY) {
- FREE(line0);
+ FREEV(wordc, wordv);
continue;
}
/* check for "include" */
- if (parse_include(&line)) {
- if ((len = parse_service_name(&line, &str)) == 0) {
+ if ((word = wordv[i++]) != NULL &&
+ strcmp(word, "include") == 0) {
+ if ((servicename = wordv[i++]) == NULL ||
+ !valid_service_name(servicename)) {
openpam_log(PAM_LOG_ERROR,
- "%s(%d): missing or invalid filename",
+ "%s(%d): missing or invalid service name",
filename, lineno);
goto fail;
}
- if ((name = strndup(str, len)) == NULL)
- goto syserr;
- if (parse_eol(&line) != 0) {
+ if (wordv[i] != NULL) {
openpam_log(PAM_LOG_ERROR,
"%s(%d): garbage at end of line",
filename, lineno);
goto fail;
}
- ret = openpam_load_chain(pamh, name, fclt);
- FREE(name);
- if (ret != PAM_SUCCESS)
+ ret = openpam_load_chain(pamh, servicename, fclt);
+ FREEV(wordc, wordv);
+ if (ret < 0)
goto fail;
- FREE(line0);
continue;
}
/* get control flag */
- if ((ctlf = parse_control_flag(&line)) == (pam_control_t)-1) {
+ if (word == NULL || /* same word we compared to "include" */
+ (ctlf = parse_control_flag(word)) == (pam_control_t)-1) {
openpam_log(PAM_LOG_ERROR,
"%s(%d): missing or invalid control flag",
filename, lineno);
@@ -438,73 +234,76 @@ openpam_parse_chain(pam_handle_t *pamh,
}
/* get module name */
- if ((len = parse_filename(&line, &str)) == 0) {
+ if ((modulename = wordv[i++]) == NULL ||
+ !valid_module_name(modulename)) {
openpam_log(PAM_LOG_ERROR,
"%s(%d): missing or invalid module name",
filename, lineno);
goto fail;
}
- if ((name = strndup(str, len)) == NULL)
- goto syserr;
/* allocate new entry */
if ((this = calloc(1, sizeof *this)) == NULL)
goto syserr;
this->flag = ctlf;
- /* get module options */
- if ((this->optv = malloc(sizeof *optv)) == NULL)
- goto syserr;
- this->optc = 0;
- while ((option = parse_option(&line)) != NULL) {
- optv = realloc(this->optv,
- (this->optc + 2) * sizeof *optv);
- if (optv == NULL)
- goto syserr;
- this->optv = optv;
- this->optv[this->optc++] = option;
- }
- this->optv[this->optc] = NULL;
- if (*line != '\0') {
- openpam_log(PAM_LOG_ERROR,
- "%s(%d): syntax error in module options",
- filename, lineno);
- goto fail;
- }
-
/* load module */
- this->module = openpam_load_module(name);
- FREE(name);
- if (this->module == NULL)
+ if ((this->module = openpam_load_module(modulename)) == NULL)
goto fail;
+ /*
+ * The remaining items in wordv are the module's
+ * arguments. We could set this->optv = wordv + i, but
+ * then free(this->optv) wouldn't work. Instead, we free
+ * the words we've already consumed, shift the rest up,
+ * and clear the tail end of the array.
+ */
+ this->optc = wordc - i;
+ for (i = 0; i < wordc - this->optc; ++i) {
+ FREE(wordv[i]);
+ wordv[i] = wordv[wordc - this->optc + i];
+ wordv[wordc - this->optc + i] = NULL;
+ }
+ this->optv = wordv;
+ wordv = NULL;
+ wordc = 0;
+
/* hook it up */
for (next = &pamh->chains[fclt]; *next != NULL;
next = &(*next)->next)
/* nothing */ ;
*next = this;
this = NULL;
-
- /* next please... */
- FREE(line0);
+ ++count;
}
- if (!feof(f))
+ /*
+ * The loop ended because openpam_readword() returned NULL, which
+ * can happen for four different reasons: an I/O error (ferror(f)
+ * is true), a memory allocation failure (ferror(f) is false,
+ * errno is non-zero)
+ */
+ if (ferror(f) || errno != 0)
goto syserr;
+ if (!feof(f))
+ goto fail;
fclose(f);
- return (PAM_SUCCESS);
+ return (count);
syserr:
+ serrno = errno;
openpam_log(PAM_LOG_ERROR, "%s: %m", filename);
+ errno = serrno;
+ /* fall through */
fail:
- if (this && this->optc) {
- while (this->optc--)
- FREE(this->optv[this->optc]);
- FREE(this->optv);
- }
+ serrno = errno;
+ if (this && this->optc && this->optv)
+ FREEV(this->optc, this->optv);
FREE(this);
- FREE(line0);
+ FREEV(wordc, wordv);
+ FREE(wordv);
FREE(name);
fclose(f);
- return (PAM_SYSTEM_ERR);
+ errno = serrno;
+ return (-1);
}
static const char *openpam_policy_path[] = {
@@ -516,44 +315,110 @@ static const char *openpam_policy_path[] = {
};
/*
+ * Read the specified chains from the specified file.
+ *
+ * Returns 0 if the file exists but does not contain any matching lines.
+ *
+ * Returns -1 and sets errno to ENOENT if the file does not exist.
+ *
+ * Returns -1 and sets errno to some other non-zero value if the file
+ * exists but is unsafe or unreadable, or an I/O error occurs.
+ */
+static int
+openpam_load_file(pam_handle_t *pamh,
+ const char *service,
+ pam_facility_t facility,
+ const char *filename,
+ openpam_style_t style)
+{
+ FILE *f;
+ int ret, serrno;
+
+ /* attempt to open the file */
+ if ((f = fopen(filename, "r")) == NULL) {
+ serrno = errno;
+ openpam_log(errno == ENOENT ? PAM_LOG_DEBUG : PAM_LOG_ERROR,
+ "%s: %m", filename);
+ errno = serrno;
+ RETURNN(-1);
+ } else {
+ openpam_log(PAM_LOG_DEBUG, "found %s", filename);
+ }
+
+ /* verify type, ownership and permissions */
+ if (OPENPAM_FEATURE(VERIFY_POLICY_FILE) &&
+ openpam_check_desc_owner_perms(filename, fileno(f)) != 0) {
+ /* already logged the cause */
+ serrno = errno;
+ fclose(f);
+ errno = serrno;
+ RETURNN(-1);
+ }
+
+ /* parse the file */
+ ret = openpam_parse_chain(pamh, service, facility,
+ f, filename, style);
+ RETURNN(ret);
+}
+
+/*
* Locates the policy file for a given service and reads the given chains
* from it.
+ *
+ * Returns the number of policy entries which were found for the specified
+ * service and facility, or -1 if a system error occurred or a syntax
+ * error was encountered.
*/
static int
openpam_load_chain(pam_handle_t *pamh,
const char *service,
pam_facility_t facility)
{
- const char **path;
- char *filename;
+ const char *p, **path;
+ char filename[PATH_MAX];
size_t len;
+ openpam_style_t style;
int ret;
- /* don't allow to escape from policy_path */
- if (strchr(service, '/')) {
- openpam_log(PAM_LOG_ERROR, "invalid service name: %s",
- service);
- return (-PAM_SYSTEM_ERR);
+ ENTERS(facility < 0 ? "any" : pam_facility_name[facility]);
+
+ /* either absolute or relative to cwd */
+ if (strchr(service, '/') != NULL) {
+ if ((p = strrchr(service, '.')) != NULL && strcmp(p, ".conf") == 0)
+ style = pam_conf_style;
+ else
+ style = pam_d_style;
+ ret = openpam_load_file(pamh, service, facility,
+ service, style);
+ RETURNN(ret);
}
+ /* search standard locations */
for (path = openpam_policy_path; *path != NULL; ++path) {
- len = strlen(*path);
- if ((*path)[len - 1] == '/') {
- if (asprintf(&filename, "%s%s", *path, service) < 0) {
- openpam_log(PAM_LOG_ERROR, "asprintf(): %m");
- return (PAM_BUF_ERR);
+ /* construct filename */
+ len = strlcpy(filename, *path, sizeof filename);
+ if (filename[len - 1] == '/') {
+ len = strlcat(filename, service, sizeof filename);
+ if (len >= sizeof filename) {
+ errno = ENAMETOOLONG;
+ RETURNN(-1);
}
- ret = openpam_parse_chain(pamh, service, facility,
- filename, pam_d_style);
- FREE(filename);
+ style = pam_d_style;
} else {
- ret = openpam_parse_chain(pamh, service, facility,
- *path, pam_conf_style);
+ style = pam_conf_style;
}
- if (ret != PAM_SUCCESS)
- return (ret);
+ ret = openpam_load_file(pamh, service, facility,
+ filename, style);
+ /* the file exists, but an error occurred */
+ if (ret == -1 && errno != ENOENT)
+ RETURNN(ret);
+ /* in pam.d style, an empty file counts as a hit */
+ if (ret == 0 && style == pam_d_style)
+ RETURNN(ret);
}
- return (PAM_SUCCESS);
+
+ /* no hit */
+ RETURNN(0);
}
/*
@@ -567,25 +432,27 @@ openpam_configure(pam_handle_t *pamh,
const char *service)
{
pam_facility_t fclt;
- const char *p;
+ int serrno;
- for (p = service; *p; ++p)
- if (!is_pfcs(*p))
- return (PAM_SYSTEM_ERR);
-
- if (openpam_load_chain(pamh, service, PAM_FACILITY_ANY) != PAM_SUCCESS)
+ ENTERS(service);
+ if (!valid_service_name(service)) {
+ openpam_log(PAM_LOG_ERROR, "invalid service name");
+ RETURNC(PAM_SYSTEM_ERR);
+ }
+ if (openpam_load_chain(pamh, service, PAM_FACILITY_ANY) < 0)
goto load_err;
-
for (fclt = 0; fclt < PAM_NUM_FACILITIES; ++fclt) {
if (pamh->chains[fclt] != NULL)
continue;
- if (openpam_load_chain(pamh, PAM_OTHER, fclt) != PAM_SUCCESS)
+ if (openpam_load_chain(pamh, PAM_OTHER, fclt) < 0)
goto load_err;
}
- return (PAM_SUCCESS);
+ RETURNC(PAM_SUCCESS);
load_err:
+ serrno = errno;
openpam_clear_chains(pamh->chains);
- return (PAM_SYSTEM_ERR);
+ errno = serrno;
+ RETURNC(PAM_SYSTEM_ERR);
}
/*
diff --git a/contrib/openpam/lib/openpam_constants.h b/contrib/openpam/lib/openpam_constants.h
index b923179..a7d6ce8 100644
--- a/contrib/openpam/lib/openpam_constants.h
+++ b/contrib/openpam/lib/openpam_constants.h
@@ -11,6 +11,9 @@
* 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
@@ -24,11 +27,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: openpam_constants.h 491 2011-11-12 00:12:32Z des $
+ * $Id: openpam_constants.h 606 2012-04-20 11:06:38Z des $
*/
-#ifndef OPENPAM_CONSTANTS_INCLUDED
-#define OPENPAM_CONSTANTS_INCLUDED
+#ifndef OPENPAM_CONSTANTS_H_INCLUDED
+#define OPENPAM_CONSTANTS_H_INCLUDED
extern const char *pam_err_name[PAM_NUM_ERRORS];
extern const char *pam_item_name[PAM_NUM_ITEMS];
diff --git a/contrib/openpam/lib/openpam_ctype.h b/contrib/openpam/lib/openpam_ctype.h
new file mode 100644
index 0000000..b3ec846
--- /dev/null
+++ b/contrib/openpam/lib/openpam_ctype.h
@@ -0,0 +1,68 @@
+/*-
+ * Copyright (c) 2012 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
+ * in this position and unchanged.
+ * 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.
+ *
+ * $Id: openpam_ctype.h 578 2012-04-06 00:45:59Z des $
+ */
+
+#ifndef OPENPAM_CTYPE_H_INCLUDED
+#define OPENPAM_CTYPE_H_INCLUDED
+
+/*
+ * Evaluates to non-zero if the argument is a linear whitespace character.
+ * For the purposes of this macro, the definition of linear whitespace is
+ * extended to include the form feed and carraige return characters.
+ */
+#define is_lws(ch) \
+ (ch == ' ' || ch == '\t' || ch == '\f' || ch == '\r')
+
+/*
+ * Evaluates to non-zero if the argument is a whitespace character.
+ */
+#define is_ws(ch) \
+ (is_lws(ch) || ch == '\n')
+
+/*
+ * Evaluates to non-zero if the argument is a printable ASCII character.
+ * Assumes that the execution character set is a superset of ASCII.
+ */
+#define is_p(ch) \
+ (ch >= '!' && ch <= '~')
+
+/*
+ * Returns non-zero if the argument belongs to the POSIX Portable Filename
+ * Character Set. Assumes that the execution character set is a superset
+ * of ASCII.
+ */
+#define is_pfcs(ch) \
+ ((ch >= '0' && ch <= '9') || \
+ (ch >= 'A' && ch <= 'Z') || \
+ (ch >= 'a' && ch <= 'z') || \
+ ch == '.' || ch == '_' || ch == '-')
+
+#endif
diff --git a/contrib/openpam/lib/openpam_debug.h b/contrib/openpam/lib/openpam_debug.h
index ef2884d..050783e 100644
--- a/contrib/openpam/lib/openpam_debug.h
+++ b/contrib/openpam/lib/openpam_debug.h
@@ -32,60 +32,68 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: openpam_debug.h 491 2011-11-12 00:12:32Z des $
+ * $Id: openpam_debug.h 606 2012-04-20 11:06:38Z des $
*/
-#ifndef OPENPAM_DEBUG_INCLUDED
-#define OPENPAM_DEBUG_INCLUDED
+#ifndef OPENPAM_DEBUG_H_INCLUDED
+#define OPENPAM_DEBUG_H_INCLUDED
#ifdef OPENPAM_DEBUG
-#define ENTER() openpam_log(PAM_LOG_DEBUG, "entering")
+#define ENTER() openpam_log(PAM_LOG_LIBDEBUG, "entering")
#define ENTERI(i) do { \
int i_ = (i); \
if (i_ > 0 && i_ < PAM_NUM_ITEMS) \
- openpam_log(PAM_LOG_DEBUG, "entering: %s", pam_item_name[i_]); \
+ openpam_log(PAM_LOG_LIBDEBUG, "entering: %s", pam_item_name[i_]); \
else \
- openpam_log(PAM_LOG_DEBUG, "entering: %d", i_); \
+ openpam_log(PAM_LOG_LIBDEBUG, "entering: %d", i_); \
} while (0)
#define ENTERN(n) do { \
int n_ = (n); \
- openpam_log(PAM_LOG_DEBUG, "entering: %d", n_); \
+ openpam_log(PAM_LOG_LIBDEBUG, "entering: %d", n_); \
} while (0)
#define ENTERS(s) do { \
const char *s_ = (s); \
if (s_ == NULL) \
- openpam_log(PAM_LOG_DEBUG, "entering: NULL"); \
+ openpam_log(PAM_LOG_LIBDEBUG, "entering: NULL"); \
else \
- openpam_log(PAM_LOG_DEBUG, "entering: '%s'", s_); \
+ openpam_log(PAM_LOG_LIBDEBUG, "entering: '%s'", s_); \
} while (0)
-#define RETURNV() openpam_log(PAM_LOG_DEBUG, "returning")
+#define ENTERF(f) do { \
+ int f_ = (f); \
+ if (f_ >= 0 && f_ <= OPENPAM_NUM_FEATURES) \
+ openpam_log(PAM_LOG_LIBDEBUG, "entering: %s", \
+ openpam_features[f_].name); \
+ else \
+ openpam_log(PAM_LOG_LIBDEBUG, "entering: %d", f_); \
+} while (0)
+#define RETURNV() openpam_log(PAM_LOG_LIBDEBUG, "returning")
#define RETURNC(c) do { \
int c_ = (c); \
if (c_ >= 0 && c_ < PAM_NUM_ERRORS) \
- openpam_log(PAM_LOG_DEBUG, "returning %s", pam_err_name[c_]); \
+ openpam_log(PAM_LOG_LIBDEBUG, "returning %s", pam_err_name[c_]); \
else \
- openpam_log(PAM_LOG_DEBUG, "returning %d!", c_); \
+ openpam_log(PAM_LOG_LIBDEBUG, "returning %d!", c_); \
return (c_); \
} while (0)
#define RETURNN(n) do { \
int n_ = (n); \
- openpam_log(PAM_LOG_DEBUG, "returning %d", n_); \
+ openpam_log(PAM_LOG_LIBDEBUG, "returning %d", n_); \
return (n_); \
} while (0)
#define RETURNP(p) do { \
- const void *p_ = (p); \
+ void *p_ = (p); \
if (p_ == NULL) \
- openpam_log(PAM_LOG_DEBUG, "returning NULL"); \
+ openpam_log(PAM_LOG_LIBDEBUG, "returning NULL"); \
else \
- openpam_log(PAM_LOG_DEBUG, "returning %p", p_); \
+ openpam_log(PAM_LOG_LIBDEBUG, "returning %p", p_); \
return (p_); \
} while (0)
#define RETURNS(s) do { \
const char *s_ = (s); \
if (s_ == NULL) \
- openpam_log(PAM_LOG_DEBUG, "returning NULL"); \
+ openpam_log(PAM_LOG_LIBDEBUG, "returning NULL"); \
else \
- openpam_log(PAM_LOG_DEBUG, "returning '%s'", s_); \
+ openpam_log(PAM_LOG_LIBDEBUG, "returning '%s'", s_); \
return (s_); \
} while (0)
#else
@@ -93,6 +101,7 @@
#define ENTERI(i)
#define ENTERN(n)
#define ENTERS(s)
+#define ENTERF(f)
#define RETURNV() return
#define RETURNC(c) return (c)
#define RETURNN(n) return (n)
diff --git a/contrib/openpam/lib/openpam_dynamic.c b/contrib/openpam/lib/openpam_dynamic.c
index d44174f..1dfc1ac 100644
--- a/contrib/openpam/lib/openpam_dynamic.c
+++ b/contrib/openpam/lib/openpam_dynamic.c
@@ -32,7 +32,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: openpam_dynamic.c 502 2011-12-18 13:59:22Z des $
+ * $Id: openpam_dynamic.c 607 2012-04-20 11:09:37Z des $
*/
#ifdef HAVE_CONFIG_H
@@ -40,6 +40,7 @@
#endif
#include <dlfcn.h>
+#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
@@ -60,15 +61,50 @@
* Perform sanity checks and attempt to load a module
*/
+#ifdef HAVE_FDLOPEN
static void *
try_dlopen(const char *modfn)
{
+ void *dlh;
+ int fd;
- if (openpam_check_path_owner_perms(modfn) != 0)
+ if ((fd = open(modfn, O_RDONLY)) < 0)
+ return (NULL);
+ if (OPENPAM_FEATURE(VERIFY_MODULE_FILE) &&
+ openpam_check_desc_owner_perms(modfn, fd) != 0) {
+ close(fd);
+ return (NULL);
+ }
+ if ((dlh = fdlopen(fd, RTLD_NOW)) == NULL) {
+ openpam_log(PAM_LOG_ERROR, "%s: %s", modfn, dlerror());
+ close(fd);
+ errno = 0;
+ return (NULL);
+ }
+ close(fd);
+ return (dlh);
+}
+#else
+static void *
+try_dlopen(const char *modfn)
+{
+ int check_module_file;
+ void *dlh;
+
+ openpam_get_feature(OPENPAM_VERIFY_MODULE_FILE,
+ &check_module_file);
+ if (check_module_file &&
+ openpam_check_path_owner_perms(modfn) != 0)
+ return (NULL);
+ if ((dlh = dlopen(modfn, RTLD_NOW)) == NULL) {
+ openpam_log(PAM_LOG_ERROR, "%s: %s", modfn, dlerror());
+ errno = 0;
return (NULL);
- return (dlopen(modfn, RTLD_NOW));
+ }
+ return (dlh);
}
-
+#endif
+
/*
* OpenPAM internal
*
@@ -100,9 +136,6 @@ openpam_dynamic(const char *path)
*strrchr(vpath, '.') = '\0';
dlh = try_dlopen(vpath);
}
- serrno = errno;
- FREE(vpath);
- errno = serrno;
if (dlh == NULL)
goto err;
if ((module = calloc(1, sizeof *module)) == NULL)
@@ -112,19 +145,41 @@ openpam_dynamic(const char *path)
module->dlh = dlh;
dlmodule = dlsym(dlh, "_pam_module");
for (i = 0; i < PAM_NUM_PRIMITIVES; ++i) {
- module->func[i] = dlmodule ? dlmodule->func[i] :
- (pam_func_t)dlsym(dlh, pam_sm_func_name[i]);
- if (module->func[i] == NULL)
- openpam_log(PAM_LOG_DEBUG, "%s: %s(): %s",
- path, pam_sm_func_name[i], dlerror());
+ if (dlmodule) {
+ module->func[i] = dlmodule->func[i];
+ } else {
+ module->func[i] =
+ (pam_func_t)dlsym(dlh, pam_sm_func_name[i]);
+ /*
+ * This openpam_log() call is a major source of
+ * log spam, and the cases that matter are caught
+ * and logged in openpam_dispatch(). This would
+ * be less problematic if dlerror() returned an
+ * error code so we could log an error only when
+ * dlsym() failed for a reason other than "no such
+ * symbol".
+ */
+#if 0
+ if (module->func[i] == NULL)
+ openpam_log(PAM_LOG_DEBUG, "%s: %s(): %s",
+ path, pam_sm_func_name[i], dlerror());
+#endif
+ }
}
+ FREE(vpath);
return (module);
buf_err:
+ serrno = errno;
if (dlh != NULL)
dlclose(dlh);
FREE(module);
+ errno = serrno;
err:
- openpam_log(PAM_LOG_ERROR, "%m");
+ serrno = errno;
+ if (errno != 0)
+ openpam_log(PAM_LOG_ERROR, "%s: %m", vpath);
+ FREE(vpath);
+ errno = serrno;
return (NULL);
}
diff --git a/contrib/openpam/lib/openpam_features.c b/contrib/openpam/lib/openpam_features.c
new file mode 100644
index 0000000..586fc2a
--- /dev/null
+++ b/contrib/openpam/lib/openpam_features.c
@@ -0,0 +1,69 @@
+/*-
+ * Copyright (c) 2012 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
+ * in this position and unchanged.
+ * 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.
+ *
+ * $Id: openpam_features.c 608 2012-05-17 16:00:13Z des $
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <security/pam_appl.h>
+
+#include "openpam_impl.h"
+
+#define STRUCT_OPENPAM_FEATURE(name, descr, dflt) \
+ [OPENPAM_##name] = { \
+ "OPENPAM_" #name, \
+ descr, \
+ dflt \
+ }
+
+struct openpam_feature openpam_features[OPENPAM_NUM_FEATURES] = {
+ STRUCT_OPENPAM_FEATURE(
+ RESTRICT_SERVICE_NAME,
+ "Disallow path separators in service names",
+ 1
+ ),
+ STRUCT_OPENPAM_FEATURE(
+ VERIFY_POLICY_FILE,
+ "Verify ownership and permissions of policy files",
+ 1
+ ),
+ STRUCT_OPENPAM_FEATURE(
+ RESTRICT_MODULE_NAME,
+ "Disallow path separators in module names",
+ 0
+ ),
+ STRUCT_OPENPAM_FEATURE(
+ VERIFY_MODULE_FILE,
+ "Verify ownership and permissions of module files",
+ 1
+ ),
+};
diff --git a/contrib/openpam/lib/openpam_features.h b/contrib/openpam/lib/openpam_features.h
new file mode 100644
index 0000000..227b1a9
--- /dev/null
+++ b/contrib/openpam/lib/openpam_features.h
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 2012 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
+ * in this position and unchanged.
+ * 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.
+ *
+ * $Id$
+ */
+
+#ifndef OPENPAM_FEATURES_H_INCLUDED
+#define OPENPAM_FEATURES_H_INCLUDED
+
+struct openpam_feature {
+ const char *name;
+ const char *desc;
+ int onoff;
+};
+
+extern struct openpam_feature openpam_features[OPENPAM_NUM_FEATURES];
+
+/* shortcut for internal use */
+#define OPENPAM_FEATURE(f) \
+ openpam_features[OPENPAM_##f].onoff
+
+#endif
diff --git a/contrib/openpam/lib/openpam_get_feature.c b/contrib/openpam/lib/openpam_get_feature.c
new file mode 100644
index 0000000..b552357
--- /dev/null
+++ b/contrib/openpam/lib/openpam_get_feature.c
@@ -0,0 +1,99 @@
+/*-
+ * Copyright (c) 2012 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
+ * in this position and unchanged.
+ * 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.
+ *
+ * $Id: openpam_get_feature.c 608 2012-05-17 16:00:13Z des $
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <security/pam_appl.h>
+#include <security/openpam.h>
+
+#include "openpam_impl.h"
+
+/*
+ * OpenPAM extension
+ *
+ * Query the state of an optional feature.
+ */
+
+int
+openpam_get_feature(int feature, int *onoff)
+{
+
+ ENTERF(feature);
+ if (feature < 0 || feature >= OPENPAM_NUM_FEATURES)
+ RETURNC(PAM_SYMBOL_ERR);
+ *onoff = openpam_features[feature].onoff;
+ RETURNC(PAM_SUCCESS);
+}
+
+/*
+ * Error codes:
+ *
+ * PAM_SYMBOL_ERR
+ */
+
+/**
+ * EXPERIMENTAL
+ *
+ * The =openpam_get_feature function stores the current state of the
+ * specified feature in the variable pointed to by its =onoff argument.
+ *
+ * The following features are recognized:
+ *
+ * =OPENPAM_RESTRICT_SERVICE_NAME:
+ * Disallow path separators in service names.
+ * This feature is enabled by default.
+ * Disabling it allows the application to specify the path to
+ * the desired policy file directly.
+ *
+ * =OPENPAM_VERIFY_POLICY_FILE:
+ * Verify the ownership and permissions of the policy file
+ * and the path leading up to it.
+ * This feature is enabled by default.
+ *
+ * =OPENPAM_RESTRICT_MODULE_NAME:
+ * Disallow path separators in module names.
+ * This feature is disabled by default.
+ * Enabling it prevents the use of modules in non-standard
+ * locations.
+ *
+ * =OPENPAM_VERIFY_MODULE_FILE:
+ * Verify the ownership and permissions of each loadable
+ * module and the path leading up to it.
+ * This feature is enabled by default.
+ *
+ *
+ * >openpam_set_feature
+ *
+ * AUTHOR DES
+ */
diff --git a/contrib/openpam/lib/openpam_get_option.c b/contrib/openpam/lib/openpam_get_option.c
index b5faa87..1f62d21 100644
--- a/contrib/openpam/lib/openpam_get_option.c
+++ b/contrib/openpam/lib/openpam_get_option.c
@@ -32,7 +32,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: openpam_get_option.c 482 2011-11-03 16:33:02Z des $
+ * $Id: openpam_get_option.c 531 2012-03-31 14:24:37Z des $
*/
#ifdef HAVE_CONFIG_H
@@ -44,7 +44,6 @@
#include <string.h>
#include <security/pam_appl.h>
-#include <security/openpam.h>
#include "openpam_impl.h"
diff --git a/contrib/openpam/lib/openpam_impl.h b/contrib/openpam/lib/openpam_impl.h
index ba4d455..9e8b45f 100644
--- a/contrib/openpam/lib/openpam_impl.h
+++ b/contrib/openpam/lib/openpam_impl.h
@@ -32,7 +32,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: openpam_impl.h 499 2011-11-22 11:51:50Z des $
+ * $Id: openpam_impl.h 594 2012-04-14 14:18:41Z des $
*/
#ifndef OPENPAM_IMPL_H_INCLUDED
@@ -157,9 +157,23 @@ pam_module_t *openpam_static(const char *);
#endif
pam_module_t *openpam_dynamic(const char *);
-#define FREE(p) do { free((p)); (p) = NULL; } while (0)
+#define FREE(p) \
+ do { \
+ free(p); \
+ (p) = NULL; \
+ } while (0)
+
+#define FREEV(c, v) \
+ do { \
+ while (c) { \
+ --(c); \
+ FREE((v)[(c)]); \
+ } \
+ FREE(v); \
+ } while (0)
#include "openpam_constants.h"
#include "openpam_debug.h"
+#include "openpam_features.h"
#endif
diff --git a/contrib/openpam/lib/openpam_load.c b/contrib/openpam/lib/openpam_load.c
index 0eb8ea7..871d1a8 100644
--- a/contrib/openpam/lib/openpam_load.c
+++ b/contrib/openpam/lib/openpam_load.c
@@ -32,7 +32,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: openpam_load.c 491 2011-11-12 00:12:32Z des $
+ * $Id: openpam_load.c 547 2012-04-01 15:01:21Z des $
*/
#ifdef HAVE_CONFIG_H
@@ -108,9 +108,7 @@ openpam_destroy_chain(pam_chain_t *chain)
return;
openpam_destroy_chain(chain->next);
chain->next = NULL;
- while (chain->optc--)
- FREE(chain->optv[chain->optc]);
- FREE(chain->optv);
+ FREEV(chain->optc, chain->optv);
openpam_release_module(chain->module);
chain->module = NULL;
FREE(chain);
diff --git a/contrib/openpam/lib/openpam_log.c b/contrib/openpam/lib/openpam_log.c
index 9e3d28b..2b89f6c 100644
--- a/contrib/openpam/lib/openpam_log.c
+++ b/contrib/openpam/lib/openpam_log.c
@@ -32,18 +32,17 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: openpam_log.c 437 2011-09-13 12:00:13Z des $
+ * $Id: openpam_log.c 544 2012-03-31 22:47:15Z des $
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
-#include <ctype.h>
+#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
#include <syslog.h>
#include <security/pam_appl.h>
@@ -71,6 +70,7 @@ openpam_log(int level, const char *fmt, ...)
int priority;
switch (level) {
+ case PAM_LOG_LIBDEBUG:
case PAM_LOG_DEBUG:
if (!openpam_debug)
return;
@@ -100,8 +100,10 @@ _openpam_log(int level, const char *func, const char *fmt, ...)
va_list ap;
char *format;
int priority;
+ int serrno;
switch (level) {
+ case PAM_LOG_LIBDEBUG:
case PAM_LOG_DEBUG:
if (!openpam_debug)
return;
@@ -119,10 +121,13 @@ _openpam_log(int level, const char *func, const char *fmt, ...)
break;
}
va_start(ap, fmt);
+ serrno = errno;
if (asprintf(&format, "in %s(): %s", func, fmt) > 0) {
+ errno = serrno;
vsyslog(priority, format, ap);
FREE(format);
} else {
+ errno = serrno;
vsyslog(priority, fmt, ap);
}
va_end(ap);
@@ -137,6 +142,9 @@ _openpam_log(int level, const char *func, const char *fmt, ...)
* The =level argument indicates the importance of the message.
* The following levels are defined:
*
+ * =PAM_LOG_LIBDEBUG:
+ * Debugging messages.
+ * For internal use only.
* =PAM_LOG_DEBUG:
* Debugging messages.
* These messages are normally not logged unless the global
diff --git a/contrib/openpam/lib/openpam_readline.c b/contrib/openpam/lib/openpam_readline.c
index 9cc8cc1..014acfb 100644
--- a/contrib/openpam/lib/openpam_readline.c
+++ b/contrib/openpam/lib/openpam_readline.c
@@ -32,7 +32,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: openpam_readline.c 473 2011-11-03 10:48:25Z des $
+ * $Id: openpam_readline.c 596 2012-04-14 14:52:40Z des $
*/
#ifdef HAVE_CONFIG_H
@@ -44,6 +44,7 @@
#include <stdlib.h>
#include <security/pam_appl.h>
+
#include "openpam_impl.h"
#define MIN_LINE_LENGTH 128
@@ -61,22 +62,11 @@ openpam_readline(FILE *f, int *lineno, size_t *lenp)
size_t len, size;
int ch;
- if ((line = malloc(MIN_LINE_LENGTH)) == NULL)
+ if ((line = malloc(size = MIN_LINE_LENGTH)) == NULL) {
+ openpam_log(PAM_LOG_ERROR, "malloc(): %m");
return (NULL);
- size = MIN_LINE_LENGTH;
+ }
len = 0;
-
-#define line_putch(ch) do { \
- if (len >= size - 1) { \
- char *tmp = realloc(line, size *= 2); \
- if (tmp == NULL) \
- goto fail; \
- line = tmp; \
- } \
- line[len++] = ch; \
- line[len] = '\0'; \
-} while (0)
-
for (;;) {
ch = fgetc(f);
/* strip comment */
@@ -105,26 +95,15 @@ openpam_readline(FILE *f, int *lineno, size_t *lenp)
/* done */
break;
}
- /* whitespace */
- if (isspace(ch)) {
- /* ignore leading whitespace */
- /* collapse linear whitespace */
- if (len > 0 && line[len - 1] != ' ')
- line_putch(' ');
- continue;
- }
/* anything else */
- line_putch(ch);
+ if (openpam_straddch(&line, &size, &len, ch) != 0)
+ goto fail;
}
-
- /* remove trailing whitespace */
- while (len > 0 && isspace((unsigned char)line[len - 1]))
- --len;
- line[len] = '\0';
if (len == 0)
goto fail;
if (lenp != NULL)
*lenp = len;
+ openpam_log(PAM_LOG_LIBDEBUG, "returning '%s'", line);
return (line);
fail:
FREE(line);
@@ -132,16 +111,18 @@ fail:
}
/**
+ * DEPRECATED openpam_readlinev
+ *
* The =openpam_readline function reads a line from a file, and returns it
- * in a NUL-terminated buffer allocated with =malloc.
+ * in a NUL-terminated buffer allocated with =!malloc.
*
* The =openpam_readline function performs a certain amount of processing
* on the data it reads:
*
- * - Comments (introduced by a hash sign) are stripped, as is leading and
- * trailing whitespace.
- * - Any amount of linear whitespace is collapsed to a single space.
+ * - Comments (introduced by a hash sign) are stripped.
+ *
* - Blank lines are ignored.
+ *
* - If a line ends in a backslash, the backslash is stripped and the
* next line is appended.
*
@@ -152,5 +133,8 @@ fail:
* terminating NUL character) is stored in the variable it points to.
*
* The caller is responsible for releasing the returned buffer by passing
- * it to =free.
+ * it to =!free.
+ *
+ * >openpam_readlinev
+ * >openpam_readword
*/
diff --git a/contrib/openpam/lib/openpam_readlinev.c b/contrib/openpam/lib/openpam_readlinev.c
new file mode 100644
index 0000000..5a43b61
--- /dev/null
+++ b/contrib/openpam/lib/openpam_readlinev.c
@@ -0,0 +1,156 @@
+/*-
+ * Copyright (c) 2012 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
+ * in this position and unchanged.
+ * 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.
+ *
+ * $Id: openpam_readlinev.c 588 2012-04-08 11:52:25Z des $
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <security/pam_appl.h>
+
+#include "openpam_impl.h"
+
+#define MIN_WORDV_SIZE 32
+
+/*
+ * OpenPAM extension
+ *
+ * Read a line from a file and split it into words.
+ */
+
+char **
+openpam_readlinev(FILE *f, int *lineno, int *lenp)
+{
+ char *word, **wordv, **tmp;
+ size_t wordlen, wordvsize;
+ int ch, serrno, wordvlen;
+
+ wordvsize = MIN_WORDV_SIZE;
+ wordvlen = 0;
+ if ((wordv = malloc(wordvsize * sizeof *wordv)) == NULL) {
+ openpam_log(PAM_LOG_ERROR, "malloc(): %m");
+ errno = ENOMEM;
+ return (NULL);
+ }
+ wordv[wordvlen] = NULL;
+ while ((word = openpam_readword(f, lineno, &wordlen)) != NULL) {
+ if ((unsigned int)wordvlen + 1 >= wordvsize) {
+ /* need to expand the array */
+ wordvsize *= 2;
+ tmp = realloc(wordv, wordvsize * sizeof *wordv);
+ if (tmp == NULL) {
+ openpam_log(PAM_LOG_ERROR, "malloc(): %m");
+ errno = ENOMEM;
+ break;
+ }
+ wordv = tmp;
+ }
+ /* insert our word */
+ wordv[wordvlen++] = word;
+ wordv[wordvlen] = NULL;
+ }
+ if (errno != 0) {
+ /* I/O error or out of memory */
+ serrno = errno;
+ while (wordvlen--)
+ free(wordv[wordvlen]);
+ free(wordv);
+ errno = serrno;
+ return (NULL);
+ }
+ /* assert(!ferror(f)) */
+ ch = fgetc(f);
+ /* assert(ch == EOF || ch == '\n') */
+ if (ch == EOF && wordvlen == 0) {
+ free(wordv);
+ return (NULL);
+ }
+ if (ch == '\n' && lineno != NULL)
+ ++*lineno;
+ if (lenp != NULL)
+ *lenp = wordvlen;
+ return (wordv);
+}
+
+/**
+ * The =openpam_readlinev function reads a line from a file, splits it
+ * into words according to the rules described in the =openpam_readword
+ * manual page, and returns a list of those words.
+ *
+ * If =lineno is not =NULL, the integer variable it points to is
+ * incremented every time a newline character is read.
+ * This includes quoted or escaped newline characters and the newline
+ * character at the end of the line.
+ *
+ * If =lenp is not =NULL, the number of words on the line is stored in the
+ * variable to which it points.
+ *
+ * RETURN VALUES
+ *
+ * If successful, the =openpam_readlinev function returns a pointer to a
+ * dynamically allocated array of pointers to individual dynamically
+ * allocated NUL-terminated strings, each containing a single word, in the
+ * order in which they were encountered on the line.
+ * The array is terminated by a =NULL pointer.
+ *
+ * The caller is responsible for freeing both the array and the individual
+ * strings by passing each of them to =!free.
+ *
+ * If the end of the line was reached before any words were read,
+ * =openpam_readlinev returns a pointer to a dynamically allocated array
+ * containing a single =NULL pointer.
+ *
+ * The =openpam_readlinev function can fail and return =NULL for one of
+ * four reasons:
+ *
+ * - The end of the file was reached before any words were read; :errno is
+ * zero, =!ferror returns zero, and =!feof returns a non-zero value.
+ *
+ * - The end of the file was reached while a quote or backslash escape
+ * was in effect; :errno is set to =EINVAL, =!ferror returns zero, and
+ * =!feof returns a non-zero value.
+ *
+ * - An error occurred while reading from the file; :errno is non-zero,
+ * =!ferror returns a non-zero value and =!feof returns zero.
+ *
+ * - A =!malloc or =!realloc call failed; :errno is set to =ENOMEM,
+ * =!ferror returns a non-zero value, and =!feof may or may not return
+ * a non-zero value.
+ *
+ * >openpam_readline
+ * >openpam_readword
+ *
+ * AUTHOR DES
+ */
diff --git a/contrib/openpam/lib/openpam_readword.c b/contrib/openpam/lib/openpam_readword.c
new file mode 100644
index 0000000..74a4d46
--- /dev/null
+++ b/contrib/openpam/lib/openpam_readword.c
@@ -0,0 +1,207 @@
+/*-
+ * Copyright (c) 2012 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
+ * in this position and unchanged.
+ * 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.
+ *
+ * $Id: openpam_readword.c 588 2012-04-08 11:52:25Z des $
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <security/pam_appl.h>
+
+#include "openpam_impl.h"
+#include "openpam_ctype.h"
+
+#define MIN_WORD_SIZE 32
+
+/*
+ * OpenPAM extension
+ *
+ * Read a word from a file, respecting shell quoting rules.
+ */
+
+char *
+openpam_readword(FILE *f, int *lineno, size_t *lenp)
+{
+ char *word;
+ size_t size, len;
+ int ch, comment, escape, quote;
+ int serrno;
+
+ errno = 0;
+
+ /* skip initial whitespace */
+ comment = 0;
+ while ((ch = getc(f)) != EOF && ch != '\n') {
+ if (ch == '#')
+ comment = 1;
+ if (!is_lws(ch) && !comment)
+ break;
+ }
+ if (ch == EOF)
+ return (NULL);
+ ungetc(ch, f);
+ if (ch == '\n')
+ return (NULL);
+
+ word = NULL;
+ size = len = 0;
+ escape = quote = 0;
+ while ((ch = fgetc(f)) != EOF && (!is_ws(ch) || quote || escape)) {
+ if (ch == '\\' && !escape && quote != '\'') {
+ /* escape next character */
+ escape = ch;
+ } else if ((ch == '\'' || ch == '"') && !quote && !escape) {
+ /* begin quote */
+ quote = ch;
+ /* edge case: empty quoted string */
+ if (word == NULL && (word = malloc(1)) == NULL) {
+ openpam_log(PAM_LOG_ERROR, "malloc(): %m");
+ errno = ENOMEM;
+ return (NULL);
+ }
+ *word = '\0';
+ size = 1;
+ } else if (ch == quote && !escape) {
+ /* end quote */
+ quote = 0;
+ } else if (ch == '\n' && escape && quote != '\'') {
+ /* line continuation */
+ escape = 0;
+ } else {
+ if (escape && quote && ch != '\\' && ch != quote &&
+ openpam_straddch(&word, &size, &len, '\\') != 0) {
+ free(word);
+ errno = ENOMEM;
+ return (NULL);
+ }
+ if (openpam_straddch(&word, &size, &len, ch) != 0) {
+ free(word);
+ errno = ENOMEM;
+ return (NULL);
+ }
+ escape = 0;
+ }
+ if (lineno != NULL && ch == '\n')
+ ++*lineno;
+ }
+ if (ch == EOF && ferror(f)) {
+ serrno = errno;
+ free(word);
+ errno = serrno;
+ return (NULL);
+ }
+ if (ch == EOF && (escape || quote)) {
+ /* Missing escaped character or closing quote. */
+ openpam_log(PAM_LOG_ERROR, "unexpected end of file");
+ free(word);
+ errno = EINVAL;
+ return (NULL);
+ }
+ ungetc(ch, f);
+ if (lenp != NULL)
+ *lenp = len;
+ return (word);
+}
+
+/**
+ * The =openpam_readword function reads the next word from a file, and
+ * returns it in a NUL-terminated buffer allocated with =!malloc.
+ *
+ * A word is a sequence of non-whitespace characters.
+ * However, whitespace characters can be included in a word if quoted or
+ * escaped according to the following rules:
+ *
+ * - An unescaped single or double quote introduces a quoted string,
+ * which ends when the same quote character is encountered a second
+ * time.
+ * The quotes themselves are stripped.
+ *
+ * - Within a single- or double-quoted string, all whitespace characters,
+ * including the newline character, are preserved as-is.
+ *
+ * - Outside a quoted string, a backslash escapes the next character,
+ * which is preserved as-is, unless that character is a newline, in
+ * which case it is discarded and reading continues at the beginning of
+ * the next line as if the backslash and newline had not been there.
+ * In all cases, the backslash itself is discarded.
+ *
+ * - Within a single-quoted string, double quotes and backslashes are
+ * preserved as-is.
+ *
+ * - Within a double-quoted string, a single quote is preserved as-is,
+ * and a backslash is preserved as-is unless used to escape a double
+ * quote.
+ *
+ * In addition, if the first non-whitespace character on the line is a
+ * hash character (#), the rest of the line is discarded.
+ * If a hash character occurs within a word, however, it is preserved
+ * as-is.
+ * A backslash at the end of a comment does cause line continuation.
+ *
+ * If =lineno is not =NULL, the integer variable it points to is
+ * incremented every time a quoted or escaped newline character is read.
+ *
+ * If =lenp is not =NULL, the length of the word (after quotes and
+ * backslashes have been removed) is stored in the variable it points to.
+ *
+ * RETURN VALUES
+ *
+ * If successful, the =openpam_readword function returns a pointer to a
+ * dynamically allocated NUL-terminated string containing the first word
+ * encountered on the line.
+ *
+ * The caller is responsible for releasing the returned buffer by passing
+ * it to =!free.
+ *
+ * If =openpam_readword reaches the end of the line or file before any
+ * characters are copied to the word, it returns =NULL. In the former
+ * case, the newline is pushed back to the file.
+ *
+ * If =openpam_readword reaches the end of the file while a quote or
+ * backslash escape is in effect, it sets :errno to =EINVAL and returns
+ * =NULL.
+ *
+ * IMPLEMENTATION NOTES
+ *
+ * The parsing rules are intended to be equivalent to the normal POSIX
+ * shell quoting rules.
+ * Any discrepancy is a bug and should be reported to the author along
+ * with sample input that can be used to reproduce the error.
+ *
+ * >openpam_readline
+ * >openpam_readlinev
+ *
+ * AUTHOR DES
+ */
diff --git a/contrib/openpam/lib/openpam_set_feature.c b/contrib/openpam/lib/openpam_set_feature.c
new file mode 100644
index 0000000..4f6a4a5
--- /dev/null
+++ b/contrib/openpam/lib/openpam_set_feature.c
@@ -0,0 +1,75 @@
+/*-
+ * Copyright (c) 2012 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
+ * in this position and unchanged.
+ * 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.
+ *
+ * $Id: openpam_set_feature.c 608 2012-05-17 16:00:13Z des $
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <security/pam_appl.h>
+#include <security/openpam.h>
+
+#include "openpam_impl.h"
+
+/*
+ * OpenPAM extension
+ *
+ * Enable or disable an optional feature.
+ */
+
+int
+openpam_set_feature(int feature, int onoff)
+{
+
+ ENTERF(feature);
+ if (feature < 0 || feature >= OPENPAM_NUM_FEATURES)
+ RETURNC(PAM_SYMBOL_ERR);
+ openpam_features[feature].onoff = onoff;
+ RETURNC(PAM_SUCCESS);
+}
+
+/*
+ * Error codes:
+ *
+ * PAM_SYMBOL_ERR
+ */
+
+/**
+ * EXPERIMENTAL
+ *
+ * The =openpam_set_feature function sets the state of the specified
+ * feature to the value specified by the =onoff argument.
+ * See =openpam_get_feature for a list of recognized features.
+ *
+ * >openpam_get_feature
+ *
+ * AUTHOR DES
+ */
diff --git a/contrib/openpam/lib/openpam_set_option.c b/contrib/openpam/lib/openpam_set_option.c
index c7cb1c7..1712a71 100644
--- a/contrib/openpam/lib/openpam_set_option.c
+++ b/contrib/openpam/lib/openpam_set_option.c
@@ -32,7 +32,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: openpam_set_option.c 482 2011-11-03 16:33:02Z des $
+ * $Id: openpam_set_option.c 532 2012-03-31 14:24:53Z des $
*/
#ifdef HAVE_CONFIG_H
@@ -46,7 +46,6 @@
#include <string.h>
#include <security/pam_appl.h>
-#include <security/openpam.h>
#include "openpam_impl.h"
diff --git a/contrib/openpam/lib/openpam_straddch.c b/contrib/openpam/lib/openpam_straddch.c
new file mode 100644
index 0000000..9845cc6
--- /dev/null
+++ b/contrib/openpam/lib/openpam_straddch.c
@@ -0,0 +1,111 @@
+/*-
+ * Copyright (c) 2012 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
+ * in this position and unchanged.
+ * 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.
+ *
+ * $Id: openpam_straddch.c 568 2012-04-05 14:35:53Z des $
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <errno.h>
+#include <stdlib.h>
+
+#include <security/pam_appl.h>
+
+#include "openpam_impl.h"
+
+#define MIN_STR_SIZE 32
+
+/*
+ * OpenPAM extension
+ *
+ * Add a character to a string, expanding the buffer if needed.
+ */
+
+int
+openpam_straddch(char **str, size_t *size, size_t *len, int ch)
+{
+ size_t tmpsize;
+ char *tmpstr;
+
+ if (*str == NULL) {
+ /* initial allocation */
+ tmpsize = MIN_STR_SIZE;
+ if ((tmpstr = malloc(tmpsize)) == NULL) {
+ openpam_log(PAM_LOG_ERROR, "malloc(): %m");
+ errno = ENOMEM;
+ return (-1);
+ }
+ *str = tmpstr;
+ *size = tmpsize;
+ *len = 0;
+ } else if (*len + 1 >= *size) {
+ /* additional space required */
+ tmpsize = *size * 2;
+ if ((tmpstr = realloc(*str, tmpsize)) == NULL) {
+ openpam_log(PAM_LOG_ERROR, "realloc(): %m");
+ errno = ENOMEM;
+ return (-1);
+ }
+ *size = tmpsize;
+ *str = tmpstr;
+ }
+ (*str)[*len] = ch;
+ ++*len;
+ (*str)[*len] = '\0';
+ return (0);
+}
+
+/**
+ * The =openpam_straddch function appends a character to a dynamically
+ * allocated NUL-terminated buffer, reallocating the buffer as needed.
+ *
+ * The =str argument points to a variable containing either a pointer to
+ * an existing buffer or =NULL.
+ * If the value of the variable pointed to by =str is =NULL, a new buffer
+ * is allocated.
+ *
+ * The =size and =len argument point to variables used to hold the size
+ * of the buffer and the length of the string it contains, respectively.
+ *
+ * If a new buffer is allocated or an existing buffer is reallocated to
+ * make room for the additional character, =str and =size are updated
+ * accordingly.
+ *
+ * The =openpam_straddch function ensures that the buffer is always
+ * NUL-terminated.
+ *
+ * If the =openpam_straddch function is successful, it increments the
+ * integer variable pointed to by =len and returns 0.
+ * Otherwise, it leaves the variables pointed to by =str, =size and =len
+ * unmodified, sets :errno to =ENOMEM and returns -1.
+ *
+ * AUTHOR DES
+ */
diff --git a/contrib/openpam/lib/openpam_strlcat.h b/contrib/openpam/lib/openpam_strlcat.h
new file mode 100644
index 0000000..1f26693
--- /dev/null
+++ b/contrib/openpam/lib/openpam_strlcat.h
@@ -0,0 +1,54 @@
+/*-
+ * Copyright (c) 2011 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
+ * in this position and unchanged.
+ * 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.
+ *
+ * $Id: openpam_strlcat.h 578 2012-04-06 00:45:59Z des $
+ */
+
+#ifndef OPENPAM_STRLCAT_H_INCLUDED
+#define OPENPAM_STRLCAT_H_INCLUDED
+
+#ifndef HAVE_STRLCAT
+/* like strcat(3), but always NUL-terminates; returns strlen(src) */
+static size_t
+strlcat(char *dst, const char *src, size_t size)
+{
+ size_t len;
+
+ for (len = 0; *dst && size > 1; ++len, --size)
+ dst++;
+ for (; *src && size > 1; ++len, --size)
+ *dst++ = *src++;
+ *dst = '\0';
+ while (*src)
+ ++len, ++src;
+ return (len);
+}
+#endif
+
+#endif
diff --git a/contrib/openpam/lib/openpam_strlcmp.h b/contrib/openpam/lib/openpam_strlcmp.h
index c692225..2a78e0f 100644
--- a/contrib/openpam/lib/openpam_strlcmp.h
+++ b/contrib/openpam/lib/openpam_strlcmp.h
@@ -11,6 +11,9 @@
* 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
@@ -24,7 +27,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: openpam_strlcmp.h 475 2011-11-03 15:29:24Z des $
+ * $Id: openpam_strlcmp.h 578 2012-04-06 00:45:59Z des $
*/
#ifndef OPENPAM_STRLCMP_H_INCLUDED
diff --git a/contrib/openpam/lib/openpam_strlcpy.h b/contrib/openpam/lib/openpam_strlcpy.h
index 921653b..9c65548 100644
--- a/contrib/openpam/lib/openpam_strlcpy.h
+++ b/contrib/openpam/lib/openpam_strlcpy.h
@@ -11,6 +11,9 @@
* 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
@@ -24,7 +27,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: openpam_strlcpy.h 492 2011-11-20 02:04:17Z des $
+ * $Id: openpam_strlcpy.h 578 2012-04-06 00:45:59Z des $
*/
#ifndef OPENPAM_STRLCPY_H_INCLUDED
@@ -32,7 +35,7 @@
#ifndef HAVE_STRLCPY
/* like strcpy(3), but always NUL-terminates; returns strlen(src) */
-size_t
+static size_t
strlcpy(char *dst, const char *src, size_t size)
{
size_t len;
diff --git a/contrib/openpam/lib/openpam_subst.c b/contrib/openpam/lib/openpam_subst.c
index d54b827..bab7a78 100644
--- a/contrib/openpam/lib/openpam_subst.c
+++ b/contrib/openpam/lib/openpam_subst.c
@@ -11,6 +11,9 @@
* 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
@@ -24,7 +27,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: openpam_subst.c 461 2011-11-02 14:00:38Z des $
+ * $Id: openpam_subst.c 543 2012-03-31 22:11:34Z des $
*/
#ifdef HAVE_CONFIG_H
diff --git a/contrib/openpam/lib/openpam_ttyconv.c b/contrib/openpam/lib/openpam_ttyconv.c
index ec078f4..14a324d 100644
--- a/contrib/openpam/lib/openpam_ttyconv.c
+++ b/contrib/openpam/lib/openpam_ttyconv.c
@@ -32,7 +32,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: openpam_ttyconv.c 437 2011-09-13 12:00:13Z des $
+ * $Id: openpam_ttyconv.c 527 2012-02-26 03:23:59Z des $
*/
#ifdef HAVE_CONFIG_H
@@ -69,17 +69,17 @@ prompt(const char *msg)
{
char buf[PAM_MAX_RESP_SIZE];
struct sigaction action, saved_action;
- sigset_t saved_sigset, sigset;
+ sigset_t saved_sigset, the_sigset;
unsigned int saved_alarm;
int eof, error, fd;
size_t len;
char *retval;
char ch;
- sigemptyset(&sigset);
- sigaddset(&sigset, SIGINT);
- sigaddset(&sigset, SIGTSTP);
- sigprocmask(SIG_SETMASK, &sigset, &saved_sigset);
+ sigemptyset(&the_sigset);
+ sigaddset(&the_sigset, SIGINT);
+ sigaddset(&the_sigset, SIGTSTP);
+ sigprocmask(SIG_SETMASK, &the_sigset, &saved_sigset);
action.sa_handler = &timeout;
action.sa_flags = 0;
sigemptyset(&action.sa_mask);
diff --git a/contrib/openpam/lib/pam_get_authtok.c b/contrib/openpam/lib/pam_get_authtok.c
index a0613ef..1a3aebc 100644
--- a/contrib/openpam/lib/pam_get_authtok.c
+++ b/contrib/openpam/lib/pam_get_authtok.c
@@ -32,7 +32,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: pam_get_authtok.c 455 2011-10-29 18:31:11Z des $
+ * $Id: pam_get_authtok.c 510 2011-12-31 13:14:23Z des $
*/
#ifdef HAVE_CONFIG_H
@@ -50,6 +50,7 @@
#include "openpam_impl.h"
static const char authtok_prompt[] = "Password:";
+static const char authtok_prompt_remote[] = "Password for %u@%h:";
static const char oldauthtok_prompt[] = "Old Password:";
static const char newauthtok_prompt[] = "New Password:";
@@ -69,6 +70,7 @@ pam_get_authtok(pam_handle_t *pamh,
size_t prompt_size;
const void *oldauthtok, *prevauthtok, *promptp;
const char *prompt_option, *default_prompt;
+ const void *lhost, *rhost;
char *resp, *resp2;
int pitem, r, style, twice;
@@ -82,6 +84,14 @@ pam_get_authtok(pam_handle_t *pamh,
pitem = PAM_AUTHTOK_PROMPT;
prompt_option = "authtok_prompt";
default_prompt = authtok_prompt;
+ r = pam_get_item(pamh, PAM_RHOST, &rhost);
+ if (r == PAM_SUCCESS && rhost != NULL) {
+ r = pam_get_item(pamh, PAM_HOST, &lhost);
+ if (r == PAM_SUCCESS && lhost != NULL) {
+ if (strcmp(rhost, lhost) != 0)
+ default_prompt = authtok_prompt_remote;
+ }
+ }
r = pam_get_item(pamh, PAM_OLDAUTHTOK, &oldauthtok);
if (r == PAM_SUCCESS && oldauthtok != NULL) {
default_prompt = newauthtok_prompt;
diff --git a/contrib/openpam/lib/pam_putenv.c b/contrib/openpam/lib/pam_putenv.c
index 369066d..e1f0bc3 100644
--- a/contrib/openpam/lib/pam_putenv.c
+++ b/contrib/openpam/lib/pam_putenv.c
@@ -32,7 +32,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: pam_putenv.c 437 2011-09-13 12:00:13Z des $
+ * $Id: pam_putenv.c 539 2012-03-31 20:53:22Z des $
*/
#ifdef HAVE_CONFIG_H
@@ -102,7 +102,7 @@ pam_putenv(pam_handle_t *pamh,
*/
/**
- * The =pam_putenv function sets a environment variable.
+ * The =pam_putenv function sets an environment variable.
* Its semantics are similar to those of =putenv, but it modifies the PAM
* context's environment list instead of the application's.
*
diff --git a/contrib/openpam/lib/pam_setenv.c b/contrib/openpam/lib/pam_setenv.c
index fbe6a8f..6fd4c10 100644
--- a/contrib/openpam/lib/pam_setenv.c
+++ b/contrib/openpam/lib/pam_setenv.c
@@ -32,7 +32,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: pam_setenv.c 437 2011-09-13 12:00:13Z des $
+ * $Id: pam_setenv.c 539 2012-03-31 20:53:22Z des $
*/
#ifdef HAVE_CONFIG_H
@@ -92,7 +92,7 @@ pam_setenv(pam_handle_t *pamh,
*/
/**
- * The =pam_setenv function sets a environment variable.
+ * The =pam_setenv function sets an environment variable.
* Its semantics are similar to those of =setenv, but it modifies the PAM
* context's environment list instead of the application's.
*
OpenPOWER on IntegriCloud