diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2008-03-13 13:53:32 +0000 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2008-03-13 13:53:32 +0000 |
commit | 222d4ff80720206deeb8e7ee87831812628329af (patch) | |
tree | ccf4a8ed8e19e8b9b1c33b6a27cb95f51b1ec256 | |
parent | f9f6f80133f16fb1fc6c064bee5fe5c53a17c9d8 (diff) | |
download | pam-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
-rw-r--r-- | ChangeLog | 17 | ||||
-rw-r--r-- | Make.rules | 26 | ||||
-rw-r--r-- | Makefile.am | 5 | ||||
-rw-r--r-- | NEWS | 14 | ||||
-rw-r--r-- | common.c | 150 | ||||
-rw-r--r-- | configure.ac | 5 | ||||
-rw-r--r-- | doc/pam-modules.texi | 80 | ||||
-rw-r--r-- | lib/Makefile.am | 19 | ||||
-rw-r--r-- | lib/converse.c | 49 | ||||
-rw-r--r-- | lib/graypam.h | 149 | ||||
-rw-r--r-- | lib/log.c | 79 | ||||
-rw-r--r-- | lib/mem.c | 99 | ||||
-rw-r--r-- | lib/slist.c | 244 | ||||
-rw-r--r-- | lib/transform.c | 533 | ||||
-rw-r--r-- | pam_fshadow/Makefile.am | 15 | ||||
-rw-r--r-- | pam_fshadow/pam_fshadow.c | 97 | ||||
-rw-r--r-- | pam_log/Makefile.am | 15 | ||||
-rw-r--r-- | pam_log/pam_log.c | 79 | ||||
-rw-r--r-- | pam_regex/Makefile.am | 18 | ||||
-rw-r--r-- | pam_regex/pam_regex.c | 150 | ||||
-rw-r--r-- | pam_sql/Makefile.am | 3 | ||||
-rw-r--r-- | pam_sql/pam_mysql.c | 15 | ||||
-rw-r--r-- | pam_sql/pam_pgsql.c | 15 | ||||
-rw-r--r-- | pam_sql/pam_sql.c | 79 |
24 files changed, 1475 insertions, 480 deletions
@@ -1 +1,18 @@ +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> diff --git a/Make.rules b/Make.rules new file mode 100644 index 0000000..ecf28eb --- /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,2 +1,2 @@ -# Copyright (C) 2001, 2006 Sergey Poznyakoff +# Copyright (C) 2001, 2006, 2008 Sergey Poznyakoff # @@ -16,3 +16,2 @@ 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 @@ -1,3 +1,3 @@ -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. @@ -6,5 +6,9 @@ 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. @@ -39,3 +43,3 @@ Copyright information: -Copyright (C) 2001,2004,2005 Sergey Poznyakoff +Copyright (C) 2001,2004,2005,2007,2008 Sergey Poznyakoff diff --git a/common.c b/common.c deleted file mode 100644 index 6004929..0000000 --- a/common.c +++ /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 @@ -28,3 +28,3 @@ 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') @@ -183,3 +183,4 @@ fi]) AC_OUTPUT(Makefile - doc/Makefile + doc/Makefile + lib/Makefile pam_fshadow/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 @@ -273,5 +273,5 @@ for the user name @samp{smith} in the files 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}. @@ -307,2 +307,76 @@ options (see above). +@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 diff --git a/lib/Makefile.am b/lib/Makefile.am new file mode 100644 index 0000000..1a5acea --- /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 --- /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 --- /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 --- /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 --- /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 --- /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; |