diff --git a/configure b/configure index eb88c4e76e6..425c56e17a2 100755 --- a/configure +++ b/configure @@ -24821,6 +24821,98 @@ esac +# Check for fnmatch() +{ echo "$as_me:$LINENO: checking for working POSIX fnmatch" >&5 +echo $ECHO_N "checking for working POSIX fnmatch... $ECHO_C" >&6; } +if test "${ac_cv_func_fnmatch_works+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Some versions of Solaris, SCO, and the GNU C Library + # have a broken or incompatible fnmatch. + # So we run a test program. If we are cross-compiling, take no chance. + # Thanks to John Oleynick, Franc,ois Pinard, and Paul Eggert for this test. + if test "$cross_compiling" = yes; then + ac_cv_func_fnmatch_works=cross +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +# define y(a, b, c) (fnmatch (a, b, c) == 0) +# define n(a, b, c) (fnmatch (a, b, c) == FNM_NOMATCH) + +int +main () +{ +return + (!(y ("a*", "abc", 0) + && n ("d*/*1", "d/s/1", FNM_PATHNAME) + && y ("a\\\\bc", "abc", 0) + && n ("a\\\\bc", "abc", FNM_NOESCAPE) + && y ("*x", ".x", 0) + && n ("*x", ".x", FNM_PERIOD) + && 1)); + ; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_fnmatch_works=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_func_fnmatch_works=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_fnmatch_works" >&5 +echo "${ECHO_T}$ac_cv_func_fnmatch_works" >&6; } +if test $ac_cv_func_fnmatch_works = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_FNMATCH 1 +_ACEOF + +fi + + + +if test x"$ac_cv_func_fnmatch_works" != x"yes"; then + case " $LIBOBJS " in + *" fnmatch.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS fnmatch.$ac_objext" + ;; +esac + +fi # Select semaphore implementation type. if test "$PORTNAME" != "win32"; then diff --git a/configure.in b/configure.in index 64b8b4eca3d..f8f507cd0c3 100644 --- a/configure.in +++ b/configure.in @@ -1,5 +1,5 @@ dnl Process this file with autoconf to produce a configure script. -dnl $PostgreSQL: pgsql/configure.in,v 1.572 2008/11/18 13:10:20 petere Exp $ +dnl $PostgreSQL: pgsql/configure.in,v 1.573 2008/11/24 09:15:15 mha Exp $ dnl dnl Developers, please strive to achieve this order: dnl @@ -1625,6 +1625,11 @@ fi # SunOS doesn't handle negative byte comparisons properly with +/- return AC_FUNC_MEMCMP +# Check for fnmatch() +AC_FUNC_FNMATCH +if test x"$ac_cv_func_fnmatch_works" != x"yes"; then + AC_LIBOBJ(fnmatch) +fi # Select semaphore implementation type. if test "$PORTNAME" != "win32"; then diff --git a/src/include/fnmatchstub.h b/src/include/fnmatchstub.h new file mode 100644 index 00000000000..fb23d8f98ce --- /dev/null +++ b/src/include/fnmatchstub.h @@ -0,0 +1,27 @@ +/*------------------------------------------------------------------------- + * + * fnmatchstub.h + * Stubs for fnmatch() in port/fnmatch.c + * + * + * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * $PostgreSQL: pgsql/src/include/fnmatchstub.h,v 1.1 2008/11/24 09:15:16 mha Exp $ + * + *------------------------------------------------------------------------- + */ +#ifndef FNMATCHSTUB_H +#define FNMATCHSTUB_H + +extern int fnmatch(const char *, const char *, int); +#define FNM_NOMATCH 1 /* Match failed. */ +#define FNM_NOSYS 2 /* Function not implemented. */ +#define FNM_NOESCAPE 0x01 /* Disable backslash escaping. */ +#define FNM_PATHNAME 0x02 /* Slash must be matched by slash. */ +#define FNM_PERIOD 0x04 /* Period must be matched by period. */ +#define FNM_CASEFOLD 0x08 /* Pattern is matched case-insensitive */ +#define FNM_LEADING_DIR 0x10 /* Ignore / after Imatch. */ + + +#endif diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in index 9f6f21bf817..1064d155260 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -143,6 +143,9 @@ /* Define to 1 if you have the `fdatasync' function. */ #undef HAVE_FDATASYNC +/* Define to 1 if your system has a working POSIX `fnmatch' function. */ +#undef HAVE_FNMATCH + /* Define to 1 if you have the `fpclass' function. */ #undef HAVE_FPCLASS diff --git a/src/interfaces/libpq/Makefile b/src/interfaces/libpq/Makefile index 3d2646b8833..82a7fc26c17 100644 --- a/src/interfaces/libpq/Makefile +++ b/src/interfaces/libpq/Makefile @@ -5,7 +5,7 @@ # Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # -# $PostgreSQL: pgsql/src/interfaces/libpq/Makefile,v 1.168 2008/10/01 15:35:32 mha Exp $ +# $PostgreSQL: pgsql/src/interfaces/libpq/Makefile,v 1.169 2008/11/24 09:15:16 mha Exp $ # #------------------------------------------------------------------------- @@ -34,7 +34,7 @@ OBJS= fe-auth.o fe-connect.o fe-exec.o fe-misc.o fe-print.o fe-lobj.o \ fe-protocol2.o fe-protocol3.o pqexpbuffer.o pqsignal.o fe-secure.o \ libpq-events.o \ md5.o ip.o wchar.o encnames.o noblock.o pgstrcasecmp.o thread.o \ - $(filter crypt.o getaddrinfo.o inet_aton.o open.o snprintf.o strerror.o strlcpy.o win32error.o, $(LIBOBJS)) + $(filter crypt.o fnmatch.o getaddrinfo.o inet_aton.o open.o snprintf.o strerror.o strlcpy.o win32error.o, $(LIBOBJS)) ifeq ($(PORTNAME), cygwin) override shlib = cyg$(NAME)$(DLSUFFIX) @@ -80,7 +80,7 @@ backend_src = $(top_srcdir)/src/backend # For port modules, this only happens if configure decides the module # is needed (see filter hack in OBJS, above). -crypt.c getaddrinfo.c inet_aton.c noblock.c open.c pgstrcasecmp.c snprintf.c strerror.c strlcpy.c thread.c win32error.c pgsleep.c: % : $(top_srcdir)/src/port/% +crypt.c fnmatch.c getaddrinfo.c inet_aton.c noblock.c open.c pgstrcasecmp.c snprintf.c strerror.c strlcpy.c thread.c win32error.c pgsleep.c: % : $(top_srcdir)/src/port/% rm -f $@ && $(LN_S) $< . md5.c ip.c: % : $(backend_src)/libpq/% @@ -123,7 +123,7 @@ uninstall: uninstall-lib rm -f '$(DESTDIR)$(datadir)/pg_service.conf.sample' clean distclean: clean-lib - rm -f $(OBJS) pg_config_paths.h crypt.c getaddrinfo.c inet_aton.c noblock.c open.c pgstrcasecmp.c snprintf.c strerror.c strlcpy.c thread.c md5.c ip.c encnames.c wchar.c win32error.c pgsleep.c pthread.h libpq.rc + rm -f $(OBJS) pg_config_paths.h crypt.c fnmatch.c getaddrinfo.c inet_aton.c noblock.c open.c pgstrcasecmp.c snprintf.c strerror.c strlcpy.c thread.c md5.c ip.c encnames.c wchar.c win32error.c pgsleep.c pthread.h libpq.rc # Might be left over from a Win32 client-only build rm -f pg_config_paths.h diff --git a/src/interfaces/libpq/fe-secure.c b/src/interfaces/libpq/fe-secure.c index 1cc7c5cbfb0..c72feeb0b23 100644 --- a/src/interfaces/libpq/fe-secure.c +++ b/src/interfaces/libpq/fe-secure.c @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.107 2008/11/13 09:45:25 mha Exp $ + * $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.108 2008/11/24 09:15:16 mha Exp $ * * NOTES * @@ -63,6 +63,13 @@ #if (SSLEAY_VERSION_NUMBER >= 0x00907000L) && !defined(OPENSSL_NO_ENGINE) #include #endif + +/* fnmatch() needed for client certificate checking */ +#ifdef HAVE_FNMATCH +#include +#else +#include "fnmatchstub.h" +#endif #endif /* USE_SSL */ @@ -461,17 +468,20 @@ verify_peer_name_matches_certificate(PGconn *conn) * Connect by hostname. * * XXX: Should support alternate names here - * XXX: Should support wildcard certificates here */ - if (pg_strcasecmp(conn->peer_cn, conn->pghost) != 0) + if (pg_strcasecmp(conn->peer_cn, conn->pghost) == 0) + /* Exact name match */ + return true; + else if (fnmatch(conn->peer_cn, conn->pghost, FNM_NOESCAPE | FNM_CASEFOLD) == 0) + /* Matched wildcard certificate */ + return true; + else { printfPQExpBuffer(&conn->errorMessage, libpq_gettext("server common name '%s' does not match hostname '%s'"), conn->peer_cn, conn->pghost); return false; } - else - return true; } } diff --git a/src/port/fnmatch.c b/src/port/fnmatch.c new file mode 100644 index 00000000000..c7fbc54a317 --- /dev/null +++ b/src/port/fnmatch.c @@ -0,0 +1,198 @@ +/*------------------------------------------------------------------------- + * + * fnmatch.c + * fnmatch() - wildcard matching function + * + * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group + * + * + * IDENTIFICATION + * $PostgreSQL: pgsql/src/port/fnmatch.c,v 1.1 2008/11/24 09:15:16 mha Exp $ + * + * This file was taken from NetBSD and is used on platforms that don't + * provide fnmatch(). The NetBSD copyright terms follow. + *------------------------------------------------------------------------- + */ + +/* $NetBSD: fnmatch.c,v 1.21 2005/12/24 21:11:16 perry Exp $ */ + +/* + * Copyright (c) 1989, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Guido van Rossum. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Function fnmatch() as specified in POSIX 1003.2-1992, section B.6. + * Compares a filename or pathname to a pattern. + */ + +#include "c.h" +#include "fnmatchstub.h" + +#define EOS '\0' + +static const char *rangematch (const char *, int, int); + +static inline int +foldcase(int ch, int flags) +{ + + if ((flags & FNM_CASEFOLD) != 0 && isupper(ch)) + return (tolower(ch)); + return (ch); +} + +#define FOLDCASE(ch, flags) foldcase((unsigned char)(ch), (flags)) + +int +fnmatch(pattern, string, flags) + const char *pattern, *string; + int flags; +{ + const char *stringstart; + char c, test; + + for (stringstart = string;;) + switch (c = FOLDCASE(*pattern++, flags)) { + case EOS: + if ((flags & FNM_LEADING_DIR) && *string == '/') + return (0); + return (*string == EOS ? 0 : FNM_NOMATCH); + case '?': + if (*string == EOS) + return (FNM_NOMATCH); + if (*string == '/' && (flags & FNM_PATHNAME)) + return (FNM_NOMATCH); + if (*string == '.' && (flags & FNM_PERIOD) && + (string == stringstart || + ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) + return (FNM_NOMATCH); + ++string; + break; + case '*': + c = FOLDCASE(*pattern, flags); + /* Collapse multiple stars. */ + while (c == '*') + c = FOLDCASE(*++pattern, flags); + + if (*string == '.' && (flags & FNM_PERIOD) && + (string == stringstart || + ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) + return (FNM_NOMATCH); + + /* Optimize for pattern with * at end or before /. */ + if (c == EOS) { + if (flags & FNM_PATHNAME) + return ((flags & FNM_LEADING_DIR) || + strchr(string, '/') == NULL ? + 0 : FNM_NOMATCH); + else + return (0); + } else if (c == '/' && flags & FNM_PATHNAME) { + if ((string = strchr(string, '/')) == NULL) + return (FNM_NOMATCH); + break; + } + + /* General case, use recursion. */ + while ((test = FOLDCASE(*string, flags)) != EOS) { + if (!fnmatch(pattern, string, + flags & ~FNM_PERIOD)) + return (0); + if (test == '/' && flags & FNM_PATHNAME) + break; + ++string; + } + return (FNM_NOMATCH); + case '[': + if (*string == EOS) + return (FNM_NOMATCH); + if (*string == '/' && flags & FNM_PATHNAME) + return (FNM_NOMATCH); + if ((pattern = + rangematch(pattern, FOLDCASE(*string, flags), + flags)) == NULL) + return (FNM_NOMATCH); + ++string; + break; + case '\\': + if (!(flags & FNM_NOESCAPE)) { + if ((c = FOLDCASE(*pattern++, flags)) == EOS) { + c = '\\'; + --pattern; + } + } + /* FALLTHROUGH */ + default: + if (c != FOLDCASE(*string++, flags)) + return (FNM_NOMATCH); + break; + } + /* NOTREACHED */ +} + +static const char * +rangematch(pattern, test, flags) + const char *pattern; + int test, flags; +{ + int negate, ok; + char c, c2; + + /* + * A bracket expression starting with an unquoted circumflex + * character produces unspecified results (IEEE 1003.2-1992, + * 3.13.2). This implementation treats it like '!', for + * consistency with the regular expression syntax. + * J.T. Conklin (conklin@ngai.kaleida.com) + */ + if ((negate = (*pattern == '!' || *pattern == '^')) != 0) + ++pattern; + + for (ok = 0; (c = FOLDCASE(*pattern++, flags)) != ']';) { + if (c == '\\' && !(flags & FNM_NOESCAPE)) + c = FOLDCASE(*pattern++, flags); + if (c == EOS) + return (NULL); + if (*pattern == '-' + && (c2 = FOLDCASE(*(pattern+1), flags)) != EOS && + c2 != ']') { + pattern += 2; + if (c2 == '\\' && !(flags & FNM_NOESCAPE)) + c2 = FOLDCASE(*pattern++, flags); + if (c2 == EOS) + return (NULL); + if (c <= test && test <= c2) + ok = 1; + } else if (c == test) + ok = 1; + } + return (ok == negate ? NULL : pattern); +} diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm index b24b8f2953b..172ce6ef93a 100644 --- a/src/tools/msvc/Mkvcbuild.pm +++ b/src/tools/msvc/Mkvcbuild.pm @@ -3,7 +3,7 @@ package Mkvcbuild; # # Package that generates build files for msvc build # -# $PostgreSQL: pgsql/src/tools/msvc/Mkvcbuild.pm,v 1.32 2008/11/14 22:12:37 mha Exp $ +# $PostgreSQL: pgsql/src/tools/msvc/Mkvcbuild.pm,v 1.33 2008/11/24 09:15:16 mha Exp $ # use Carp; use Win32; @@ -43,7 +43,7 @@ sub mkvcbuild $solution = new Solution($config); our @pgportfiles = qw( - chklocale.c crypt.c fseeko.c getrusage.c inet_aton.c random.c srandom.c + chklocale.c crypt.c fseeko.c fnmatch.c getrusage.c inet_aton.c random.c srandom.c unsetenv.c getaddrinfo.c gettimeofday.c kill.c open.c rand.c snprintf.c strlcat.c strlcpy.c copydir.c dirmod.c exec.c noblock.c path.c pipe.c pgsleep.c pgstrcasecmp.c qsort.c qsort_arg.c sprompt.c thread.c