summaryrefslogtreecommitdiff
path: root/src/interfaces
diff options
context:
space:
mode:
authorHeikki Linnakangas2017-04-07 11:27:02 +0000
committerHeikki Linnakangas2017-04-07 11:27:02 +0000
commit5ba20866e593bb03c7915997188b0d12f4614873 (patch)
treefe3eaa86daee5df071c4dfbc1072d89fd86ff37d /src/interfaces
parent32e33a7979a10e9fcf2c9b32703838cec1daf674 (diff)
Use SASLprep to normalize passwords for SCRAM authentication.saslprep
SASLprep works on UTF-8, but we try to apply the SASLprep normalization even when the password is not in UTF-8 encoding. That may seem odd, but the encoding used during authentication isn't well-defined, so by always applying the normalization, we don't rely on client locale settings, which might well be wrong. If the input cannot be processed as UTF-8, we skip the normalization. (That is contrary to the spec, but we need to somehow deal with other encodings, while the spec just dictates UTF-8.) An important step of SASLprep normalization, is to convert the string to Unicode normalization form NFKC. The Unicode normalization requires a fairly large table of character decompositions, which is generated from data published by the Unicode consortium. The script to generate the table is put in src/common/unicode, as well test code for the normalization. A pre-generated version of the tables is included in src/include/common, so you don't need the code in src/common/unicode to build PostgreSQL, only if you wish to modify the normalization tables. The SASLprep implementation depends on the UTF-8 functions from src/backend/utils/mb/wchar.c. So to use it, you must also compile and link that. That doesn't change anything for the current users of these functions, the backend and libpq, as they both already link with wchar.o. It would be good to move those functions into a separate file in src/commmon, but I'll leave that for another day. Patch by Michael Paquier and me. Discussion: https://www.postgresql.org/message-id/CAB7nPqSByyEmAVLtEf1KxTRh=PWNKiWKEKQR=e1yGehz=wbymQ@mail.gmail.com
Diffstat (limited to 'src/interfaces')
-rw-r--r--src/interfaces/libpq/.gitignore2
-rw-r--r--src/interfaces/libpq/Makefile4
-rw-r--r--src/interfaces/libpq/fe-auth-scram.c27
3 files changed, 29 insertions, 4 deletions
diff --git a/src/interfaces/libpq/.gitignore b/src/interfaces/libpq/.gitignore
index 2224ada731..3829a4b008 100644
--- a/src/interfaces/libpq/.gitignore
+++ b/src/interfaces/libpq/.gitignore
@@ -11,6 +11,7 @@
/pg_strong_random.c
/pgstrcasecmp.c
/pqsignal.c
+/saslprep.c
/scram-common.c
/sha2.c
/sha2_openssl.c
@@ -19,6 +20,7 @@
/strlcpy.c
/system.c
/thread.c
+/unicode_norm.c
/win32error.c
/win32setlocale.c
/pgsleep.c
diff --git a/src/interfaces/libpq/Makefile b/src/interfaces/libpq/Makefile
index 36b57268a7..6ffb90ff39 100644
--- a/src/interfaces/libpq/Makefile
+++ b/src/interfaces/libpq/Makefile
@@ -49,7 +49,7 @@ endif
# src/backend/utils/mb
OBJS += encnames.o wchar.o
# src/common
-OBJS += base64.o ip.o md5.o scram-common.o
+OBJS += base64.o ip.o md5.o scram-common.o saslprep.o unicode_norm.o
ifeq ($(with_openssl),yes)
OBJS += fe-secure-openssl.o sha2_openssl.o
@@ -106,7 +106,7 @@ backend_src = $(top_srcdir)/src/backend
chklocale.c crypt.c erand48.c getaddrinfo.c getpeereid.c inet_aton.c inet_net_ntop.c noblock.c open.c system.c pgsleep.c pg_strong_random.c pgstrcasecmp.c pqsignal.c snprintf.c strerror.c strlcpy.c thread.c win32error.c win32setlocale.c: % : $(top_srcdir)/src/port/%
rm -f $@ && $(LN_S) $< .
-ip.c md5.c base64.c scram-common.c sha2.c sha2_openssl.c: % : $(top_srcdir)/src/common/%
+ip.c md5.c base64.c scram-common.c sha2.c sha2_openssl.c saslprep.c unicode_norm.c: % : $(top_srcdir)/src/common/%
rm -f $@ && $(LN_S) $< .
encnames.c wchar.c: % : $(backend_src)/utils/mb/%
diff --git a/src/interfaces/libpq/fe-auth-scram.c b/src/interfaces/libpq/fe-auth-scram.c
index 818ade4993..c56e91e0e0 100644
--- a/src/interfaces/libpq/fe-auth-scram.c
+++ b/src/interfaces/libpq/fe-auth-scram.c
@@ -15,6 +15,7 @@
#include "postgres_fe.h"
#include "common/base64.h"
+#include "common/saslprep.h"
#include "common/scram-common.h"
#include "fe-auth.h"
@@ -42,7 +43,7 @@ typedef struct
/* These are supplied by the user */
const char *username;
- const char *password;
+ char *password;
/* We construct these */
char *client_nonce;
@@ -82,6 +83,8 @@ void *
pg_fe_scram_init(const char *username, const char *password)
{
fe_scram_state *state;
+ char *prep_password;
+ pg_saslprep_rc rc;
state = (fe_scram_state *) malloc(sizeof(fe_scram_state));
if (!state)
@@ -89,7 +92,24 @@ pg_fe_scram_init(const char *username, const char *password)
memset(state, 0, sizeof(fe_scram_state));
state->state = FE_SCRAM_INIT;
state->username = username;
- state->password = password;
+
+ /* Normalize the password with SASLprep, if possible */
+ rc = pg_saslprep(password, &prep_password);
+ if (rc == SASLPREP_OOM)
+ {
+ free(state);
+ return NULL;
+ }
+ if (rc != SASLPREP_SUCCESS)
+ {
+ prep_password = strdup(password);
+ if (!prep_password)
+ {
+ free(state);
+ return NULL;
+ }
+ }
+ state->password = prep_password;
return state;
}
@@ -102,6 +122,9 @@ pg_fe_scram_free(void *opaq)
{
fe_scram_state *state = (fe_scram_state *) opaq;
+ if (state->password)
+ free(state->password);
+
/* client messages */
if (state->client_nonce)
free(state->client_nonce);