From fa2b09640075ecdcb0b6b7ccef5ddcf26456b6b0 Mon Sep 17 00:00:00 2001
From: Mukundan Kavanur Kidambi <mukundan.kidambi@outreach.io>
Date: Tue, 29 Mar 2022 14:05:14 -0700
Subject: [PATCH 1/5] fix: Adding overall format before appending
 ColumnFormatCodes

---
 copy_both_response.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/copy_both_response.go b/copy_both_response.go
index fbd985d8..4a1c3a07 100644
--- a/copy_both_response.go
+++ b/copy_both_response.go
@@ -48,7 +48,7 @@ func (src *CopyBothResponse) Encode(dst []byte) []byte {
 	dst = append(dst, 'W')
 	sp := len(dst)
 	dst = pgio.AppendInt32(dst, -1)
-
+	dst = append(dst, src.OverallFormat)
 	dst = pgio.AppendUint16(dst, uint16(len(src.ColumnFormatCodes)))
 	for _, fc := range src.ColumnFormatCodes {
 		dst = pgio.AppendUint16(dst, fc)

From 1d7886b01260a464e06d756375aeb70603210e4e Mon Sep 17 00:00:00 2001
From: Mukundan Kavanur Kidambi <mukundan.kidambi@outreach.io>
Date: Wed, 30 Mar 2022 15:45:42 -0700
Subject: [PATCH 2/5] Adding UTs

---
 copy_both_response_test.go | 22 ++++++++++++++++++++++
 go.mod                     |  1 +
 go.sum                     | 32 ++++++++++++++++++++++++++++++++
 3 files changed, 55 insertions(+)
 create mode 100644 copy_both_response_test.go

diff --git a/copy_both_response_test.go b/copy_both_response_test.go
new file mode 100644
index 00000000..fb2c00d0
--- /dev/null
+++ b/copy_both_response_test.go
@@ -0,0 +1,22 @@
+package pgproto3_test
+
+import (
+	"testing"
+
+	"github.com/jackc/pgproto3/v2"
+	"gotest.tools/v3/assert"
+)
+
+func TestEncodeDecode(t *testing.T) {
+	src := pgproto3.CopyBothResponse{
+		OverallFormat:     byte(1), // Just to differ from defaults
+		ColumnFormatCodes: []uint16{0, 1},
+	}
+	dstBytes := []byte{}
+	dstBytes = src.Encode(dstBytes)
+	dst := pgproto3.CopyBothResponse{}
+	err := dst.Decode(dstBytes[5:])
+	assert.NilError(t, err, "No errors on decode")
+	assert.Equal(t, dst.OverallFormat, src.OverallFormat, "OverallFormat is decoded successfully")
+	assert.DeepEqual(t, dst.ColumnFormatCodes, src.ColumnFormatCodes)
+}
diff --git a/go.mod b/go.mod
index 36041a94..ed5b4d5d 100644
--- a/go.mod
+++ b/go.mod
@@ -6,4 +6,5 @@ require (
 	github.com/jackc/chunkreader/v2 v2.0.0
 	github.com/jackc/pgio v1.0.0
 	github.com/stretchr/testify v1.4.0
+	gotest.tools/v3 v3.1.0
 )
diff --git a/go.sum b/go.sum
index dd9cd044..faffff19 100644
--- a/go.sum
+++ b/go.sum
@@ -1,14 +1,46 @@
 github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/jackc/chunkreader/v2 v2.0.0 h1:DUwgMQuuPnS0rhMXenUtZpqZqrR/30NWY+qQvTpSvEs=
 github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
 github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE=
 github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gotest.tools/v3 v3.1.0 h1:rVV8Tcg/8jHUkPUorwjaMTtemIMVXfIPKiOqnhEhakk=
+gotest.tools/v3 v3.1.0/go.mod h1:fHy7eyTmJFO5bQbUsEGQ1v4m2J3Jz9eWL54TP2/ZuYQ=

From e145003288619f513827479651048c3ad408bf13 Mon Sep 17 00:00:00 2001
From: Mukundan Kavanur Kidambi <mukundan.kidambi@outreach.io>
Date: Wed, 30 Mar 2022 16:16:03 -0700
Subject: [PATCH 3/5] Addressing feedback

---
 copy_both_response_test.go |  6 +++---
 go.mod                     |  1 -
 go.sum                     | 31 -------------------------------
 3 files changed, 3 insertions(+), 35 deletions(-)

diff --git a/copy_both_response_test.go b/copy_both_response_test.go
index fb2c00d0..7aa7da22 100644
--- a/copy_both_response_test.go
+++ b/copy_both_response_test.go
@@ -4,7 +4,7 @@ import (
 	"testing"
 
 	"github.com/jackc/pgproto3/v2"
-	"gotest.tools/v3/assert"
+	"github.com/stretchr/testify/assert"
 )
 
 func TestEncodeDecode(t *testing.T) {
@@ -16,7 +16,7 @@ func TestEncodeDecode(t *testing.T) {
 	dstBytes = src.Encode(dstBytes)
 	dst := pgproto3.CopyBothResponse{}
 	err := dst.Decode(dstBytes[5:])
-	assert.NilError(t, err, "No errors on decode")
+	assert.NoError(t, err, "No errors on decode")
 	assert.Equal(t, dst.OverallFormat, src.OverallFormat, "OverallFormat is decoded successfully")
-	assert.DeepEqual(t, dst.ColumnFormatCodes, src.ColumnFormatCodes)
+	assert.EqualValues(t, dst.ColumnFormatCodes, src.ColumnFormatCodes)
 }
diff --git a/go.mod b/go.mod
index ed5b4d5d..36041a94 100644
--- a/go.mod
+++ b/go.mod
@@ -6,5 +6,4 @@ require (
 	github.com/jackc/chunkreader/v2 v2.0.0
 	github.com/jackc/pgio v1.0.0
 	github.com/stretchr/testify v1.4.0
-	gotest.tools/v3 v3.1.0
 )
diff --git a/go.sum b/go.sum
index faffff19..af835086 100644
--- a/go.sum
+++ b/go.sum
@@ -1,46 +1,15 @@
 github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
-github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/jackc/chunkreader/v2 v2.0.0 h1:DUwgMQuuPnS0rhMXenUtZpqZqrR/30NWY+qQvTpSvEs=
 github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
 github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE=
 github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8=
-github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
-github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
-github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
-golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
-golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
-golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gotest.tools/v3 v3.1.0 h1:rVV8Tcg/8jHUkPUorwjaMTtemIMVXfIPKiOqnhEhakk=
-gotest.tools/v3 v3.1.0/go.mod h1:fHy7eyTmJFO5bQbUsEGQ1v4m2J3Jz9eWL54TP2/ZuYQ=

From c6ccb4b9a3dd75e628009594cd6adf8b47172d1a Mon Sep 17 00:00:00 2001
From: Mukundan Kavanur Kidambi <mukundan.kidambi@outreach.io>
Date: Wed, 30 Mar 2022 16:22:28 -0700
Subject: [PATCH 4/5] Addressing feedback

---
 copy_both_response_test.go | 16 ++++++----------
 1 file changed, 6 insertions(+), 10 deletions(-)

diff --git a/copy_both_response_test.go b/copy_both_response_test.go
index 7aa7da22..d9816fc8 100644
--- a/copy_both_response_test.go
+++ b/copy_both_response_test.go
@@ -8,15 +8,11 @@ import (
 )
 
 func TestEncodeDecode(t *testing.T) {
-	src := pgproto3.CopyBothResponse{
-		OverallFormat:     byte(1), // Just to differ from defaults
-		ColumnFormatCodes: []uint16{0, 1},
-	}
-	dstBytes := []byte{}
-	dstBytes = src.Encode(dstBytes)
-	dst := pgproto3.CopyBothResponse{}
-	err := dst.Decode(dstBytes[5:])
+	srcBytes := []byte{'W', 0x00, 0x00, 0x00, 0x0b, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01}
+	dstResp := pgproto3.CopyBothResponse{}
+	err := dstResp.Decode(srcBytes[5:])
 	assert.NoError(t, err, "No errors on decode")
-	assert.Equal(t, dst.OverallFormat, src.OverallFormat, "OverallFormat is decoded successfully")
-	assert.EqualValues(t, dst.ColumnFormatCodes, src.ColumnFormatCodes)
+	dstBytes := []byte{}
+	dstBytes = dstResp.Encode(dstBytes)
+	assert.EqualValues(t, srcBytes, dstBytes, "Expecting src & dest bytes to match")
 }

From 175856ffd3c8377db2e631b99ef7a7c996fdae77 Mon Sep 17 00:00:00 2001
From: Oliver Tan <otan@cockroachlabs.com>
Date: Tue, 12 Apr 2022 14:26:13 +1000
Subject: [PATCH 5/5] add GSS authentication to pgproto3

---
 authentication_gss.go          | 58 +++++++++++++++++++++++++++++
 authentication_gss_continue.go | 67 ++++++++++++++++++++++++++++++++++
 backend.go                     | 11 +++---
 frontend.go                    |  6 ++-
 gss_response.go                | 48 ++++++++++++++++++++++++
 json_test.go                   | 39 ++++++++++++++++++++
 6 files changed, 222 insertions(+), 7 deletions(-)
 create mode 100644 authentication_gss.go
 create mode 100644 authentication_gss_continue.go
 create mode 100644 gss_response.go

diff --git a/authentication_gss.go b/authentication_gss.go
new file mode 100644
index 00000000..5a3f3b1d
--- /dev/null
+++ b/authentication_gss.go
@@ -0,0 +1,58 @@
+package pgproto3
+
+import (
+	"encoding/binary"
+	"encoding/json"
+	"errors"
+	"github.com/jackc/pgio"
+)
+
+type AuthenticationGSS struct{}
+
+func (a *AuthenticationGSS) Backend() {}
+
+func (a *AuthenticationGSS) AuthenticationResponse() {}
+
+func (a *AuthenticationGSS) Decode(src []byte) error {
+	if len(src) < 4 {
+		return errors.New("authentication message too short")
+	}
+
+	authType := binary.BigEndian.Uint32(src)
+
+	if authType != AuthTypeGSS {
+		return errors.New("bad auth type")
+	}
+	return nil
+}
+
+func (a *AuthenticationGSS) Encode(dst []byte) []byte {
+	dst = append(dst, 'R')
+	dst = pgio.AppendInt32(dst, 4)
+	dst = pgio.AppendUint32(dst, AuthTypeGSS)
+	return dst
+}
+
+func (a *AuthenticationGSS) MarshalJSON() ([]byte, error) {
+	return json.Marshal(struct {
+		Type string
+		Data []byte
+	}{
+		Type: "AuthenticationGSS",
+	})
+}
+
+func (a *AuthenticationGSS) UnmarshalJSON(data []byte) error {
+	// Ignore null, like in the main JSON package.
+	if string(data) == "null" {
+		return nil
+	}
+
+	var msg struct {
+		Type string
+	}
+	if err := json.Unmarshal(data, &msg); err != nil {
+		return err
+	}
+	return nil
+}
diff --git a/authentication_gss_continue.go b/authentication_gss_continue.go
new file mode 100644
index 00000000..cf8b1834
--- /dev/null
+++ b/authentication_gss_continue.go
@@ -0,0 +1,67 @@
+package pgproto3
+
+import (
+	"encoding/binary"
+	"encoding/json"
+	"errors"
+	"github.com/jackc/pgio"
+)
+
+type AuthenticationGSSContinue struct {
+	Data []byte
+}
+
+func (a *AuthenticationGSSContinue) Backend() {}
+
+func (a *AuthenticationGSSContinue) AuthenticationResponse() {}
+
+func (a *AuthenticationGSSContinue) Decode(src []byte) error {
+	if len(src) < 4 {
+		return errors.New("authentication message too short")
+	}
+
+	authType := binary.BigEndian.Uint32(src)
+
+	if authType != AuthTypeGSSCont {
+		return errors.New("bad auth type")
+	}
+
+	a.Data = src[4:]
+	return nil
+}
+
+func (a *AuthenticationGSSContinue) Encode(dst []byte) []byte {
+	dst = append(dst, 'R')
+	dst = pgio.AppendInt32(dst, int32(len(a.Data))+8)
+	dst = pgio.AppendUint32(dst, AuthTypeGSSCont)
+	dst = append(dst, a.Data...)
+	return dst
+}
+
+func (a *AuthenticationGSSContinue) MarshalJSON() ([]byte, error) {
+	return json.Marshal(struct {
+		Type string
+		Data []byte
+	}{
+		Type: "AuthenticationGSSContinue",
+		Data: a.Data,
+	})
+}
+
+func (a *AuthenticationGSSContinue) UnmarshalJSON(data []byte) error {
+	// Ignore null, like in the main JSON package.
+	if string(data) == "null" {
+		return nil
+	}
+
+	var msg struct {
+		Type string
+		Data []byte
+	}
+	if err := json.Unmarshal(data, &msg); err != nil {
+		return err
+	}
+
+	a.Data = msg.Data
+	return nil
+}
diff --git a/backend.go b/backend.go
index 9c42ad02..a48b66f1 100644
--- a/backend.go
+++ b/backend.go
@@ -30,11 +30,10 @@ type Backend struct {
 	sync           Sync
 	terminate      Terminate
 
-	bodyLen      int
-	msgType      byte
-	partialMsg   bool
-	authType     uint32
-	
+	bodyLen    int
+	msgType    byte
+	partialMsg bool
+	authType   uint32
 }
 
 const (
@@ -147,6 +146,8 @@ func (b *Backend) Receive() (FrontendMessage, error) {
 			msg = &SASLResponse{}
 		case AuthTypeSASLFinal:
 			msg = &SASLResponse{}
+		case AuthTypeGSS, AuthTypeGSSCont:
+			msg = &GSSResponse{}
 		case AuthTypeCleartextPassword, AuthTypeMD5Password:
 			fallthrough
 		default:
diff --git a/frontend.go b/frontend.go
index c33dfb08..f15a3e04 100644
--- a/frontend.go
+++ b/frontend.go
@@ -16,6 +16,8 @@ type Frontend struct {
 	authenticationOk                AuthenticationOk
 	authenticationCleartextPassword AuthenticationCleartextPassword
 	authenticationMD5Password       AuthenticationMD5Password
+	authenticationGSS               AuthenticationGSS
+	authenticationGSSContinue       AuthenticationGSSContinue
 	authenticationSASL              AuthenticationSASL
 	authenticationSASLContinue      AuthenticationSASLContinue
 	authenticationSASLFinal         AuthenticationSASLFinal
@@ -178,9 +180,9 @@ func (f *Frontend) findAuthenticationMessageType(src []byte) (BackendMessage, er
 	case AuthTypeSCMCreds:
 		return nil, errors.New("AuthTypeSCMCreds is unimplemented")
 	case AuthTypeGSS:
-		return nil, errors.New("AuthTypeGSS is unimplemented")
+		return &f.authenticationGSS, nil
 	case AuthTypeGSSCont:
-		return nil, errors.New("AuthTypeGSSCont is unimplemented")
+		return &f.authenticationGSSContinue, nil
 	case AuthTypeSSPI:
 		return nil, errors.New("AuthTypeSSPI is unimplemented")
 	case AuthTypeSASL:
diff --git a/gss_response.go b/gss_response.go
new file mode 100644
index 00000000..62da99c7
--- /dev/null
+++ b/gss_response.go
@@ -0,0 +1,48 @@
+package pgproto3
+
+import (
+	"encoding/json"
+	"github.com/jackc/pgio"
+)
+
+type GSSResponse struct {
+	Data []byte
+}
+
+// Frontend identifies this message as sendable by a PostgreSQL frontend.
+func (g *GSSResponse) Frontend() {}
+
+func (g *GSSResponse) Decode(data []byte) error {
+	g.Data = data
+	return nil
+}
+
+func (g *GSSResponse) Encode(dst []byte) []byte {
+	dst = append(dst, 'p')
+	dst = pgio.AppendInt32(dst, int32(4+len(g.Data)))
+	dst = append(dst, g.Data...)
+	return dst
+}
+
+// MarshalJSON implements encoding/json.Marshaler.
+func (g *GSSResponse) MarshalJSON() ([]byte, error) {
+	return json.Marshal(struct {
+		Type string
+		Data []byte
+	}{
+		Type: "GSSResponse",
+		Data: g.Data,
+	})
+}
+
+// UnmarshalJSON implements encoding/json.Unmarshaler.
+func (g *GSSResponse) UnmarshalJSON(data []byte) error {
+	var msg struct {
+		Data []byte
+	}
+	if err := json.Unmarshal(data, &msg); err != nil {
+		return err
+	}
+	g.Data = msg.Data
+	return nil
+}
diff --git a/json_test.go b/json_test.go
index eab26252..8fad4f88 100644
--- a/json_test.go
+++ b/json_test.go
@@ -37,6 +37,32 @@ func TestJSONUnmarshalAuthenticationSASL(t *testing.T) {
 	}
 }
 
+func TestJSONUnmarshalAuthenticationGSS(t *testing.T) {
+	data := []byte(`{"Type":"AuthenticationGSS"}`)
+	want := AuthenticationGSS{}
+
+	var got AuthenticationGSS
+	if err := json.Unmarshal(data, &got); err != nil {
+		t.Errorf("cannot JSON unmarshal %v", err)
+	}
+	if !reflect.DeepEqual(got, want) {
+		t.Error("unmarshaled AuthenticationGSS struct doesn't match expected value")
+	}
+}
+
+func TestJSONUnmarshalAuthenticationGSSContinue(t *testing.T) {
+	data := []byte(`{"Type":"AuthenticationGSSContinue","Data":[1,2,3,4]}`)
+	want := AuthenticationGSSContinue{Data: []byte{1, 2, 3, 4}}
+
+	var got AuthenticationGSSContinue
+	if err := json.Unmarshal(data, &got); err != nil {
+		t.Errorf("cannot JSON unmarshal %v", err)
+	}
+	if !reflect.DeepEqual(got, want) {
+		t.Error("unmarshaled AuthenticationGSSContinue struct doesn't match expected value")
+	}
+}
+
 func TestJSONUnmarshalAuthenticationSASLContinue(t *testing.T) {
 	data := []byte(`{"Type":"AuthenticationSASLContinue", "Data":"1"}`)
 	want := AuthenticationSASLContinue{
@@ -551,6 +577,19 @@ func TestAuthenticationMD5Password(t *testing.T) {
 	}
 }
 
+func TestJSONUnmarshalGSSResponse(t *testing.T) {
+	data := []byte(`{"Type":"GSSResponse","Data":[10,20,30,40]}`)
+	want := GSSResponse{Data: []byte{10, 20, 30, 40}}
+
+	var got GSSResponse
+	if err := json.Unmarshal(data, &got); err != nil {
+		t.Errorf("cannot JSON unmarshal %v", err)
+	}
+	if !reflect.DeepEqual(got, want) {
+		t.Error("unmarshaled GSSResponse struct doesn't match expected value")
+	}
+}
+
 func TestErrorResponse(t *testing.T) {
 	data := []byte(`{"Type":"ErrorResponse","UnknownFields":{"112":"foo"},"Code": "Fail","Position":1,"Message":"this is an error"}`)
 	want := ErrorResponse{