v1-5-Error-when-receiving-plaintext-on-GSS-encrypted-conn.patch
text/x-diff
Filename: v1-5-Error-when-receiving-plaintext-on-GSS-encrypted-conn.patch
Type: text/x-diff
Part: 4
Message:
[PATCH v1] GSSAPI encryption support
Patch
Format: format-patch
Series: patch v1
Subject: Error when receiving plaintext on GSS-encrypted connections
| File | + | − |
|---|---|---|
| src/backend/tcop/postgres.c | 12 | 0 |
| src/interfaces/libpq/fe-protocol3.c | 30 | 2 |
| src/interfaces/libpq/libpq-int.h | 1 | 0 |
From e55795e0638ca37447ef200f21f74db80b07ebf4 Mon Sep 17 00:00:00 2001
From: "Robbie Harwood (frozencemetery)" <rharwood@redhat.com>
Date: Fri, 12 Jun 2015 13:27:50 -0400
Subject: Error when receiving plaintext on GSS-encrypted connections
---
src/backend/tcop/postgres.c | 12 ++++++++++++
src/interfaces/libpq/fe-protocol3.c | 32 ++++++++++++++++++++++++++++++--
src/interfaces/libpq/libpq-int.h | 1 +
3 files changed, 43 insertions(+), 2 deletions(-)
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 8510908..ba8ed4e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -379,6 +379,18 @@ SocketBackend(StringInfo inBuf)
if (qtype < 0)
return EOF;
}
+ else if (gss_encrypt && MyProcPort->hba->auth_method == uaGSS &&
+ qtype != 'g' && qtype != 'R' )
+ {
+ /*
+ * Either something malicious is occuring, or we have lost
+ * synchronization.
+ */
+ ereport(FATAL,
+ (errcode(ERRCODE_PROTOCOL_VIOLATION),
+ errmsg("invalid frontend message type %d", qtype)));
+ return EOF;
+ }
#endif
/*
diff --git a/src/interfaces/libpq/fe-protocol3.c b/src/interfaces/libpq/fe-protocol3.c
index 65acfd1..d5fb461 100644
--- a/src/interfaces/libpq/fe-protocol3.c
+++ b/src/interfaces/libpq/fe-protocol3.c
@@ -131,7 +131,7 @@ pqParseInput3(PGconn *conn)
#ifdef ENABLE_GSS
/* We want to be ready in both IDLE and BUSY states for encryption */
- if (id == 'g')
+ if (id == 'g' && !conn->gss_disable_enc && conn->gctx)
{
ssize_t encEnd, next;
@@ -152,8 +152,33 @@ pqParseInput3(PGconn *conn)
memmove(conn->inBuffer + encEnd, conn->inBuffer + next,
conn->inEnd - next);
conn->inEnd = (conn->inEnd - next) + encEnd;
- continue;
+
+ conn->inCursor = conn->inStart;
+ (void) pqGetc(&id, conn);
+ (void) pqGetInt(&msgLength, 4, conn);
+ msgLength -= 4;
+ if (msgLength != encEnd - conn->inCursor)
+ {
+ /* This isn't a sync error because decrypt was successful */
+ printfPQExpBuffer(&conn->errorMessage,
+ libpq_gettext(
+ "server lied about message length: got message length %ld, but expected legnth %d\n"),
+ encEnd - conn->inCursor, msgLength);
+ /* build an error result holding the error message */
+ pqSaveErrorResult(conn);
+ /* drop out of GetResult wait loop */
+ conn->asyncStatus = PGASYNC_READY;
+
+ pqDropConnection(conn);
+ /* No more connection to backend */
+ conn->status = CONNECTION_BAD;
+ }
+ conn->gss_decrypted_cur = true;
}
+ else if (!conn->gss_disable_enc && conn->gss_auth_done &&
+ !conn->gss_decrypted_cur && id != 'E')
+ /* This could be a sync error, so let's handle it as such. */
+ handleSyncLoss(conn, id, msgLength);
#endif
/*
@@ -425,6 +450,9 @@ pqParseInput3(PGconn *conn)
{
/* Normal case: parsing agrees with specified length */
conn->inStart = conn->inCursor;
+#ifdef ENABLE_GSS
+ conn->gss_decrypted_cur = false;
+#endif
}
else
{
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index ff2e39d..7a3ebcd 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -447,6 +447,7 @@ struct pg_conn
gss_buffer_desc goutbuf; /* GSS output token */
bool gss_disable_enc; /* Does server recognize gss_encrypt? */
bool gss_auth_done; /* Did we finish the AUTH step? */
+ bool gss_decrypted_cur; /* Is first message in buffer decrypted? */
#endif
#ifdef ENABLE_SSPI
--
2.1.4