aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2006-05-21 20:11:02 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2006-05-21 20:11:02 +0000
commit3d4dc1acf5047c2067c411e3403c27c5c41f45cf (patch)
tree8e578bb3d22964718f8c801fe360db2159f23901
parent8fe643b41b93823f8db54149f3b5b3741d6c3613 (diff)
downloadpostgresql-3d4dc1acf5047c2067c411e3403c27c5c41f45cf.tar.gz
postgresql-3d4dc1acf5047c2067c411e3403c27c5c41f45cf.zip
Add a new GUC parameter backslash_quote, which determines whether the SQL
parser will allow "\'" to be used to represent a literal quote mark. The "\'" representation has been deprecated for some time in favor of the SQL-standard representation "''" (two single quote marks), but it has been used often enough that just disallowing it immediately won't do. Hence backslash_quote allows the settings "on", "off", and "safe_encoding", the last meaning to allow "\'" only if client_encoding is a valid server encoding. That is now the default, and the reason is that in encodings such as SJIS that allow 0x5c (ASCII backslash) to be the last byte of a multibyte character, accepting "\'" allows SQL-injection attacks as per CVE-2006-2314 (further details will be published after release). The "on" setting is available for backward compatibility, but it must not be used with clients that are exposed to untrusted input. Thanks to Akio Ishida and Yasuo Ohgaki for identifying this security issue.
-rw-r--r--doc/src/sgml/config.sgml31
-rw-r--r--src/backend/parser/scan.l17
-rw-r--r--src/backend/utils/misc/guc.c40
-rw-r--r--src/backend/utils/misc/postgresql.conf.sample5
-rw-r--r--src/include/parser/gramparse.h14
-rw-r--r--src/include/utils/guc.h3
6 files changed, 99 insertions, 11 deletions
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index bd4a5e552dc..bd0c8a6dcc9 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -1,5 +1,5 @@
<!--
-$PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.36.2.5 2006/04/18 12:41:29 momjian Exp $
+$PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.36.2.6 2006/05/21 20:11:02 tgl Exp $
-->
<chapter Id="runtime-config">
<title>Server Configuration</title>
@@ -3660,6 +3660,35 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir'
</listitem>
</varlistentry>
+ <varlistentry id="guc-backslash-quote" xreflabel="backslash_quote">
+ <term><varname>backslash_quote</varname> (<type>string</type>)</term>
+ <indexterm><primary>strings</><secondary>backslash quotes</></>
+ <indexterm>
+ <primary><varname>backslash_quote</> configuration parameter</primary>
+ </indexterm>
+ <listitem>
+ <para>
+ This controls whether a quote mark can be represented by
+ <literal>\'</> in a string literal. The preferred, SQL-standard way
+ to represent a quote mark is by doubling it (<literal>''</>) but
+ <productname>PostgreSQL</> has historically also accepted
+ <literal>\'</>. However, use of <literal>\'</> creates security risks
+ because in some client character set encodings, there are multibyte
+ characters in which the last byte is numerically equivalent to ASCII
+ <literal>\</>. If client-side code does escaping incorrectly then a
+ SQL-injection attack is possible. This risk can be prevented by
+ making the server reject queries in which a quote mark appears to be
+ escaped by a backslash.
+ The allowed values of <varname>backslash_quote</> are
+ <literal>on</> (allow <literal>\'</> always),
+ <literal>off</> (reject always), and
+ <literal>safe_encoding</> (allow only if client encoding does not
+ allow ASCII <literal>\</> within a multibyte character).
+ <literal>safe_encoding</> is the default setting.
+ </para>
+ </listitem>
+ </varlistentry>
+
<varlistentry id="guc-default-with-oids" xreflabel="default_with_oids">
<term><varname>default_with_oids</varname> (<type>boolean</type>)</term>
<indexterm>
diff --git a/src/backend/parser/scan.l b/src/backend/parser/scan.l
index 2a56c44a56b..35f2bc4657e 100644
--- a/src/backend/parser/scan.l
+++ b/src/backend/parser/scan.l
@@ -24,7 +24,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/scan.l,v 1.128 2005/08/16 00:48:12 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/scan.l,v 1.128.2.1 2006/05/21 20:11:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -51,13 +51,14 @@ static int xcdepth = 0; /* depth of nesting in slash-star comments */
static char *dolqstart; /* current $foo$ quote start string */
/*
- * GUC variable. This is a DIRECT violation of the warning given at the
+ * GUC variables. This is a DIRECT violation of the warning given at the
* head of gram.y, ie flex/bison code must not depend on any GUC variables;
- * as such, changing its value can induce very unintuitive behavior.
+ * as such, changing their values can induce very unintuitive behavior.
* But we shall have to live with it as a short-term thing until the switch
* to SQL-standard string syntax is complete.
*/
-bool escape_string_warning;
+BackslashQuoteType backslash_quote = BACKSLASH_QUOTE_SAFE_ENCODING;
+bool escape_string_warning = true;
static bool warn_on_first_escape;
@@ -453,6 +454,14 @@ other .
<xq>{xqescape} {
if (yytext[1] == '\'')
{
+ if (backslash_quote == BACKSLASH_QUOTE_OFF ||
+ (backslash_quote == BACKSLASH_QUOTE_SAFE_ENCODING &&
+ PG_ENCODING_IS_CLIENT_ONLY(pg_get_client_encoding())))
+ ereport(ERROR,
+ (errcode(ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER),
+ errmsg("unsafe use of \\' in a string literal"),
+ errhint("Use '' to write quotes in strings. \\' is insecure in client-only encodings."),
+ errposition(pg_err_position())));
if (warn_on_first_escape && escape_string_warning)
ereport(WARNING,
(errcode(ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER),
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 6d711618f9a..aad13930f70 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -10,7 +10,7 @@
* Written by Peter Eisentraut <peter_e@gmx.net>.
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.299.2.2 2006/02/12 22:32:57 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.299.2.3 2006/05/21 20:11:02 tgl Exp $
*
*--------------------------------------------------------------------
*/
@@ -46,6 +46,7 @@
#include "optimizer/geqo.h"
#include "optimizer/paths.h"
#include "optimizer/prep.h"
+#include "parser/gramparse.h"
#include "parser/parse_expr.h"
#include "parser/parse_relation.h"
#include "parser/scansup.h"
@@ -135,6 +136,7 @@ static bool assign_stage_log_stats(bool newval, bool doit, GucSource source);
static bool assign_log_stats(bool newval, bool doit, GucSource source);
static bool assign_transaction_read_only(bool newval, bool doit, GucSource source);
static const char *assign_canonical_path(const char *newval, bool doit, GucSource source);
+static const char *assign_backslash_quote(const char *newval, bool doit, GucSource source);
static bool assign_tcp_keepalives_idle(int newval, bool doit, GucSource source);
static bool assign_tcp_keepalives_interval(int newval, bool doit, GucSource source);
@@ -203,6 +205,7 @@ static char *syslog_ident_str;
static bool phony_autocommit;
static bool session_auth_is_superuser;
static double phony_random_seed;
+static char *backslash_quote_string;
static char *client_encoding_string;
static char *datestyle_string;
static char *default_iso_level_string;
@@ -1660,6 +1663,15 @@ static struct config_string ConfigureNamesString[] =
},
{
+ {"backslash_quote", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
+ gettext_noop("Sets whether \"\\'\" is allowed in string literals."),
+ gettext_noop("Valid values are ON, OFF, and SAFE_ENCODING.")
+ },
+ &backslash_quote_string,
+ "safe_encoding", assign_backslash_quote, NULL
+ },
+
+ {
{"client_encoding", PGC_USERSET, CLIENT_CONN_LOCALE,
gettext_noop("Sets the client's character set encoding."),
NULL,
@@ -5930,6 +5942,32 @@ assign_canonical_path(const char *newval, bool doit, GucSource source)
return newval;
}
+static const char *
+assign_backslash_quote(const char *newval, bool doit, GucSource source)
+{
+ BackslashQuoteType bq;
+ bool bqbool;
+
+ /*
+ * Although only "on", "off", and "safe_encoding" are documented,
+ * we use parse_bool so we can accept all the likely variants of
+ * "on" and "off".
+ */
+ if (pg_strcasecmp(newval, "safe_encoding") == 0)
+ bq = BACKSLASH_QUOTE_SAFE_ENCODING;
+ else if (parse_bool(newval, &bqbool))
+ {
+ bq = bqbool ? BACKSLASH_QUOTE_ON : BACKSLASH_QUOTE_OFF;
+ }
+ else
+ return NULL; /* reject */
+
+ if (doit)
+ backslash_quote = bq;
+
+ return newval;
+}
+
static bool
assign_tcp_keepalives_idle(int newval, bool doit, GucSource source)
{
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 773899e8b77..b1bdd3b4be4 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -413,10 +413,11 @@
# - Previous Postgres Versions -
#add_missing_from = off
-#regex_flavor = advanced # advanced, extended, or basic
-#sql_inheritance = on
+#backslash_quote = safe_encoding # on, off, or safe_encoding
#default_with_oids = off
#escape_string_warning = off
+#regex_flavor = advanced # advanced, extended, or basic
+#sql_inheritance = on
# - Other Platforms & Clients -
diff --git a/src/include/parser/gramparse.h b/src/include/parser/gramparse.h
index 8095ef2300a..25935e69aa6 100644
--- a/src/include/parser/gramparse.h
+++ b/src/include/parser/gramparse.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/parser/gramparse.h,v 1.31 2004/12/31 22:03:38 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/parser/gramparse.h,v 1.31.6.1 2006/05/21 20:11:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -18,6 +18,18 @@
#include "nodes/parsenodes.h"
+typedef enum
+{
+ BACKSLASH_QUOTE_OFF,
+ BACKSLASH_QUOTE_ON,
+ BACKSLASH_QUOTE_SAFE_ENCODING
+} BackslashQuoteType;
+
+/* GUC variables in scan.l (every one of these is a bad idea :-() */
+extern BackslashQuoteType backslash_quote;
+extern bool escape_string_warning;
+
+
/* from parser.c */
extern int yylex(void);
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index fdfd5dbeb71..dfeb2bc2644 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -7,7 +7,7 @@
* Copyright (c) 2000-2005, PostgreSQL Global Development Group
* Written by Peter Eisentraut <peter_e@gmx.net>.
*
- * $PostgreSQL: pgsql/src/include/utils/guc.h,v 1.63 2005/10/15 02:49:46 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/utils/guc.h,v 1.63.2.1 2006/05/21 20:11:02 tgl Exp $
*--------------------------------------------------------------------
*/
#ifndef GUC_H
@@ -120,7 +120,6 @@ extern bool SQL_inheritance;
extern bool Australian_timezones;
extern bool default_with_oids;
-extern bool escape_string_warning;
extern int log_min_error_statement;
extern int log_min_messages;