summaryrefslogtreecommitdiffabout
authorSergey Poznyakoff <gray@gnu.org.ua>2008-03-13 13:53:32 (GMT)
committer Sergey Poznyakoff <gray@gnu.org.ua>2008-03-13 13:53:32 (GMT)
commit222d4ff80720206deeb8e7ee87831812628329af (patch) (side-by-side diff)
treeccf4a8ed8e19e8b9b1c33b6a27cb95f51b1ec256
parentf9f6f80133f16fb1fc6c064bee5fe5c53a17c9d8 (diff)
downloadpam-modules-222d4ff80720206deeb8e7ee87831812628329af.tar.gz
pam-modules-222d4ff80720206deeb8e7ee87831812628329af.tar.bz2
* configure.ac (PAM_COMMON_INCLUDES): Add -I${top_srcdir}/lib.
(AC_OUTPUT): Add lib/Makefile. * doc/pam-modules.texi: Document `transform' option. * Make.rules: New file. * lib/mem.c, lib/slist.c, lib/log.c, lib/converse.c, lib/graypam.h, lib/Makefile.am, lib/transform.c. * pam_regex/pam_regex.c: Implement user name transformations. * pam_fshadow/Makefile.am, pam_sql/Makefile.am: Add ../lib/libgraypam.la to LDADD * pam_fshadow/pam_fshadow.c, pam_sql/pam_mysql.c, pam_sql/pam_pgsql.c, pam_sql/pam_sql.c: Use functions from ../lib. git-svn-id: file:///svnroot/pam-modules/trunk@63 56984be4-0537-0410-a56c-fcb268c96130
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--ChangeLog17
-rw-r--r--Make.rules26
-rw-r--r--Makefile.am5
-rw-r--r--NEWS14
-rw-r--r--common.c150
-rw-r--r--configure.ac5
-rw-r--r--doc/pam-modules.texi80
-rw-r--r--lib/Makefile.am19
-rw-r--r--lib/converse.c49
-rw-r--r--lib/graypam.h149
-rw-r--r--lib/log.c79
-rw-r--r--lib/mem.c99
-rw-r--r--lib/slist.c244
-rw-r--r--lib/transform.c533
-rw-r--r--pam_fshadow/Makefile.am15
-rw-r--r--pam_fshadow/pam_fshadow.c97
-rw-r--r--pam_log/Makefile.am15
-rw-r--r--pam_log/pam_log.c79
-rw-r--r--pam_regex/Makefile.am18
-rw-r--r--pam_regex/pam_regex.c150
-rw-r--r--pam_sql/Makefile.am3
-rw-r--r--pam_sql/pam_mysql.c15
-rw-r--r--pam_sql/pam_pgsql.c15
-rw-r--r--pam_sql/pam_sql.c79
24 files changed, 1475 insertions, 480 deletions
diff --git a/ChangeLog b/ChangeLog
index e2fb656..80ebb18 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2008-03-13 Sergey Poznyakoff <gray@gnu.org.ua>
+
+ * configure.ac (PAM_COMMON_INCLUDES): Add -I${top_srcdir}/lib.
+ (AC_OUTPUT): Add lib/Makefile.
+ * doc/pam-modules.texi: Document `transform' option.
+ * Make.rules: New file.
+
+ * lib/mem.c, lib/slist.c, lib/log.c, lib/converse.c,
+ lib/graypam.h, lib/Makefile.am, lib/transform.c.
+
+ * pam_regex/pam_regex.c: Implement user name transformations.
+
+ * pam_fshadow/Makefile.am, pam_sql/Makefile.am:
+ Add ../lib/libgraypam.la to LDADD
+ * pam_fshadow/pam_fshadow.c, pam_sql/pam_mysql.c,
+ pam_sql/pam_pgsql.c, pam_sql/pam_sql.c: Use functions from ../lib.
+
2007-08-28 Sergey Poznyakoff <gray@gnu.org.ua>
* pam_fshadow/Makefile.am, pam_regex/Makefile.am,
diff --git a/Make.rules b/Make.rules
new file mode 100644
index 0000000..ecf28eb
--- a/dev/null
+++ b/Make.rules
@@ -0,0 +1,26 @@
+# Copyright (C) 2001, 2006, 2007 Sergey Poznyakoff
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see <http://www.gnu.org/licenses/>.
+
+.c.lo:
+ $(LIBTOOL) --mode=compile $(CC) -c -DHAVE_CONFIG_H \
+ $(CFLAGS) $(AM_CFLAGS) $(INCLUDES) $(CPPFLAGS) \
+ $(AM_CPPFLAGS) $<
+
+.lo.la:
+ $(LIBTOOL) --mode=link $(CC) -module -export-dynamic \
+ $(AM_LDFLAGS) \
+ -o $@ $< $(AM_LDADD) $(LDADD) \
+ -rpath $(pamdir) -shared
+
diff --git a/Makefile.am b/Makefile.am
index 0434695..7885d82 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,4 +1,4 @@
-# Copyright (C) 2001, 2006 Sergey Poznyakoff
+# Copyright (C) 2001, 2006, 2008 Sergey Poznyakoff
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -14,5 +14,4 @@
# with this program. If not, see <http://www.gnu.org/licenses/>.
AUTOMAKE_OPTIONS = gnits 1.8
-SUBDIRS = doc pam_fshadow pam_regex pam_log pam_sql
-EXTRA_DIST=common.c
+SUBDIRS = doc lib pam_fshadow pam_regex pam_log pam_sql
diff --git a/NEWS b/NEWS
index 763e42c..7b01934 100644
--- a/NEWS
+++ b/NEWS
@@ -1,12 +1,16 @@
-pam-modules -- history of user-visible changes. 2007-08-14
-Copyright (C) 2001,2004,2005,2007 Sergey Poznyakoff
+pam-modules -- history of user-visible changes. 2008-03-13
+Copyright (C) 2001,2004,2005,2007,2008 Sergey Poznyakoff
See the end of file for copying conditions.
Please send radius bug reports to <bug-pam-modules@gnu.org.ua>
-Version 1.2, CVS
+Version 1.2, SVN
-Several fixes in debugging code and pam_mysql, pam_pgsql modules.
+* Several fixes in debugging code and pam_mysql, pam_pgsql modules.
+
+* pam_regex transform=expr
+
+New command line option `transform' allows to rewrite user names.
Version 1.1, 2007-08-11
@@ -37,7 +41,7 @@ Version 0.1
=========================================================================
Copyright information:
-Copyright (C) 2001,2004,2005 Sergey Poznyakoff
+Copyright (C) 2001,2004,2005,2007,2008 Sergey Poznyakoff
Permission is granted to anyone to make or distribute verbatim copies
of this document as received, in any medium, provided that the
diff --git a/common.c b/common.c
deleted file mode 100644
index 6004929..0000000
--- a/common.c
+++ b/dev/null
@@ -1,150 +0,0 @@
-/* This file is part of pam-modules.
- Copyright (C) 2001, 2007 Sergey Poznyakoff
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 3 of the License, or (at your
- option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with this program. If not, see <http://www.gnu.org/licenses/>. */
-
-#ifndef PAM_CONV_AGAIN
-# define PAM_CONV_AGAIN PAM_TRY_AGAIN
-#endif
-#ifndef PAM_AUTHTOK_RECOVER_ERR
-# define PAM_AUTHTOK_RECOVER_ERR PAM_AUTHTOK_RECOVERY_ERR
-#endif
-#ifndef PAM_EXTERN
-# define PAM_EXTERN
-#endif
-
-#include <regex.h>
-
-#define XSTRDUP(s) (s) ? strdup(s) : NULL
-
-#define PAM_OVERWRITE(s) \
- do { \
- register char *p; \
- if ((p = s) != NULL) \
- while (*p) *p++ = 0; \
- } while (0)
-
-#define PAM_DROP_REPLY(reply, nrepl) \
- do { \
- int i; \
- for (i=0; i<nrepl; i++) { \
- PAM_OVERWRITE(reply[i].resp); \
- free(reply[i].resp); \
- } \
- if (reply) \
- free(reply); \
- } while (0)
-
-static void
-_pam_delete(char *x)
-{
- PAM_OVERWRITE(x);
- free(x);
-}
-
-static void
-_cleanup_string(pam_handle_t *pamh, void *x, int error_status)
-{
- _pam_delete(x);
-}
-
-static void
-_cleanup_regex(pam_handle_t *pamh, void *x, int error_status)
-{
- regfree((regex_t*)x);
-}
-
-static void _pam_log(int err, const char *format, ...);
-
-static void
-make_str(pam_handle_t *pamh, const char *str, const char *name, char **ret)
-{
- int retval;
- char *newstr = XSTRDUP(str);
-
- retval = pam_set_data(pamh, name, (void *)newstr, _cleanup_string);
- if (retval != PAM_SUCCESS) {
- _pam_log(LOG_CRIT,
- "can't keep data [%s]: %s",
- name,
- pam_strerror(pamh, retval));
- _pam_delete(newstr);
- } else {
- *ret = newstr;
- newstr = NULL;
- }
-}
-
-#define MAKE_STR(pamh, str, var) \
- make_str(pamh,str,#var,&var)
-
-/* Syslog functions */
-static int syslog_dont_open = 0;
-static const char *syslog_tag = MODULE_NAME;
-static int facility = LOG_AUTHPRIV;
-
-static void
-_pam_vlog(int err, const char *format, va_list args)
-{
- if (syslog_dont_open)
- err |= facility;
- else
- openlog(syslog_tag, LOG_CONS|LOG_PID, facility);
- vsyslog(err, format, args);
- if (!syslog_dont_open)
- closelog();
-}
-
-static void
-_pam_log(int err, const char *format, ...)
-{
- va_list args;
-
- va_start(args, format);
- _pam_vlog(err, format, args);
- va_end(args);
-}
-
-static void
-_pam_debug(const char *format, ...)
-{
- va_list args;
-
- va_start(args, format);
- _pam_vlog(LOG_DEBUG, format, args);
- va_end(args);
-}
-
-void
-wait_debug(size_t interval, const char *file, size_t line)
-{
-#ifdef DEBUG_MODE
- if (!interval)
- interval = 3600;
- _pam_log(LOG_CRIT, "WAITING FOR DEBUG AT %s:%d",
- file, (unsigned long)line);
- while (interval-- > 0)
- sleep(1);
-#else
- _pam_log(LOG_NOTICE, "Debugging is not configured");
-#endif
-}
-
-#define WAITDEBUG(arg) do { size_t line = __LINE__; \
- if ((arg)[0] == '=') \
- wait_debug(atoi((arg)+1), __FILE__, line); \
- else \
- wait_debug(0, __FILE__, line); \
-} while (0)
-
diff --git a/configure.ac b/configure.ac
index 00d84a5..7280b84 100644
--- a/configure.ac
+++ b/configure.ac
@@ -26,7 +26,7 @@ dnl Library versioning
AC_SUBST(VI_CURRENT,1)
AC_SUBST(VI_REVISION,0)
AC_SUBST(VI_AGE,0)
-AC_SUBST(PAM_COMMON_INCLUDES, '-I${top_builddir} -I${top_srcdir}')
+AC_SUBST(PAM_COMMON_INCLUDES, '-I${top_builddir} -I${top_srcdir} -I${top_srcdir}/lib')
dnl Checks for programs.
AC_PROG_CC
@@ -181,7 +181,8 @@ else
fi])
AC_OUTPUT(Makefile
- doc/Makefile
+ doc/Makefile
+ lib/Makefile
pam_fshadow/Makefile
pam_regex/Makefile
pam_log/Makefile
diff --git a/doc/pam-modules.texi b/doc/pam-modules.texi
index 1c94929..11b1037 100644
--- a/doc/pam-modules.texi
+++ b/doc/pam-modules.texi
@@ -271,9 +271,9 @@ for the user name @samp{smith} in the files
@prindex pam_regex
The module @command{pam_regex} allows to control user access by
-matching their login name against a regular expression. It
-may be useful, for example, in authentication stacks for such services
-as @acronym{FTP} or @acronym{HTTP}.
+matching their login name against a regular expression and to alter
+user names. It may be useful, for example, in authentication stacks
+for such services as @acronym{FTP} or @acronym{HTTP}.
@table @code
@opindex basic, @command{pam_regex} option
@@ -305,6 +305,80 @@ options (see above).
@item sense=@{allow|deny@}
What to do if user name matches the regexp. Default is @samp{allow}.
+@opindex transform, @command{pam_regex} option
+@item transform=@var{expression}
+ Transform the user name using given expression. The argument
+@var{expression} is a @command{sed}-like replace expression of the
+form:
+
+@smallexample
+s/@var{regexp}/@var{replace}/[@var{flags}]
+@end smallexample
+
+@noindent
+where @var{regexp} is a @dfn{regular expression}, @var{replace} is a
+replacement for each file name part that matches @var{regexp}. Both
+@var{regexp} and @var{replace} are described in detail in
+@ref{The "s" Command, The "s" Command, The `s' Command, sed, GNU sed}.
+
+As in @command{sed}, you can give several replace expressions,
+separated by a semicolon.
+
+Supported @var{flags} are:
+
+@table @samp
+@item g
+Apply the replacement to @emph{all} matches to the @var{regexp}, not
+just the first.
+
+@item i
+Use case-insensitive matching
+
+@item x
+@var{regexp} is an @dfn{extended regular expression} (@pxref{Extended
+regexps, Extended regular expressions, Extended regular expressions,
+sed, GNU sed}).
+
+@item @var{number}
+Only replace the @var{number}th match of the @var{regexp}.
+
+Note: the @var{posix} standard does not specify what should happen
+when you mix the @samp{g} and @var{number} modifiers. @command{Pam_regex}
+follows the GNU @command{sed} implementation in this regard, so
+the interaction is defined to be: ignore matches before the
+@var{number}th, and then match and replace all matches from the
+@var{number}th on.
+
+@end table
+
+Any delimiter can be used in lieue of @samp{/}, the only requirement being
+that it be used consistently throughout the expression. For example,
+the following two expressions are equivalent:
+
+@smallexample
+@group
+s/one/two/
+s,one,two,
+@end group
+@end smallexample
+
+Changing delimiters is often useful when the @var{regex} contains
+slashes. For instance, it is more convenient to write @code{s,/,-,} than
+@code{s/\//-/}.
+
+The following example converts the user name to
+lower case and removes anything after the @samp{@@} symbol. It allows
+allows only user names @samp{anoncvs} and @samp{anonymous}. As a
+result, the following user names will pass the module: @samp{anoncvs},
+@samp{Anoncvs}, @samp{AnonCVS@@user.org}.
+
+@smallexample
+@group
+pam_refex.so extended transform=s/.*/\L&/g;s/@.*/ \
+ regex=^(anoncvs|anonymous)$ sense=allow
+@end group
+@end smallexample
+
@opindex use_authtok, @command{pam_regex} option
@item use_authtok
Do not prompt the user for password, take it from the saved
diff --git a/lib/Makefile.am b/lib/Makefile.am
new file mode 100644
index 0000000..1a5acea
--- a/dev/null
+++ b/lib/Makefile.am
@@ -0,0 +1,19 @@
+# Copyright (C) 2008 Sergey Poznyakoff
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see <http://www.gnu.org/licenses/>.
+
+lib_LTLIBRARIES = libgraypam.la
+
+libgraypam_la_SOURCES = log.c mem.c slist.c transform.c converse.c
+noinst_HEADERS = graypam.h \ No newline at end of file
diff --git a/lib/converse.c b/lib/converse.c
new file mode 100644
index 0000000..dc7c44d
--- a/dev/null
+++ b/lib/converse.c
@@ -0,0 +1,49 @@
+/* This file is part of pam-modules.
+ Copyright (C) 2008 Sergey Poznyakoff
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <graypam.h>
+
+int
+gray_converse(pam_handle_t *pamh,
+ int nargs,
+ struct pam_message **message,
+ struct pam_response **response)
+{
+ int retval;
+ struct pam_conv *conv;
+
+ retval = pam_get_item(pamh, PAM_CONV, (const void **) &conv);
+ if (retval == PAM_SUCCESS) {
+
+ retval = conv->conv(nargs,
+ (const struct pam_message **) message,
+ response,
+ conv->appdata_ptr);
+
+ if (retval != PAM_SUCCESS) {
+ _pam_log(LOG_ERR,
+ "conversation failure [%s]",
+ pam_strerror(pamh, retval));
+ }
+ } else if (retval != PAM_CONV_AGAIN) {
+ _pam_log(LOG_ERR,
+ "couldn't obtain coversation function: %s",
+ pam_strerror(pamh, retval));
+ }
+
+ return retval; /* propagate error status */
+}
+
diff --git a/lib/graypam.h b/lib/graypam.h
new file mode 100644
index 0000000..24b8ea7
--- a/dev/null
+++ b/lib/graypam.h
@@ -0,0 +1,149 @@
+/* This file is part of pam-modules.
+ Copyright (C) 2008 Sergey Poznyakoff
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef _graypam_h_
+#define _graypam_h_
+
+#if defined(HAVE_CONFIG_H)
+# include <config.h>
+#endif
+#ifdef HAVE__PAM_ACONF_H
+#include <security/_pam_aconf.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <syslog.h>
+#include <errno.h>
+#include <regex.h>
+#include <setjmp.h>
+
+#ifndef LINUX_PAM
+#include <security/pam_appl.h>
+#endif /* LINUX_PAM */
+#include <security/pam_modules.h>
+
+#ifndef PAM_CONV_AGAIN
+# define PAM_CONV_AGAIN PAM_TRY_AGAIN
+#endif
+#ifndef PAM_AUTHTOK_RECOVER_ERR
+# define PAM_AUTHTOK_RECOVER_ERR PAM_AUTHTOK_RECOVERY_ERR
+#endif
+#ifndef PAM_EXTERN
+# define PAM_EXTERN
+#endif
+
+#define XSTRDUP(s) ((s) ? strdup(s) : NULL)
+
+#define PAM_OVERWRITE(s) \
+ do { \
+ register char *p; \
+ if ((p = s) != NULL) \
+ while (*p) *p++ = 0; \
+ } while (0)
+
+#define PAM_DROP_REPLY(reply, nrepl) \
+ do { \
+ int i; \
+ for (i=0; i<nrepl; i++) { \
+ PAM_OVERWRITE(reply[i].resp); \
+ free(reply[i].resp); \
+ } \
+ if (reply) \
+ free(reply); \
+ } while (0)
+
+
+#define MAKE_STR(pamh, str, var) \
+ gray_make_str(pamh,str,#var,&var)
+
+#define WAITDEBUG(arg) do { size_t line = __LINE__; \
+ if ((arg)[0] == '=') \
+ gray_wait_debug(atoi((arg)+1), __FILE__, line); \
+ else \
+ gray_wait_debug(0, __FILE__, line); \
+} while (0)
+
+extern jmp_buf gray_pam_jmp;
+
+#define gray_pam_init(retval) \
+ if (setjmp(gray_pam_jmp)) \
+ return retval; \
+
+void gray_raise(const char *fmt, ...);
+
+void *gray_malloc(size_t size);
+void *gray_zalloc(size_t size);
+void *gray_realloc(void *ptr, size_t size);
+
+void gray_pam_delete(char *x);
+void gray_cleanup_string(pam_handle_t *pamh, void *x, int error_status);
+void gray_cleanup_regex(pam_handle_t *pamh, void *x, int error_status);
+void gray_make_str(pam_handle_t *pamh, const char *str, const char *name,
+ char **ret);
+
+
+typedef struct gray_slist *gray_slist_t;
+
+gray_slist_t gray_slist_create();
+void gray_slist_clear(gray_slist_t slist);
+void gray_slist_free(gray_slist_t *slist);
+void gray_slist_append(gray_slist_t slist, const char *str, size_t n);
+void gray_slist_append_char(gray_slist_t slist, char c);
+size_t gray_slist_size(gray_slist_t slist);
+size_t gray_slist_coalesce(gray_slist_t slist);
+void *gray_slist_head(gray_slist_t slist, size_t *psize);
+void *gray_slist_finish(gray_slist_t slist);
+void gray_slist_grow_backslash_num(gray_slist_t slist, char *text, char **pend,
+ int len, int base);
+void gray_slist_grow_backslash(gray_slist_t slist, char *text, char **endp);
+
+
+void gray_log_init(int dont_open, const char *tag, int f);
+void gray_pam_vlog(int err, const char *format, va_list args);
+void gray_pam_log(int err, const char *format, ...);
+void gray_pam_debug(const char *format, ...);
+void gray_wait_debug(size_t interval, const char *file, size_t line);
+
+#define _pam_vlog gray_pam_vlog
+#define _pam_log gray_pam_log
+#define _pam_debug gray_pam_debug
+
+
+int gray_transform_name_to_slist (gray_slist_t slist, char *input, char **output);
+void gray_set_transform_expr (const char *expr);
+
+
+int gray_converse(pam_handle_t *pamh, int nargs,
+ struct pam_message **message,
+ struct pam_response **response);
+
+/* Command line parsing */
+#define CNTL_DEBUG 0x0001
+#define CNTL_AUDIT 0x0002
+#define CNTL_WAITDEBUG 0x0004
+
+#define CNTL_DEBUG_LEV() (cntl_flags>>16)
+#define CNTL_SET_DEBUG_LEV(cntl,n) (cntl |= ((n)<<16))
+
+#define DEBUG(m,c) if (CNTL_DEBUG_LEV()>=(m)) _pam_debug c
+#define AUDIT(c) if (cntl_flags&CNTL_AUDIT) _pam_debug c
+
+#endif
diff --git a/lib/log.c b/lib/log.c
new file mode 100644
index 0000000..2794c02
--- a/dev/null
+++ b/lib/log.c
@@ -0,0 +1,79 @@
+/* This file is part of pam-modules.
+ Copyright (C) 2008 Sergey Poznyakoff
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <graypam.h>
+
+/* Syslog functions */
+static int syslog_dont_open;
+static const char *syslog_tag = "pam_modules";
+static int facility;
+
+void
+gray_log_init(int dont_open, const char *tag, int f)
+{
+ syslog_dont_open = dont_open;
+ syslog_tag = tag;
+ facility = f;
+}
+
+void
+gray_pam_vlog(int err, const char *format, va_list args)
+{
+ if (syslog_dont_open)
+ err |= facility;
+ else
+ openlog(syslog_tag, LOG_CONS|LOG_PID, facility);
+ vsyslog(err, format, args);
+ if (!syslog_dont_open)
+ closelog();
+}
+
+void
+gray_pam_log(int err, const char *format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+ gray_pam_vlog(err, format, args);
+ va_end(args);
+}
+
+void
+gray_pam_debug(const char *format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+ gray_pam_vlog(LOG_DEBUG, format, args);
+ va_end(args);
+}
+
+void
+gray_wait_debug(size_t interval, const char *file, size_t line)
+{
+#ifdef DEBUG_MODE
+ if (!interval)
+ interval = 3600;
+ gray_pam_log(LOG_CRIT, "WAITING FOR DEBUG AT %s:%d",
+ file, (unsigned long)line);
+ while (interval-- > 0)
+ sleep(1);
+#else
+ gray_pam_log(LOG_NOTICE, "Debugging is not configured");
+#endif
+}
+
+
diff --git a/lib/mem.c b/lib/mem.c
new file mode 100644
index 0000000..e8ee1cc
--- a/dev/null
+++ b/lib/mem.c
@@ -0,0 +1,99 @@
+/* This file is part of pam-modules.
+ Copyright (C) 2008 Sergey Poznyakoff
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <graypam.h>
+
+jmp_buf gray_pam_jmp;
+
+void
+gray_raise(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ _pam_vlog(LOG_ERR, fmt, ap);
+ va_end(ap);
+ longjmp(gray_pam_jmp, 1);
+}
+
+void *
+gray_malloc(size_t size)
+{
+ void *p = malloc(size);
+ if (!p)
+ gray_raise("Not enough memory");
+ return p;
+}
+
+void *
+gray_zalloc(size_t size)
+{
+ void *p = malloc(size);
+ if (!p)
+ gray_raise("Not enough memory");
+ memset(p, 0, size);
+ return p;
+}
+
+void *
+gray_realloc(void *ptr, size_t size)
+{
+ ptr = realloc(ptr, size);
+ if (!ptr)
+ gray_raise("Not enough memory");
+ return ptr;
+}
+
+
+void
+gray_pam_delete(char *x)
+{
+ PAM_OVERWRITE(x);
+ free(x);
+}
+
+void
+gray_cleanup_string(pam_handle_t *pamh, void *x, int error_status)
+{
+ gray_pam_delete(x);
+}
+
+void
+gray_cleanup_regex(pam_handle_t *pamh, void *x, int error_status)
+{
+ regfree((regex_t*)x);
+}
+
+void
+gray_make_str(pam_handle_t *pamh, const char *str, const char *name,
+ char **ret)
+{
+ int retval;
+ char *newstr = XSTRDUP(str);
+
+ retval = pam_set_data(pamh, name, (void *)newstr, gray_cleanup_string);
+ if (retval != PAM_SUCCESS) {
+ _pam_log(LOG_CRIT,
+ "can't keep data [%s]: %s",
+ name,
+ pam_strerror(pamh, retval));
+ gray_pam_delete(newstr);
+ } else {
+ *ret = newstr;
+ newstr = NULL;
+ }
+}
+
+
diff --git a/lib/slist.c b/lib/slist.c
new file mode 100644
index 0000000..6a4820b
--- a/dev/null
+++ b/lib/slist.c
@@ -0,0 +1,244 @@
+/* This file is part of pam_modules.
+ Copyright (C) 2007 Free Software Foundation, Inc.
+
+ Written by Sergey Poznyakoff
+
+ GNU Radius is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ GNU Radius is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with GNU Radius; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301 USA. */
+
+#include <graypam.h>
+
+#define GRAY_SLIST_BUCKET_SIZE 1024
+
+struct gray_slist_bucket {
+ struct gray_slist_bucket *next;
+ char *buf;
+ size_t level;
+ size_t size;
+};
+
+struct gray_slist {
+ struct gray_slist_bucket *head, *tail;
+ struct gray_slist_bucket *free;
+};
+
+static struct gray_slist_bucket *
+alloc_bucket(size_t size)
+{
+ struct gray_slist_bucket *p = gray_malloc(sizeof(*p) + size);
+ p->buf = (char*)(p + 1);
+ p->level = 0;
+ p->size = size;
+ p->next = NULL;
+ return p;
+}
+
+static void
+alloc_pool(gray_slist_t slist, size_t size)
+{
+ struct gray_slist_bucket *p = alloc_bucket(GRAY_SLIST_BUCKET_SIZE);
+ if (slist->tail)
+ slist->tail->next = p;
+ else
+ slist->head = p;
+ slist->tail = p;
+}
+
+static size_t
+copy_chars(gray_slist_t slist, const char *str, size_t n)
+{
+ size_t rest;
+
+
+ if (!slist->head || slist->tail->level == slist->tail->size)
+ alloc_pool(slist, GRAY_SLIST_BUCKET_SIZE);
+ rest = slist->tail->size - slist->tail->level;
+ if (n > rest)
+ n = rest;
+ memcpy(slist->tail->buf + slist->tail->level, str, n);
+ slist->tail->level += n;
+ return n;
+}
+
+gray_slist_t
+gray_slist_create()
+{
+ gray_slist_t slist = gray_malloc(sizeof(*slist));
+ slist->head = slist->tail = slist->free = 0;
+ return slist;
+}
+
+void
+gray_slist_clear(gray_slist_t slist)
+{
+ if (slist->tail) {
+ slist->tail->next = slist->free;
+ slist->free = slist->head;
+ slist->head = slist->tail = NULL;
+ }
+}
+
+
+void
+gray_slist_free(gray_slist_t *slist)
+{
+ struct gray_slist_bucket *p;
+ if (*slist) {
+ gray_slist_clear(*slist);
+ for (p = (*slist)->free; p; ) {
+ struct gray_slist_bucket *next = p->next;
+ free(p);
+ p = next;
+ }
+ }
+ free(*slist);
+ *slist = NULL;
+}
+
+void
+gray_slist_append(gray_slist_t slist, const char *str, size_t n)
+{
+ const char *ptr = str;
+ while (n) {
+ size_t s = copy_chars(slist, ptr, n);
+ ptr += s;
+ n -= s;
+ }
+}
+
+void
+gray_slist_append_char(gray_slist_t slist, char c)
+{
+ gray_slist_append(slist, &c, 1);
+}
+
+size_t
+gray_slist_size(gray_slist_t slist)
+{
+ size_t size = 0;
+ struct gray_slist_bucket *p;
+ for (p = slist->head; p; p = p->next)
+ size += p->level;
+ return size;
+}
+
+size_t
+gray_slist_coalesce(gray_slist_t slist)
+{
+ size_t size;
+
+ if (slist->head && slist->head->next == NULL)
+ size = slist->head->level;
+ else {
+ size = gray_slist_size(slist);
+ struct gray_slist_bucket *bucket = alloc_bucket(size);
+ struct gray_slist_bucket *p;
+
+ for (p = slist->head; p; ) {
+ struct gray_slist_bucket *next = p->next;
+ memcpy(bucket->buf + bucket->level, p->buf, p->level);
+ bucket->level += p->level;
+ free(p);
+ p = next;
+ }
+ slist->head = slist->tail = bucket;
+ }
+ return size;
+}
+
+void *
+gray_slist_head(gray_slist_t slist, size_t *psize)
+{
+ if (*psize)
+ *psize = slist->head ? slist->head->level : 0;
+ return slist->head ? slist->head->buf : NULL;
+}
+
+void *
+gray_slist_finish(gray_slist_t slist)
+{
+ gray_slist_coalesce(slist);
+ gray_slist_clear(slist);
+ return slist->free->buf;
+}
+
+
+#define to_num(c) \
+ (isdigit(c) ? c - '0' : (isxdigit(c) ? toupper(c) - 'A' + 10 : 255 ))
+
+void
+gray_slist_grow_backslash_num(gray_slist_t slist, char *text, char **pend,
+ int len, int base)
+{
+ int i;
+ int val = 0;
+ char *start = text;
+
+ if (text[0] == '\\') {
+ text++;
+ if (base == 16)
+ text++;
+ }
+
+ for (i = 0; i < len; i++) {
+ int n = (unsigned char)text[i];
+ if (n > 127 || (n = to_num(n)) >= base)
+ break;
+ val = val*base + n;
+ }
+
+ if (i == 0) {
+ gray_slist_append(slist, start, 1);
+ if (pend)
+ *pend = start + 1;
+ } else {
+ gray_slist_append_char(slist, val);
+ if (pend)
+ *pend = text + i;
+ }
+}
+
+int
+gray_decode_backslash(int c)
+{
+ static char transtab[] = "a\ab\bf\fn\nr\rt\t";
+ char *p;
+
+ for (p = transtab; *p; p += 2) {
+ if (*p == c)
+ return p[1];
+ }
+ return c;
+}
+
+void
+gray_slist_grow_backslash(gray_slist_t slist, char *text, char **endp)
+{
+ if (text[1] == '\\' || (unsigned char)text[1] > 127) {
+ gray_slist_append_char(slist, text[1]);
+ text += 2;
+ } else if (isdigit(text[1]))
+ gray_slist_grow_backslash_num(slist, text, &text, 3, 8);
+ else if (text[1] == 'x' || text[1] == 'X')
+ gray_slist_grow_backslash_num(slist, text, &text, 2, 16);
+ else {
+ int c = gray_decode_backslash(text[1]);
+ gray_slist_append_char(slist, c);
+ text += 2;
+ }
+
+ *endp = text;
+}
+
diff --git a/lib/transform.c b/lib/transform.c
new file mode 100644
index 0000000..17fc651
--- a/dev/null
+++ b/lib/transform.c
@@ -0,0 +1,533 @@
+/* This file is part of pam_modules.
+ Copyright (C) 2006, 2007, 2008 Sergey Poznyakoff.
+ (using my implementation for the GNU tar).
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 3, or (at your option) any later
+ version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <graypam.h>
+
+enum transform_type
+ {
+ transform_first,
+ transform_global
+ };
+
+enum replace_segm_type
+ {
+ segm_literal, /* Literal segment */
+ segm_backref, /* Back-reference segment */
+ segm_case_ctl /* Case control segment (GNU extension) */
+ };
+
+enum case_ctl_type
+ {
+ ctl_stop, /* Stop case conversion */
+ ctl_upcase_next,/* Turn the next character to uppercase */
+ ctl_locase_next,/* Turn the next character to lowercase */
+ ctl_upcase, /* Turn the replacement to uppercase until ctl_stop */
+ ctl_locase /* Turn the replacement to lowercase until ctl_stop */
+ };
+
+struct replace_segm
+{
+ struct replace_segm *next;
+ enum replace_segm_type type;
+ union
+ {
+ struct
+ {
+ char *ptr;
+ size_t size;
+ } literal; /* type == segm_literal */
+ size_t ref; /* type == segm_backref */
+ enum case_ctl_type ctl; /* type == segm_case_ctl */
+ } v;
+};
+
+struct transform
+{
+ struct transform *next;
+ enum transform_type transform_type;
+ unsigned match_number;
+ regex_t regex;
+ /* Compiled replacement expression */
+ struct replace_segm *repl_head, *repl_tail;
+ size_t segm_count; /* Number of elements in the above list */
+};
+
+
+static struct transform *transform_head, *transform_tail;
+
+static struct transform *
+new_transform ()
+{
+ struct transform *p = gray_zalloc (sizeof *p);
+ if (transform_tail)
+ transform_tail->next = p;
+ else
+ transform_head = p;
+ transform_tail = p;
+ return p;
+}
+
+static struct replace_segm *
+add_segment (struct transform *tf)
+{
+ struct replace_segm *segm = gray_malloc (sizeof *segm);
+ segm->next = NULL;
+ if (tf->repl_tail)
+ tf->repl_tail->next = segm;
+ else
+ tf->repl_head = segm;
+ tf->repl_tail = segm;
+ tf->segm_count++;
+ return segm;
+}
+
+static void
+add_literal_segment (struct transform *tf, char *str, char *end)
+{
+ size_t len = end - str;
+ if (len)
+ {
+ struct replace_segm *segm = add_segment (tf);
+ segm->type = segm_literal;
+ segm->v.literal.ptr = gray_malloc (len + 1);
+ memcpy (segm->v.literal.ptr, str, len);
+ segm->v.literal.ptr[len] = 0;
+ segm->v.literal.size = len;
+ }
+}
+
+static void
+add_char_segment (struct transform *tf, int chr)
+{
+ struct replace_segm *segm = add_segment (tf);
+ segm->type = segm_literal;
+ segm->v.literal.ptr = gray_malloc (2);
+ segm->v.literal.ptr[0] = chr;
+ segm->v.literal.ptr[1] = 0;
+ segm->v.literal.size = 1;
+}
+
+static void
+add_backref_segment (struct transform *tf, size_t ref)
+{
+ struct replace_segm *segm = add_segment (tf);
+ segm->type = segm_backref;
+ segm->v.ref = ref;
+}
+
+static void
+add_case_ctl_segment (struct transform *tf, enum case_ctl_type ctl)
+{
+ struct replace_segm *segm = add_segment (tf);
+ segm->type = segm_case_ctl;
+ segm->v.ctl = ctl;
+}
+
+static const char *
+parse_transform_expr (const char *expr)
+{
+ int delim;
+ int i, j, rc;
+ char *str, *beg, *cur;
+ const char *p;
+ int cflags = 0;
+ struct transform *tf = new_transform ();
+
+ if (expr[0] != 's')
+ gray_raise ("Invalid transform expression");
+
+ delim = expr[1];
+
+ /* Scan regular expression */
+ for (i = 2; expr[i] && expr[i] != delim; i++)
+ if (expr[i] == '\\' && expr[i+1])
+ i++;
+
+ if (expr[i] != delim)
+ gray_raise ("Invalid transform expression");
+
+ /* Scan replacement expression */
+ for (j = i + 1; expr[j] && expr[j] != delim; j++)
+ if (expr[j] == '\\' && expr[j+1])
+ j++;
+
+ if (expr[j] != delim)
+ gray_raise ("Invalid transform expression");
+
+ /* Check flags */
+ tf->transform_type = transform_first;
+ for (p = expr + j + 1; *p && *p != ';'; p++)
+ switch (*p)
+ {
+ case 'g':
+ tf->transform_type = transform_global;
+ break;
+
+ case 'i':
+ cflags |= REG_ICASE;
+ break;
+
+ case 'x':
+ cflags |= REG_EXTENDED;
+ break;
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ tf->match_number = strtoul (p, (char**) &p, 0);
+ p--;
+ break;
+
+ default:
+ gray_raise("Unknown flag in transform expression: %c", *p);
+ }
+
+ if (*p == ';')
+ p++;
+
+ /* Extract and compile regex */
+ str = gray_malloc (i - 1);
+ memcpy (str, expr + 2, i - 2);
+ str[i - 2] = 0;
+
+ rc = regcomp (&tf->regex, str, cflags);
+
+ if (rc)
+ {
+ char errbuf[512];
+ regerror (rc, &tf->regex, errbuf, sizeof (errbuf));
+ gray_raise("Invalid transform expression: %s", errbuf);
+ }
+
+ if (str[0] == '^' || str[strlen (str) - 1] == '$')
+ tf->transform_type = transform_first;
+
+ free (str);
+
+ /* Extract and compile replacement expr */
+ i++;
+ str = gray_malloc (j - i + 1);
+ memcpy (str, expr + i, j - i);
+ str[j - i] = 0;
+
+ for (cur = beg = str; *cur;)
+ {
+ if (*cur == '\\')
+ {
+ size_t n;
+
+ add_literal_segment (tf, beg, cur);
+ switch (*++cur)
+ {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ n = strtoul (cur, &cur, 10);
+ if (n > tf->regex.re_nsub)
+ gray_raise ("Invalid transform replacement: "
+ "back reference out of range");
+ add_backref_segment (tf, n);
+ break;
+
+ case '\\':
+ add_char_segment (tf, '\\');
+ cur++;
+ break;
+
+ case 'a':
+ add_char_segment (tf, '\a');
+ cur++;
+ break;
+
+ case 'b':
+ add_char_segment (tf, '\b');
+ cur++;
+ break;
+
+ case 'f':
+ add_char_segment (tf, '\f');
+ cur++;
+ break;
+
+ case 'n':
+ add_char_segment (tf, '\n');
+ cur++;
+ break;
+
+ case 'r':
+ add_char_segment (tf, '\r');
+ cur++;
+ break;
+
+ case 't':
+ add_char_segment (tf, '\t');
+ cur++;
+ break;
+
+ case 'v':
+ add_char_segment (tf, '\v');
+ cur++;
+ break;
+
+ case '&':
+ add_char_segment (tf, '&');
+ cur++;
+ break;
+
+ case 'L':
+ /* Turn the replacement to lowercase until a `\U' or `\E'
+ is found, */
+ add_case_ctl_segment (tf, ctl_locase);
+ cur++;
+ break;
+
+ case 'l':
+ /* Turn the next character to lowercase, */
+ add_case_ctl_segment (tf, ctl_locase_next);
+ cur++;
+ break;
+
+ case 'U':
+ /* Turn the replacement to uppercase until a `\L' or `\E'
+ is found, */
+ add_case_ctl_segment (tf, ctl_upcase);
+ cur++;
+ break;
+
+ case 'u':
+ /* Turn the next character to uppercase, */
+ add_case_ctl_segment (tf, ctl_upcase_next);
+ cur++;
+ break;
+
+ case 'E':
+ /* Stop case conversion started by `\L' or `\U'. */
+ add_case_ctl_segment (tf, ctl_stop);
+ cur++;
+ break;
+
+ default:
+ /* Try to be nice */
+ {
+ char buf[2];
+ buf[0] = '\\';
+ buf[1] = *cur;
+ add_literal_segment (tf, buf, buf + 2);
+ }
+ cur++;
+ break;
+ }
+ beg = cur;
+ }
+ else if (*cur == '&')
+ {
+ add_literal_segment (tf, beg, cur);
+ add_backref_segment (tf, 0);
+ beg = ++cur;
+ }
+ else
+ cur++;
+ }
+ add_literal_segment (tf, beg, cur);
+
+ return p;
+}
+
+void
+gray_set_transform_expr (const char *expr)
+{
+ while (*expr)
+ expr = parse_transform_expr (expr);
+}
+
+/* Run case conversion specified by CASE_CTL on array PTR of SIZE
+ characters. Returns pointer to statically allocated storage. */
+static char *
+run_case_conv (enum case_ctl_type case_ctl, char *ptr, size_t size)
+{
+ static char *case_ctl_buffer;
+ static size_t case_ctl_bufsize;
+ char *p;
+
+ if (case_ctl_bufsize < size)
+ {
+ case_ctl_bufsize = size;
+ case_ctl_buffer = gray_realloc (case_ctl_buffer, case_ctl_bufsize);
+ }
+ memcpy (case_ctl_buffer, ptr, size);
+ switch (case_ctl)
+ {
+ case ctl_upcase_next:
+ case_ctl_buffer[0] = toupper (case_ctl_buffer[0]);
+ break;
+
+ case ctl_locase_next:
+ case_ctl_buffer[0] = tolower (case_ctl_buffer[0]);
+ break;
+
+ case ctl_upcase:
+ for (p = case_ctl_buffer; p < case_ctl_buffer + size; p++)
+ *p = toupper (*p);
+ break;
+
+ case ctl_locase:
+ for (p = case_ctl_buffer; p < case_ctl_buffer + size; p++)
+ *p = tolower (*p);
+ break;
+
+ case ctl_stop:
+ break;
+ }
+ return case_ctl_buffer;
+}
+
+
+void
+_single_transform_name_to_slist (struct transform *tf, gray_slist_t slist,
+ char *input)
+{
+ regmatch_t *rmp;
+ int rc;
+ size_t nmatches = 0;
+ enum case_ctl_type case_ctl = ctl_stop, /* Current case conversion op */
+ save_ctl = ctl_stop; /* Saved case_ctl for \u and \l */
+
+ /* Reset case conversion after a single-char operation */
+#define CASE_CTL_RESET() if (case_ctl == ctl_upcase_next \
+ || case_ctl == ctl_locase_next) \
+ { \
+ case_ctl = save_ctl; \
+ save_ctl = ctl_stop; \
+ }
+
+ rmp = gray_malloc ((tf->regex.re_nsub + 1) * sizeof (*rmp));
+
+ while (*input)
+ {
+ size_t disp;
+ char *ptr;
+
+ rc = regexec (&tf->regex, input, tf->regex.re_nsub + 1, rmp, 0);
+
+ if (rc == 0)
+ {
+ struct replace_segm *segm;
+
+ disp = rmp[0].rm_eo;
+
+ if (rmp[0].rm_so)
+ gray_slist_append (slist, input, rmp[0].rm_so);
+
+ nmatches++;
+ if (tf->match_number && nmatches < tf->match_number)
+ {
+ gray_slist_append (slist, input, disp);
+ input += disp;
+ continue;
+ }
+
+ for (segm = tf->repl_head; segm; segm = segm->next)
+ {
+ switch (segm->type)
+ {
+ case segm_literal: /* Literal segment */
+ if (case_ctl == ctl_stop)
+ ptr = segm->v.literal.ptr;
+ else
+ {
+ ptr = run_case_conv (case_ctl,
+ segm->v.literal.ptr,
+ segm->v.literal.size);
+ CASE_CTL_RESET();
+ }
+ gray_slist_append (slist, ptr, segm->v.literal.size);
+ break;
+
+ case segm_backref: /* Back-reference segment */
+ if (rmp[segm->v.ref].rm_so != -1
+ && rmp[segm->v.ref].rm_eo != -1)
+ {
+ size_t size = rmp[segm->v.ref].rm_eo
+ - rmp[segm->v.ref].rm_so;
+ ptr = input + rmp[segm->v.ref].rm_so;
+ if (case_ctl != ctl_stop)
+ {
+ ptr = run_case_conv (case_ctl, ptr, size);
+ CASE_CTL_RESET();
+ }
+
+ gray_slist_append (slist, ptr, size);
+ }
+ break;
+
+ case segm_case_ctl:
+ switch (segm->v.ctl)
+ {
+ case ctl_upcase_next:
+ case ctl_locase_next:
+ switch (save_ctl)
+ {
+ case ctl_stop:
+ case ctl_upcase:
+ case ctl_locase:
+ save_ctl = case_ctl;
+ default:
+ break;
+ }
+ /*FALL THROUGH*/
+
+ case ctl_upcase:
+ case ctl_locase:
+ case ctl_stop:
+ case_ctl = segm->v.ctl;
+ }
+ }
+ }
+ }
+ else
+ {
+ disp = strlen (input);
+ gray_slist_append (slist, input, disp);
+ }
+
+ input += disp;
+
+ if (tf->transform_type == transform_first)
+ {
+ gray_slist_append (slist, input, strlen (input));
+ break;
+ }
+ }
+
+ gray_slist_append_char (slist, 0);
+ free (rmp);
+}
+
+int
+gray_transform_name_to_slist (gray_slist_t slist, char *input, char **output)
+{
+ struct transform *tf;
+
+ for (tf = transform_head; tf; tf = tf->next)
+ {
+ _single_transform_name_to_slist (tf, slist, input);
+ input = gray_slist_finish (slist);
+ }
+ *output = input;
+ return transform_head != NULL;
+}
+
+
diff --git a/pam_fshadow/Makefile.am b/pam_fshadow/Makefile.am
index 10849cb..f996406 100644
--- a/pam_fshadow/Makefile.am
+++ b/pam_fshadow/Makefile.am
@@ -1,4 +1,4 @@
-# Copyright (C) 2001, 2006, 2007 Sergey Poznyakoff
+# Copyright (C) 2001, 2006, 2007, 2008 Sergey Poznyakoff
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -17,18 +17,13 @@ pamdir=@PAMDIR@
pam_PROGRAMS = pam_fshadow.la
AM_INSTALLCHECK_STD_OPTIONS_EXEMPT = pam_fshadow.la
pam_fshadow_la_SOURCES = pam_fshadow.c
-pam_fshadow_la_LDADD = -lpam @LIBS@
+LDADD = -lpam @LIBS@ ../lib/libgraypam.la
AM_LDFLAGS = -version-info @VI_CURRENT@:@VI_REVISION@:@VI_AGE@
AM_CPPFLAGS=-DMODULE_NAME=\"pam_fshadow\" -DSYSCONFDIR=\"${sysconfdir}\"
INCLUDES=@PAM_COMMON_INCLUDES@
NORMAL_UNINSTALL = -rm -f $(DESTDIR)$(pamdir)/pam_fshadow.a $(DESTDIR)$(pamdir)/pam_fshadow.so.@VI_CURRENT@.@VI_REVISION@.@VI_AGE@
-pam_fshadow.lo: $(srcdir)/pam_fshadow.c
- $(LIBTOOL) --mode=compile $(CC) -c -DHAVE_CONFIG_H \
- $(CFLAGS) $(AM_CFLAGS) $(INCLUDES) $(CPPFLAGS) $(AM_CPPFLAGS) $<
+include $(top_srcdir)/Make.rules
-pam_fshadow.la$(EXEEXT): pam_fshadow.lo
- $(LIBTOOL) --mode=link $(CC) -module -export-dynamic \
- $(AM_LDFLAGS) \
- -o $@ $< $(pam_fshadow_la_LDADD) $(AM_LDADD) $(LDADD) \
- -rpath $(pamdir)
+pam_fshadow.lo: pam_fshadow.c
+pam_fshadow.la: pam_fshadow.lo
diff --git a/pam_fshadow/pam_fshadow.c b/pam_fshadow/pam_fshadow.c
index 9e7ab68..dea6357 100644
--- a/pam_fshadow/pam_fshadow.c
+++ b/pam_fshadow/pam_fshadow.c
@@ -1,5 +1,5 @@
/* This file is part of pam-modules.
- * Copyright (C) 2001, 2005, 2007 Sergey Poznyakoff
+ * Copyright (C) 2001, 2005, 2007, 2008 Sergey Poznyakoff
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -17,34 +17,22 @@
/* pam_fshadow */
-#if defined(HAVE_CONFIG_H)
-# include <config.h>
-#endif
-
-#include <security/_pam_aconf.h>
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <syslog.h>
-#include <stdarg.h>
+#include <graypam.h>
#include <time.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
#include <pwd.h>
#include <shadow.h>
-#include <regex.h>
+
+#if defined(HAVE_CRYPT_H)
+# include <crypt.h>
+#else
+extern char *crypt(const char *, const char *);
+#endif
#define PAM_SM_AUTH
#define PAM_SM_ACCOUNT
#include <security/pam_modules.h>
-#include <common.c>
-
char *sysconfdir = SYSCONFDIR;
static int cntl_flags = 0;
@@ -53,20 +41,17 @@ const char *regex_str = NULL;
static int username_index = 1;
static int domain_index = 2;
-#define CNTL_DEBUG 0x0001
-#define CNTL_AUTHTOK 0x0002
-#define CNTL_NOPASSWD 0x0004
-#define CNTL_REGEX 0x0008
-
-#define CNTL_DEBUG_LEV() (cntl_flags>>16)
-#define CNTL_SET_DEBUG_LEV(cntl,n) (cntl |= ((n)<<16))
-#define DEBUG(m,c) if (CNTL_DEBUG_LEV()>=(m)) _pam_debug c
+#define CNTL_AUTHTOK 0x0010
+#define CNTL_NOPASSWD 0x0020
+#define CNTL_REGEX 0x0040
static int
_pam_parse(pam_handle_t *pamh, int argc, const char **argv)
{
int regex_flags = 0;
int retval = PAM_SUCCESS;
+
+ gray_log_init(0, MODULE_NAME, LOG_AUTHPRIV);
/* step through arguments */
for (cntl_flags = 0; argc-- > 0; ++argv) {
@@ -81,7 +66,7 @@ _pam_parse(pam_handle_t *pamh, int argc, const char **argv)
else
CNTL_SET_DEBUG_LEV(cntl_flags, 1);
} else if (!strncmp(*argv, "waitdebug", 9))
- WAITDEBUG(*argv + 9);
+ WAITDEBUG(*argv + 9);
else if (!strcmp(*argv,"use_authtok"))
cntl_flags |= CNTL_AUTHTOK;
else if (!strncmp(*argv, "sysconfdir=", 11))
@@ -132,7 +117,7 @@ _pam_parse(pam_handle_t *pamh, int argc, const char **argv)
} else {
cntl_flags |= CNTL_REGEX;
rc = pam_set_data(pamh, "REGEX", &rexp,
- _cleanup_regex);
+ gray_cleanup_regex);
if (rc != PAM_SUCCESS) {
_pam_log(LOG_NOTICE,
@@ -147,44 +132,6 @@ _pam_parse(pam_handle_t *pamh, int argc, const char **argv)
}
static int
-converse(pam_handle_t *pamh,
- int nargs,
- struct pam_message **message,
- struct pam_response **response)
-{
- int retval;
- struct pam_conv *conv;
-
- DEBUG(100,("enter converse"));
-
- retval = pam_get_item(pamh, PAM_CONV, (const void **) &conv);
- DEBUG(10,("pam_get_item(PAM_CONV): %d", retval));
- if (retval == PAM_SUCCESS) {
-
- retval = conv->conv(nargs,
- (const struct pam_message **) message,
- response,
- conv->appdata_ptr);
-
- DEBUG(10, ("app conversation returned %d", retval));
-
- if (retval != PAM_SUCCESS) {
- _pam_log(LOG_ERR,
- "conversation failure [%s]",
- pam_strerror(pamh, retval));
- }
- } else if (retval != PAM_CONV_AGAIN) {
- _pam_log(LOG_ERR,
- "couldn't obtain coversation function: %s",
- pam_strerror(pamh, retval));
- }
-
- DEBUG(100,("exit converse: %d", retval));
-
- return retval; /* propagate error status */
-}
-
-static int
_pam_get_password(pam_handle_t *pamh, char **password, const char *prompt)
{
char *item, *token;
@@ -229,11 +176,11 @@ _pam_get_password(pam_handle_t *pamh, char **password, const char *prompt)
/* run conversation */
resp = NULL;
token = NULL;
- retval = converse(pamh, i, pmsg, &resp);
+ retval = gray_converse(pamh, i, pmsg, &resp);
if (resp != NULL) {
if (retval == PAM_SUCCESS) { /* a good conversation */
- token = XSTRDUP(resp[i - replies].resp);
+ token = XSTRDUP(resp[i - replies].resp);
DEBUG(10,("app returned [%s]", token));
PAM_DROP_REPLY(resp, 1);
} else {
@@ -253,12 +200,12 @@ _pam_get_password(pam_handle_t *pamh, char **password, const char *prompt)
*/
retval = pam_set_data(pamh, "password",
(void *)token,
- _cleanup_string);
+ gray_cleanup_string);
if (retval != PAM_SUCCESS) {
_pam_log(LOG_CRIT,
"can't keep password: %s",
pam_strerror(pamh, retval));
- _pam_delete(token);
+ gray_pam_delete(token);
} else {
*password = token;
token = NULL; /* break link to password */
@@ -397,13 +344,13 @@ copy_backref (pam_handle_t *pamh, const char *name,
_pam_log(LOG_CRIT, "not enough memory");
return PAM_SYSTEM_ERR;
}
- rc = pam_set_data(pamh, name, (void *)str, _cleanup_string);
+ rc = pam_set_data(pamh, name, (void *)str, gray_cleanup_string);
if (rc != PAM_SUCCESS) {
_pam_log(LOG_CRIT,
"can't keep data [%s]: %s",
name,
pam_strerror(pamh, rc));
- _pam_delete(str);
+ gray_pam_delete(str);
} else {
if (size != 0)
memcpy(str, buf + rmatch[index].rm_so, size);
@@ -453,7 +400,7 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags,
return rc;
confdir = mkfilename(sysconfdir, domain);
pam_set_data(pamh, "CONFDIR",
- (void *)confdir, _cleanup_string);
+ (void *)confdir, gray_cleanup_string);
} else {
_pam_log(LOG_DEBUG,
"user name `%s' does not match regular "
diff --git a/pam_log/Makefile.am b/pam_log/Makefile.am
index 886baea..80bb0bd 100644
--- a/pam_log/Makefile.am
+++ b/pam_log/Makefile.am
@@ -1,4 +1,4 @@
-# Copyright (C) 2006 Sergey Poznyakoff
+# Copyright (C) 2006, 2008 Sergey Poznyakoff
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -17,18 +17,13 @@ pamdir=@PAMDIR@
pam_PROGRAMS = pam_log.la
AM_INSTALLCHECK_STD_OPTIONS_EXEMPT = pam_log.la
pam_log_la_SOURCES = pam_log.c
-pam_log_la_LDADD = -lpam
+LDADD = -lpam ../lib/libgraypam.la
AM_LDFLAGS = -version-info @VI_CURRENT@:@VI_REVISION@:@VI_AGE@
AM_CPPFLAGS=-DMODULE_NAME=\"pam_log\" -DSYSCONFDIR=\"${sysconfdir}\"
INCLUDES=@PAM_COMMON_INCLUDES@
NORMAL_UNINSTALL = -rm -f $(DESTDIR)$(pamdir)/pam_log.a $(DESTDIR)$(pamdir)/pam_log.so.@VI_CURRENT@.@VI_REVISION@.@VI_AGE@
-pam_log.lo: $(srcdir)/pam_log.c
- $(LIBTOOL) --mode=compile $(CC) -c -DHAVE_CONFIG_H \
- $(CFLAGS) $(AM_CFLAGS) $(INCLUDES) $(CPPFLAGS) $(AM_CPPFLAGS) $<
+include $(top_srcdir)/Make.rules
-pam_log.la$(EXEEXT): pam_log.lo
- $(LIBTOOL) --mode=link $(CC) -module -export-dynamic \
- $(AM_LDFLAGS) \
- -o $@ $< $(pam_log_la_LDADD) $(AM_LDADD) $(LDADD)\
- -rpath $(pamdir)
+pam_log.lo: pam_log.c
+pam_log.la: pam_log.lo
diff --git a/pam_log/pam_log.c b/pam_log/pam_log.c
index bc39be1..0b81ee5 100644
--- a/pam_log/pam_log.c
+++ b/pam_log/pam_log.c
@@ -1,5 +1,5 @@
/* This file is part of pam-modules.
- Copyright (C) 2006, 2007 Sergey Poznyakoff
+ Copyright (C) 2006, 2007, 2008 Sergey Poznyakoff
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
@@ -14,46 +14,17 @@
You should have received a copy of the GNU General Public License along
with this program. If not, see <http://www.gnu.org/licenses/>. */
-#if defined(HAVE_CONFIG_H)
-# include <config.h>
-#endif
-#ifdef HAVE__PAM_ACONF_H
-#include <security/_pam_aconf.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <syslog.h>
-#include <stdarg.h>
-#include <ctype.h>
-#define obstack_chunk_alloc malloc
-#define obstack_chunk_free free
-#include <obstack.h>
-
-#define PAM_SM_AUTH
-#define PAM_SM_PASSWORD
-#include <security/pam_modules.h>
-
-#include <common.c>
+#include <graypam.h>
/* Command line parsing */
-#define CNTL_DEBUG 0x0001
-#define CNTL_AUDIT 0x0002
-#define CNTL_WAITDEBUG 0x0004
-
-#define CNTL_DEBUG_LEV() (cntl_flags>>16)
-#define CNTL_SET_DEBUG_LEV(cntl,n) (cntl |= ((n)<<16))
-
static int cntl_flags;
static int xargc;
static const char **xargv;
static int priority = LOG_INFO;
-
-#define DEBUG(m,c) if (CNTL_DEBUG_LEV()>=(m)) _pam_debug c
-#define AUDIT(c) if (cntl_flags&CNTL_AUDIT) _pam_debug c
+static int facility = LOG_AUTHPRIV;
+static const char *syslog_tag =MODULE_NAME;
struct keyword {
char *name;
@@ -137,7 +108,8 @@ static void
_pam_parse(pam_handle_t *pamh, int argc, const char **argv)
{
int ctrl = 0;
-
+ int dont_open = 0;
+
/* Collect generic arguments */
for (; argc > 0; argv++, argc--) {
if (!strncmp(*argv, "-debug", 6)) {
@@ -155,7 +127,7 @@ _pam_parse(pam_handle_t *pamh, int argc, const char **argv)
else if (!strncmp(*argv, "-pri=", 5))
parse_priority(*argv + 5);
else if (!strcmp(*argv, "-no-open"))
- syslog_dont_open = 1;
+ dont_open = 1;
else if (!strcmp(*argv, "--"))
break;
else if (**argv == '-')
@@ -170,6 +142,8 @@ _pam_parse(pam_handle_t *pamh, int argc, const char **argv)
xargv = argv;
cntl_flags = ctrl;
+
+ gray_log_init(dont_open, syslog_tag, facility);
}
static struct keyword vartab[] = {
@@ -214,7 +188,7 @@ repl_tok(const char *str, const char ** pret, size_t *plen)
}
static int
-get_variable(pam_handle_t *pamh, const char *str, struct obstack *stk,
+get_variable(pam_handle_t *pamh, const char *str, gray_slist_t slist,
const char **endp)
{
const char *name;
@@ -277,36 +251,37 @@ get_variable(pam_handle_t *pamh, const char *str, struct obstack *stk,
} else
vallen = strlen(val);
- obstack_grow(stk, val, vallen);
+ gray_slist_append(slist, val, vallen);
*endp = end;
return 0;
}
static void
-expand_string(pam_handle_t *pamh, struct obstack *stk)
+expand_string(pam_handle_t *pamh, gray_slist_t slist)
{
int i;
for (i = 0; i < xargc; i++) {
DEBUG(2,("%s: %d %s", __FUNCTION__, i, xargv[i]));
if (i > 0)
- obstack_1grow(stk, ' ');
+ gray_slist_append_char(slist, ' ');
if (strchr(xargv[i], '$') == 0)
- obstack_grow(stk, xargv[i], strlen(xargv[i]));
+ gray_slist_append(slist, xargv[i], strlen(xargv[i]));
else {
const char *p;
for (p = xargv[i]; *p; p++) {
if (*p == '\\') {
p++;
- obstack_1grow(stk, *p);
+ gray_slist_append_char(slist, *p);
} else if (*p == '$') {
- if (get_variable(pamh, p, stk, &p))
- obstack_1grow(stk, *p);
+ if (get_variable(pamh, p, slist, &p))
+ gray_slist_append_char(slist,
+ *p);
else
p--;
} else
- obstack_1grow(stk, *p);
+ gray_slist_append_char(slist, *p);
}
}
}
@@ -316,19 +291,19 @@ static int
echo(pam_handle_t *pamh, const char *prefix, int argc, const char **argv)
{
char *str;
- struct obstack stk;
+ gray_slist_t slist;
_pam_parse(pamh, argc, argv);
- obstack_init(&stk);
+ slist = gray_slist_create();
if (prefix) {
- obstack_grow(&stk, prefix, strlen(prefix));
- obstack_grow(&stk, ": ", 2);
+ gray_slist_append(slist, prefix, strlen(prefix));
+ gray_slist_append(slist, ": ", 2);
}
- expand_string(pamh, &stk);
- obstack_1grow(&stk, 0);
- str = obstack_finish(&stk);
+ expand_string(pamh, slist);
+ gray_slist_append_char(slist, 0);
+ str = gray_slist_finish(slist);
_pam_log(priority, "%s", str);
- obstack_free(&stk, NULL);
+ gray_slist_free(&slist);
return PAM_IGNORE;
}
diff --git a/pam_regex/Makefile.am b/pam_regex/Makefile.am
index 798b54d..a29daec 100644
--- a/pam_regex/Makefile.am
+++ b/pam_regex/Makefile.am
@@ -1,4 +1,4 @@
-# Copyright (C) 2001, 2006 Sergey Poznyakoff
+# Copyright (C) 2001, 2006, 2008 Sergey Poznyakoff
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -16,19 +16,15 @@
pamdir=@PAMDIR@
pam_PROGRAMS = pam_regex.la
pam_regex_la_SOURCES = pam_regex.c
+pam_regex_la_LDADD = ../lib/libgraypam.la
AM_INSTALLCHECK_STD_OPTIONS_EXEMPT = pam_regex.la
-pam_regex_la_LDADD = -lpam
+LDADD = -lpam ../lib/libgraypam.la
AM_LDFLAGS = -version-info @VI_CURRENT@:@VI_REVISION@:@VI_AGE@
AM_CPPFLAGS=-DMODULE_NAME=\"pam_regex\" -DSYSCONFDIR=\"${sysconfdir}\"
-INCLUDES=@PAM_COMMON_INCLUDES@
+INCLUDES=-I. @PAM_COMMON_INCLUDES@
NORMAL_UNINSTALL = -rm -f $(DESTDIR)$(pamdir)/pam_regex.a $(DESTDIR)$(pamdir)/pam_regex.so.@VI_CURRENT@.@VI_REVISION@.@VI_AGE@
-pam_regex.lo: $(srcdir)/pam_regex.c
- $(LIBTOOL) --mode=compile $(CC) -c -DHAVE_CONFIG_H \
- $(CFLAGS) $(AM_CFLAGS) $(INCLUDES) $(CPPFLAGS) $(AM_CPPFLAGS) $<
+include $(top_srcdir)/Make.rules
-pam_regex.la$(EXEEXT): pam_regex.lo
- $(LIBTOOL) --mode=link $(CC) -module -export-dynamic \
- $(AM_LDFLAGS) \
- -o $@ $< $(pam_regex_la_LDADD) $(AM_LDADD) $(LDADD)\
- -rpath $(pamdir)
+pam_regex.lo: pam_regex.c
+pam_regex.la: pam_regex.lo
diff --git a/pam_regex/pam_regex.c b/pam_regex/pam_regex.c
index 4d0eb3c..8529917 100644
--- a/pam_regex/pam_regex.c
+++ b/pam_regex/pam_regex.c
@@ -1,5 +1,5 @@
/* This file is part of pam-modules.
- Copyright (C) 2001, 2006, 2007 Sergey Poznyakoff
+ Copyright (C) 2001, 2006, 2007, 2008 Sergey Poznyakoff
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
@@ -14,9 +14,6 @@
You should have received a copy of the GNU General Public License along
with this program. If not, see <http://www.gnu.org/licenses/>. */
-#if defined(HAVE_CONFIG_H)
-# include <config.h>
-#endif
#ifdef HAVE__PAM_ACONF_H
#include <security/_pam_aconf.h>
#endif
@@ -31,6 +28,8 @@
#include <errno.h>
#include <regex.h>
+#include "graypam.h"
+
/* indicate the following groups are defined */
#define PAM_SM_AUTH
@@ -39,31 +38,26 @@
#endif /* LINUX_PAM */
#include <security/pam_modules.h>
-#include <common.c>
-
-#define CNTL_DEBUG 0x0001
-#define CNTL_AUDIT 0x0002
-#define CNTL_AUTHTOK 0x0004
-
-#define CNTL_SENSE_DENY 0x0010
-#define CNTL_REGEX_FLAGS 0x0020
+#define CNTL_AUTHTOK 0x0010
+#define CNTL_REGEX_FLAGS 0x0012
-#define CNTL_DEBUG_LEV() (cntl_flags>>16)
-#define CNTL_SET_DEBUG_LEV(cntl,n) (cntl |= ((n)<<16))
+#define SENSE_ALLOW 0
+#define SENSE_DENY 1
+static int sense;
static int cntl_flags;
static const char *regex = NULL;
static int regex_flags = REG_NOSUB;
-static const char *user_name = NULL;
-
-#define DEBUG(m,c) if (CNTL_DEBUG_LEV()>=(m)) _pam_debug c
-#define AUDIT(c) if (cntl_flags&CNTL_AUDIT) _pam_debug c
+static const char *transform = NULL;
+static const char *user_name;
static void
_pam_parse(pam_handle_t *pamh, int argc, const char **argv)
{
int ctrl = 0;
+ gray_log_init(0, MODULE_NAME, LOG_AUTHPRIV);
+
/* step through arguments */
for (; argc-- > 0; ++argv) {
@@ -83,11 +77,17 @@ _pam_parse(pam_handle_t *pamh, int argc, const char **argv)
ctrl |= CNTL_AUTHTOK;
else if (!strncmp(*argv, "sense=", 6)) {
if (strcmp(*argv + 6, "deny") == 0)
- ctrl |= CNTL_SENSE_DENY;
- else if (strcmp(*argv + 6, "allow"))
+ sense = SENSE_DENY;
+ else if (strcmp(*argv + 6, "allow") == 0)
+ sense = SENSE_ALLOW;
+ else
_pam_log(LOG_ERR,"unknown sense value: %s",
*argv + 6);
- } else if (!strncmp(*argv, "regex=", 6))
+ } else if (!strncmp(*argv, "transform=", 10))
+ transform = *argv + 10;
+ else if (!strncmp(*argv, "user=",5))
+ user_name = *argv + 5;
+ else if (!strncmp(*argv, "regex=", 6))
regex = *argv + 6;
else if (!strcmp(*argv, "extended")) {
regex_flags |= REG_EXTENDED;
@@ -102,8 +102,6 @@ _pam_parse(pam_handle_t *pamh, int argc, const char **argv)
} else if (!strcmp(*argv, "case")) {
regex_flags &= ~REG_ICASE;
ctrl |= CNTL_REGEX_FLAGS;
- } else if (!strncmp(*argv, "user=",5)) {
- user_name = *argv + 5;
} else {
_pam_log(LOG_ERR,
"unknown option: %s", *argv);
@@ -111,7 +109,9 @@ _pam_parse(pam_handle_t *pamh, int argc, const char **argv)
}
if (!regex)
_pam_log(LOG_ERR, "regex not specified");
- if (!ctrl & CNTL_REGEX_FLAGS)
+ if (user_name && transform)
+ _pam_log(LOG_ERR, "Both `user' and `transform' are given");
+ if (!(ctrl & CNTL_REGEX_FLAGS))
regex_flags |= REG_EXTENDED;
cntl_flags = ctrl;
}
@@ -123,7 +123,7 @@ _pam_parse(pam_handle_t *pamh, int argc, const char **argv)
/* Fun starts here :)
- * pam_sm_authenticate() performs RADIUS authentication
+ * pam_sm_authenticate() performs authentication
*
*/
@@ -133,56 +133,80 @@ pam_sm_authenticate(pam_handle_t *pamh,
int argc,
const char **argv)
{
- int retval;
+ int retval, rc;
char *name;
regex_t rx;
-
+ regmatch_t rmatch[2];
+
_pam_parse(pamh, argc, argv);
DEBUG(100,("enter pam_sm_authenticate"));
if (!regex)
return PAM_AUTHINFO_UNAVAIL;
-
- for (;;) {
-
- /*
- * get username
- */
- retval = pam_get_user(pamh, (const char**)&name, "login: ");
- if (retval == PAM_SUCCESS) {
- DEBUG(10, ("username [%s] obtained", name));
- } else {
- _pam_log(LOG_NOTICE, "can't get username");
- break;
- }
- if (regcomp(&rx, regex, regex_flags)) {
- _pam_log(LOG_NOTICE, "can't compile regex: %s", regex);
- retval = PAM_AUTHINFO_UNAVAIL;
- break;
- }
+ gray_pam_init(PAM_AUTHINFO_UNAVAIL);
- retval = regexec(&rx, name, 0, NULL, 0);
- if (retval) {
- DEBUG(1,("%s does not match %s",name,regex));
- }
- if (cntl_flags & CNTL_SENSE_DENY)
- retval = !retval;
- if (retval) {
- _pam_log(LOG_NOTICE, "rejecting %s", name);
- retval = PAM_AUTH_ERR;
- } else {
- _pam_log(LOG_NOTICE, "allowing %s", name);
- if (user_name) {
- retval = pam_set_item(pamh, PAM_USER,
- strdup(user_name));
- DEBUG(100,("user name=%s, status=%d",
- user_name,retval));
+ /*
+ * get username
+ */
+ retval = pam_get_user(pamh, (const char**)&name, "login: ");
+ if (retval == PAM_SUCCESS) {
+ DEBUG(10, ("username [%s] obtained", name));
+ } else {
+ _pam_log(LOG_NOTICE, "can't get username");
+ return PAM_AUTHINFO_UNAVAIL;
+ }
+
+ if (transform) {
+ char *newname;
+ gray_slist_t slist;
+
+ gray_set_transform_expr(transform);
+ slist = gray_slist_create();
+ gray_transform_name_to_slist(slist, name, &newname);
+ DEBUG(100,("new name: %s", newname));
+ MAKE_STR(pamh, newname, name);
+ pam_set_item(pamh, PAM_AUTHTOK, name);
+ }
+
+ if (regex) {
+ for (;;) {
+
+ if (rc = regcomp(&rx, regex, regex_flags)) {
+ char errbuf[512];
+ regerror (rc, &rx, errbuf, sizeof (errbuf));
+ _pam_log(LOG_ERR, "can't compile regex: %s",
+ errbuf);
+ retval = PAM_AUTHINFO_UNAVAIL;
+ break;
+ }
+
+ retval = regexec(&rx, name, 2, rmatch, 0);
+ if (retval) {
+ DEBUG(1,("%s does not match %s",name,regex));
}
- retval = PAM_SUCCESS;
+
+ switch (sense) {
+ case SENSE_ALLOW:
+ break;
+
+ case SENSE_DENY:
+ retval = !retval;
+ break;
+
+ }
+
+ if (retval != PAM_SUCCESS) {
+ _pam_log(LOG_NOTICE, "rejecting %s", name);
+ retval = PAM_AUTH_ERR;
+ if (user_name)
+ retval = pam_set_item(pamh, PAM_USER,
+ strdup(user_name));
+ } else
+ _pam_log(LOG_NOTICE, "allowing %s", name);
+ break;
}
- break;
}
DEBUG(100,("exit pam_sm_authenticate: %d", retval));
diff --git a/pam_sql/Makefile.am b/pam_sql/Makefile.am
index b9b6c65..36cea87 100644
--- a/pam_sql/Makefile.am
+++ b/pam_sql/Makefile.am
@@ -1,4 +1,4 @@
-# Copyright (C) 2005, 2006 Sergey Poznyakoff
+# Copyright (C) 2005, 2006, 2008 Sergey Poznyakoff
#
# This file is free software; as a special exception the author gives
# unlimited permission to copy and/or distribute it, with or without
@@ -13,6 +13,7 @@ pam_PROGRAMS = @SQL_MODULES@
AM_INSTALLCHECK_STD_OPTIONS_EXEMPT = pam_mysql.la pam_pgsql.la
EXTRA_PROGRAMS = pam_mysql.la pam_pgsql.la
EXTRA_DIST = sha1.h sha1.c pam_sql.c md5.c md5.h
+LDADD = ../lib/libgraypam.la
pam_mysql_la_SOURCES = pam_mysql.c pam_sql.c
pam_mysql_la_LDADD = -lpam @MYSQLLIBS@
pam_pgsql_la_SOURCES = pam_pgsql.c pam_sql.c
diff --git a/pam_sql/pam_mysql.c b/pam_sql/pam_mysql.c
index a78246a..5d5c16a 100644
--- a/pam_sql/pam_mysql.c
+++ b/pam_sql/pam_mysql.c
@@ -1,5 +1,5 @@
/* This file is part of pam-modules.
- Copyright (C) 2005, 2006, 2007 Sergey Poznyakoff
+ Copyright (C) 2005, 2006, 2007, 2008 Sergey Poznyakoff
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
@@ -14,18 +14,7 @@
You should have received a copy of the GNU General Public License along
with this program. If not, see <http://www.gnu.org/licenses/>. */
-#if defined(HAVE_CONFIG_H)
-# include <config.h>
-#endif
-#ifdef HAVE__PAM_ACONF_H
-#include <security/_pam_aconf.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <unistd.h>
+#include <graypam.h>
#include <mysql/mysql.h>
#include "pam_sql.c"
diff --git a/pam_sql/pam_pgsql.c b/pam_sql/pam_pgsql.c
index 97374a3..76a9ebc 100644
--- a/pam_sql/pam_pgsql.c
+++ b/pam_sql/pam_pgsql.c
@@ -1,5 +1,5 @@
/* This file is part of pam-modules.
- Copyright (C) 2005, 2006, 2007 Sergey Poznyakoff
+ Copyright (C) 2005, 2006, 2007, 2008 Sergey Poznyakoff
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
@@ -14,18 +14,7 @@
You should have received a copy of the GNU General Public License along
with this program. If not, see <http://www.gnu.org/licenses/>. */
-#if defined(HAVE_CONFIG_H)
-# include <config.h>
-#endif
-#ifdef HAVE__PAM_ACONF_H
-#include <security/_pam_aconf.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <unistd.h>
+#include <graypam.h>
#include <libpq-fe.h>
#include "pam_sql.c"
diff --git a/pam_sql/pam_sql.c b/pam_sql/pam_sql.c
index bad485f..6f54c7d 100644
--- a/pam_sql/pam_sql.c
+++ b/pam_sql/pam_sql.c
@@ -1,5 +1,5 @@
/* This file is part of pam-modules.
- Copyright (C) 2005, 2006, 2007 Sergey Poznyakoff
+ Copyright (C) 2005, 2006, 2007, 2008 Sergey Poznyakoff
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
@@ -14,30 +14,16 @@
You should have received a copy of the GNU General Public License along
with this program. If not, see <http://www.gnu.org/licenses/>. */
-#if defined(HAVE_CONFIG_H)
-# include <config.h>
-#endif
-#ifdef HAVE__PAM_ACONF_H
-# include <security/_pam_aconf.h>
-#endif
-#include <security/pam_modules.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <unistd.h>
-#include <ctype.h>
-#include <syslog.h>
-#include <errno.h>
+#include <graypam.h>
#if defined(HAVE_CRYPT_H)
# include <crypt.h>
+#else
+extern char *crypt(const char *, const char *);
#endif
/* indicate the following groups are defined */
#define PAM_SM_AUTH
-#include <common.c>
-
#define CHKVAR(v) \
if (!(v)) { \
_pam_log(LOG_ERR, "%s: %s not defined", config_file, #v); \
@@ -47,15 +33,7 @@
static int verify_user_pass(const char *username, const char *password);
-#define CNTL_DEBUG 0x0001
-#define CNTL_AUDIT 0x0002
-#define CNTL_AUTHTOK 0x0004
-
-#define CNTL_SET_DEBUG_LEV(cntl,n) (cntl |= ((n)<<16))
-#define CNTL_DEBUG_LEV() (cntl_flags>>16)
-
-#define DEBUG(m,c) if (CNTL_DEBUG_LEV()>=(m)) _pam_debug c
-#define AUDIT(c) if (cntl_flags&CNTL_AUDIT) _pam_debug c
+#define CNTL_AUTHTOK 0x0010
static int cntl_flags;
char *config_file = SYSCONFDIR "/pam_sql.conf";
@@ -65,6 +43,8 @@ _pam_parse(int argc, const char **argv)
{
int ctrl=0;
+ gray_log_init(0, MODULE_NAME, LOG_AUTHPRIV);
+
/* step through arguments */
for (ctrl=0; argc-- > 0; ++argv) {
@@ -93,45 +73,6 @@ _pam_parse(int argc, const char **argv)
}
-/* FIXME: Duplicated in pam_fshadow */
-static int
-converse(pam_handle_t *pamh,
- int nargs,
- struct pam_message **message,
- struct pam_response **response)
-{
- int retval;
- struct pam_conv *conv;
-
- DEBUG(100,("enter converse"));
-
- retval = pam_get_item(pamh, PAM_CONV, (const void **) &conv);
- DEBUG(10,("pam_get_item(PAM_CONV): %d", retval));
- if (retval == PAM_SUCCESS) {
-
- retval = conv->conv(nargs,
- (const struct pam_message **) message,
- response,
- conv->appdata_ptr);
-
- DEBUG(10, ("app conversation returned %d", retval));
-
- if (retval != PAM_SUCCESS) {
- _pam_log(LOG_ERR,
- "conversation failure [%s]",
- pam_strerror(pamh, retval));
- }
- } else if (retval != PAM_CONV_AGAIN) {
- _pam_log(LOG_ERR,
- "couldn't obtain coversation function: %s",
- pam_strerror(pamh, retval));
- }
-
- DEBUG(100,("exit converse: %d", retval));
-
- return retval; /* propagate error status */
-}
-
static int
_pam_get_password(pam_handle_t *pamh, char **password, const char *prompt)
{
@@ -177,7 +118,7 @@ _pam_get_password(pam_handle_t *pamh, char **password, const char *prompt)
/* run conversation */
resp = NULL;
token = NULL;
- retval = converse(pamh, i, pmsg, &resp);
+ retval = gray_converse(pamh, i, pmsg, &resp);
if (resp != NULL) {
if (retval == PAM_SUCCESS) { /* a good conversation */
@@ -201,12 +142,12 @@ _pam_get_password(pam_handle_t *pamh, char **password, const char *prompt)
*/
retval = pam_set_data(pamh, "password",
(void *)token,
- _cleanup_string);
+ gray_cleanup_string);
if (retval != PAM_SUCCESS) {
_pam_log(LOG_CRIT,
"can't keep password: %s",
pam_strerror(pamh, retval));
- _pam_delete(token);
+ gray_pam_delete(token);
} else {
*password = token;
token = NULL; /* break link to password */

Return to:

Send suggestions and report system problems to the System administrator.