~ttt/minifluxlite

ec8fa56c95c90fb90925c723d7afd0d5fd642a76 — Frédéric Guillot 2 years ago 91508c5
Update vendor folder
M vendor/github.com/lib/pq/.travis.sh => vendor/github.com/lib/pq/.travis.sh +1 -1
@@ 80,7 80,7 @@ megacheck_install() {
}

golint_install() {
	go get github.com/golang/lint/golint
	go get golang.org/x/lint/golint
}

$1

M vendor/github.com/lib/pq/.travis.yml => vendor/github.com/lib/pq/.travis.yml +2 -2
@@ 1,9 1,9 @@
language: go

go:
  - 1.8.x
  - 1.9.x
  - 1.10.x
  - 1.11.x
  - master

sudo: true


@@ 44,7 44,7 @@ script:
  - >
    goimports -d -e $(find -name '*.go') | awk '{ print } END { exit NR == 0 ? 0 : 1 }'
  - go vet ./...
  - megacheck -go 1.8 ./...
  - megacheck -go 1.9 ./...
  - golint ./...
  - PQTEST_BINARY_PARAMETERS=no  go test -race -v ./...
  - PQTEST_BINARY_PARAMETERS=yes go test -race -v ./...

M vendor/github.com/lib/pq/README.md => vendor/github.com/lib/pq/README.md +1 -1
@@ 10,7 10,7 @@
## Docs

For detailed documentation and basic usage examples, please see the package
documentation at <http://godoc.org/github.com/lib/pq>.
documentation at <https://godoc.org/github.com/lib/pq>.

## Tests


M vendor/github.com/lib/pq/conn.go => vendor/github.com/lib/pq/conn.go +143 -114
@@ 2,7 2,9 @@ package pq

import (
	"bufio"
	"context"
	"crypto/md5"
	"crypto/sha256"
	"database/sql"
	"database/sql/driver"
	"encoding/binary"


@@ 20,6 22,7 @@ import (
	"unicode"

	"github.com/lib/pq/oid"
	"github.com/lib/pq/scram"
)

// Common error types


@@ 89,13 92,24 @@ type Dialer interface {
	DialTimeout(network, address string, timeout time.Duration) (net.Conn, error)
}

type defaultDialer struct{}
type DialerContext interface {
	DialContext(ctx context.Context, network, address string) (net.Conn, error)
}

type defaultDialer struct {
	d net.Dialer
}

func (d defaultDialer) Dial(ntw, addr string) (net.Conn, error) {
	return net.Dial(ntw, addr)
func (d defaultDialer) Dial(network, address string) (net.Conn, error) {
	return d.d.Dial(network, address)
}
func (d defaultDialer) DialTimeout(ntw, addr string, timeout time.Duration) (net.Conn, error) {
	return net.DialTimeout(ntw, addr, timeout)
func (d defaultDialer) DialTimeout(network, address string, timeout time.Duration) (net.Conn, error) {
	ctx, cancel := context.WithTimeout(context.Background(), timeout)
	defer cancel()
	return d.DialContext(ctx, network, address)
}
func (d defaultDialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
	return d.d.DialContext(ctx, network, address)
}

type conn struct {


@@ 244,90 258,35 @@ func (cn *conn) writeBuf(b byte) *writeBuf {
	}
}

// Open opens a new connection to the database. name is a connection string.
// Open opens a new connection to the database. dsn is a connection string.
// Most users should only use it through database/sql package from the standard
// library.
func Open(name string) (_ driver.Conn, err error) {
	return DialOpen(defaultDialer{}, name)
func Open(dsn string) (_ driver.Conn, err error) {
	return DialOpen(defaultDialer{}, dsn)
}

// DialOpen opens a new connection to the database using a dialer.
func DialOpen(d Dialer, name string) (_ driver.Conn, err error) {
func DialOpen(d Dialer, dsn string) (_ driver.Conn, err error) {
	c, err := NewConnector(dsn)
	if err != nil {
		return nil, err
	}
	c.dialer = d
	return c.open(context.Background())
}

func (c *Connector) open(ctx context.Context) (cn *conn, err error) {
	// Handle any panics during connection initialization.  Note that we
	// specifically do *not* want to use errRecover(), as that would turn any
	// connection errors into ErrBadConns, hiding the real error message from
	// the user.
	defer errRecoverNoErrBadConn(&err)

	o := make(values)
	o := c.opts

	// A number of defaults are applied here, in this order:
	//
	// * Very low precedence defaults applied in every situation
	// * Environment variables
	// * Explicitly passed connection information
	o["host"] = "localhost"
	o["port"] = "5432"
	// N.B.: Extra float digits should be set to 3, but that breaks
	// Postgres 8.4 and older, where the max is 2.
	o["extra_float_digits"] = "2"
	for k, v := range parseEnviron(os.Environ()) {
		o[k] = v
	}

	if strings.HasPrefix(name, "postgres://") || strings.HasPrefix(name, "postgresql://") {
		name, err = ParseURL(name)
		if err != nil {
			return nil, err
		}
	}

	if err := parseOpts(name, o); err != nil {
		return nil, err
	}

	// Use the "fallback" application name if necessary
	if fallback, ok := o["fallback_application_name"]; ok {
		if _, ok := o["application_name"]; !ok {
			o["application_name"] = fallback
		}
	}

	// We can't work with any client_encoding other than UTF-8 currently.
	// However, we have historically allowed the user to set it to UTF-8
	// explicitly, and there's no reason to break such programs, so allow that.
	// Note that the "options" setting could also set client_encoding, but
	// parsing its value is not worth it.  Instead, we always explicitly send
	// client_encoding as a separate run-time parameter, which should override
	// anything set in options.
	if enc, ok := o["client_encoding"]; ok && !isUTF8(enc) {
		return nil, errors.New("client_encoding must be absent or 'UTF8'")
	}
	o["client_encoding"] = "UTF8"
	// DateStyle needs a similar treatment.
	if datestyle, ok := o["datestyle"]; ok {
		if datestyle != "ISO, MDY" {
			panic(fmt.Sprintf("setting datestyle must be absent or %v; got %v",
				"ISO, MDY", datestyle))
		}
	} else {
		o["datestyle"] = "ISO, MDY"
	}

	// If a user is not provided by any other means, the last
	// resort is to use the current operating system provided user
	// name.
	if _, ok := o["user"]; !ok {
		u, err := userCurrent()
		if err != nil {
			return nil, err
		}
		o["user"] = u
	}

	cn := &conn{
	cn = &conn{
		opts:   o,
		dialer: d,
		dialer: c.dialer,
	}
	err = cn.handleDriverSettings(o)
	if err != nil {


@@ 335,7 294,7 @@ func DialOpen(d Dialer, name string) (_ driver.Conn, err error) {
	}
	cn.handlePgpass(o)

	cn.c, err = dial(d, o)
	cn.c, err = dial(ctx, c.dialer, o)
	if err != nil {
		return nil, err
	}


@@ 364,10 323,10 @@ func DialOpen(d Dialer, name string) (_ driver.Conn, err error) {
	return cn, err
}

func dial(d Dialer, o values) (net.Conn, error) {
	ntw, addr := network(o)
func dial(ctx context.Context, d Dialer, o values) (net.Conn, error) {
	network, address := network(o)
	// SSL is not necessary or supported over UNIX domain sockets
	if ntw == "unix" {
	if network == "unix" {
		o["sslmode"] = "disable"
	}



@@ 378,19 337,30 @@ func dial(d Dialer, o values) (net.Conn, error) {
			return nil, fmt.Errorf("invalid value for parameter connect_timeout: %s", err)
		}
		duration := time.Duration(seconds) * time.Second

		// connect_timeout should apply to the entire connection establishment
		// procedure, so we both use a timeout for the TCP connection
		// establishment and set a deadline for doing the initial handshake.
		// The deadline is then reset after startup() is done.
		deadline := time.Now().Add(duration)
		conn, err := d.DialTimeout(ntw, addr, duration)
		var conn net.Conn
		if dctx, ok := d.(DialerContext); ok {
			ctx, cancel := context.WithTimeout(ctx, duration)
			defer cancel()
			conn, err = dctx.DialContext(ctx, network, address)
		} else {
			conn, err = d.DialTimeout(network, address, duration)
		}
		if err != nil {
			return nil, err
		}
		err = conn.SetDeadline(deadline)
		return conn, err
	}
	return d.Dial(ntw, addr)
	if dctx, ok := d.(DialerContext); ok {
		return dctx.DialContext(ctx, network, address)
	}
	return d.Dial(network, address)
}

func network(o values) (string, string) {


@@ 704,7 674,7 @@ func (cn *conn) simpleQuery(q string) (res *rows, err error) {
			// res might be non-nil here if we received a previous
			// CommandComplete, but that's fine; just overwrite it
			res = &rows{cn: cn}
			res.colNames, res.colFmts, res.colTyps = parsePortalRowDescribe(r)
			res.rowsHeader = parsePortalRowDescribe(r)

			// To work around a bug in QueryRow in Go 1.2 and earlier, wait
			// until the first DataRow has been received.


@@ 861,17 831,15 @@ func (cn *conn) query(query string, args []driver.Value) (_ *rows, err error) {
		cn.readParseResponse()
		cn.readBindResponse()
		rows := &rows{cn: cn}
		rows.colNames, rows.colFmts, rows.colTyps = cn.readPortalDescribeResponse()
		rows.rowsHeader = cn.readPortalDescribeResponse()
		cn.postExecuteWorkaround()
		return rows, nil
	}
	st := cn.prepareTo(query, "")
	st.exec(args)
	return &rows{
		cn:       cn,
		colNames: st.colNames,
		colTyps:  st.colTyps,
		colFmts:  st.colFmts,
		cn:         cn,
		rowsHeader: st.rowsHeader,
	}, nil
}



@@ 992,7 960,6 @@ func (cn *conn) recv() (t byte, r *readBuf) {
		if err != nil {
			panic(err)
		}

		switch t {
		case 'E':
			panic(parseError(r))


@@ 1163,6 1130,55 @@ func (cn *conn) auth(r *readBuf, o values) {
		if r.int32() != 0 {
			errorf("unexpected authentication response: %q", t)
		}
	case 10:
		sc := scram.NewClient(sha256.New, o["user"], o["password"])
		sc.Step(nil)
		if sc.Err() != nil {
			errorf("SCRAM-SHA-256 error: %s", sc.Err().Error())
		}
		scOut := sc.Out()

		w := cn.writeBuf('p')
		w.string("SCRAM-SHA-256")
		w.int32(len(scOut))
		w.bytes(scOut)
		cn.send(w)

		t, r := cn.recv()
		if t != 'R' {
			errorf("unexpected password response: %q", t)
		}

		if r.int32() != 11 {
			errorf("unexpected authentication response: %q", t)
		}

		nextStep := r.next(len(*r))
		sc.Step(nextStep)
		if sc.Err() != nil {
			errorf("SCRAM-SHA-256 error: %s", sc.Err().Error())
		}

		scOut = sc.Out()
		w = cn.writeBuf('p')
		w.bytes(scOut)
		cn.send(w)

		t, r = cn.recv()
		if t != 'R' {
			errorf("unexpected password response: %q", t)
		}

		if r.int32() != 12 {
			errorf("unexpected authentication response: %q", t)
		}

		nextStep = r.next(len(*r))
		sc.Step(nextStep)
		if sc.Err() != nil {
			errorf("SCRAM-SHA-256 error: %s", sc.Err().Error())
		}

	default:
		errorf("unknown authentication response: %d", code)
	}


@@ 1180,12 1196,10 @@ var colFmtDataAllBinary = []byte{0, 1, 0, 1}
var colFmtDataAllText = []byte{0, 0}

type stmt struct {
	cn         *conn
	name       string
	colNames   []string
	colFmts    []format
	cn   *conn
	name string
	rowsHeader
	colFmtData []byte
	colTyps    []fieldDesc
	paramTyps  []oid.Oid
	closed     bool
}


@@ 1231,10 1245,8 @@ func (st *stmt) Query(v []driver.Value) (r driver.Rows, err error) {

	st.exec(v)
	return &rows{
		cn:       st.cn,
		colNames: st.colNames,
		colTyps:  st.colTyps,
		colFmts:  st.colFmts,
		cn:         st.cn,
		rowsHeader: st.rowsHeader,
	}, nil
}



@@ 1344,16 1356,22 @@ func (cn *conn) parseComplete(commandTag string) (driver.Result, string) {
	return driver.RowsAffected(n), commandTag
}

type rows struct {
	cn       *conn
	finish   func()
type rowsHeader struct {
	colNames []string
	colTyps  []fieldDesc
	colFmts  []format
	done     bool
	rb       readBuf
	result   driver.Result
	tag      string
}

type rows struct {
	cn     *conn
	finish func()
	rowsHeader
	done   bool
	rb     readBuf
	result driver.Result
	tag    string

	next *rowsHeader
}

func (rs *rows) Close() error {


@@ 1440,7 1458,8 @@ func (rs *rows) Next(dest []driver.Value) (err error) {
			}
			return
		case 'T':
			rs.colNames, rs.colFmts, rs.colTyps = parsePortalRowDescribe(&rs.rb)
			next := parsePortalRowDescribe(&rs.rb)
			rs.next = &next
			return io.EOF
		default:
			errorf("unexpected message after execute: %q", t)


@@ 1449,10 1468,16 @@ func (rs *rows) Next(dest []driver.Value) (err error) {
}

func (rs *rows) HasNextResultSet() bool {
	return !rs.done
	hasNext := rs.next != nil && !rs.done
	return hasNext
}

func (rs *rows) NextResultSet() error {
	if rs.next == nil {
		return io.EOF
	}
	rs.rowsHeader = *rs.next
	rs.next = nil
	return nil
}



@@ 1630,13 1655,13 @@ func (cn *conn) readStatementDescribeResponse() (paramTyps []oid.Oid, colNames [
	}
}

func (cn *conn) readPortalDescribeResponse() (colNames []string, colFmts []format, colTyps []fieldDesc) {
func (cn *conn) readPortalDescribeResponse() rowsHeader {
	t, r := cn.recv1()
	switch t {
	case 'T':
		return parsePortalRowDescribe(r)
	case 'n':
		return nil, nil, nil
		return rowsHeader{}
	case 'E':
		err := parseError(r)
		cn.readReadyForQuery()


@@ 1742,11 1767,11 @@ func parseStatementRowDescribe(r *readBuf) (colNames []string, colTyps []fieldDe
	return
}

func parsePortalRowDescribe(r *readBuf) (colNames []string, colFmts []format, colTyps []fieldDesc) {
func parsePortalRowDescribe(r *readBuf) rowsHeader {
	n := r.int16()
	colNames = make([]string, n)
	colFmts = make([]format, n)
	colTyps = make([]fieldDesc, n)
	colNames := make([]string, n)
	colFmts := make([]format, n)
	colTyps := make([]fieldDesc, n)
	for i := range colNames {
		colNames[i] = r.string()
		r.next(6)


@@ 1755,7 1780,11 @@ func parsePortalRowDescribe(r *readBuf) (colNames []string, colFmts []format, co
		colTyps[i].Mod = r.int32()
		colFmts[i] = format(r.int16())
	}
	return
	return rowsHeader{
		colNames: colNames,
		colFmts:  colFmts,
		colTyps:  colTyps,
	}
}

// parseEnviron tries to mimic some of libpq's environment handling

M vendor/github.com/lib/pq/conn_go18.go => vendor/github.com/lib/pq/conn_go18.go +23 -5
@@ 1,5 1,3 @@
// +build go1.8

package pq

import (


@@ 9,6 7,7 @@ import (
	"fmt"
	"io"
	"io/ioutil"
	"time"
)

// Implement the "QueryerContext" interface


@@ 76,13 75,32 @@ func (cn *conn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, 
	return tx, nil
}

func (cn *conn) Ping(ctx context.Context) error {
	if finish := cn.watchCancel(ctx); finish != nil {
		defer finish()
	}
	rows, err := cn.simpleQuery("SELECT 'lib/pq ping test';")
	if err != nil {
		return driver.ErrBadConn // https://golang.org/pkg/database/sql/driver/#Pinger
	}
	rows.Close()
	return nil
}

func (cn *conn) watchCancel(ctx context.Context) func() {
	if done := ctx.Done(); done != nil {
		finished := make(chan struct{})
		go func() {
			select {
			case <-done:
				_ = cn.cancel()
				// At this point the function level context is canceled,
				// so it must not be used for the additional network
				// request to cancel the query.
				// Create a new context to pass into the dial.
				ctxCancel, cancel := context.WithTimeout(context.Background(), time.Second*10)
				defer cancel()

				_ = cn.cancel(ctxCancel)
				finished <- struct{}{}
			case <-finished:
			}


@@ 97,8 115,8 @@ func (cn *conn) watchCancel(ctx context.Context) func() {
	return nil
}

func (cn *conn) cancel() error {
	c, err := dial(cn.dialer, cn.opts)
func (cn *conn) cancel(ctx context.Context) error {
	c, err := dial(ctx, cn.dialer, cn.opts)
	if err != nil {
		return err
	}

M vendor/github.com/lib/pq/connector.go => vendor/github.com/lib/pq/connector.go +79 -12
@@ 1,10 1,12 @@
// +build go1.10

package pq

import (
	"context"
	"database/sql/driver"
	"errors"
	"fmt"
	"os"
	"strings"
)

// Connector represents a fixed configuration for the pq driver with a given


@@ 14,30 16,95 @@ import (
//
// See https://golang.org/pkg/database/sql/driver/#Connector.
// See https://golang.org/pkg/database/sql/#OpenDB.
type connector struct {
	name string
type Connector struct {
	opts   values
	dialer Dialer
}

// Connect returns a connection to the database using the fixed configuration
// of this Connector. Context is not used.
func (c *connector) Connect(_ context.Context) (driver.Conn, error) {
	return (&Driver{}).Open(c.name)
func (c *Connector) Connect(ctx context.Context) (driver.Conn, error) {
	return c.open(ctx)
}

// Driver returnst the underlying driver of this Connector.
func (c *connector) Driver() driver.Driver {
func (c *Connector) Driver() driver.Driver {
	return &Driver{}
}

var _ driver.Connector = &connector{}

// NewConnector returns a connector for the pq driver in a fixed configuration
// with the given name. The returned connector can be used to create any number
// with the given dsn. The returned connector can be used to create any number
// of equivalent Conn's. The returned connector is intended to be used with
// database/sql.OpenDB.
//
// See https://golang.org/pkg/database/sql/driver/#Connector.
// See https://golang.org/pkg/database/sql/#OpenDB.
func NewConnector(name string) (driver.Connector, error) {
	return &connector{name: name}, nil
func NewConnector(dsn string) (*Connector, error) {
	var err error
	o := make(values)

	// A number of defaults are applied here, in this order:
	//
	// * Very low precedence defaults applied in every situation
	// * Environment variables
	// * Explicitly passed connection information
	o["host"] = "localhost"
	o["port"] = "5432"
	// N.B.: Extra float digits should be set to 3, but that breaks
	// Postgres 8.4 and older, where the max is 2.
	o["extra_float_digits"] = "2"
	for k, v := range parseEnviron(os.Environ()) {
		o[k] = v
	}

	if strings.HasPrefix(dsn, "postgres://") || strings.HasPrefix(dsn, "postgresql://") {
		dsn, err = ParseURL(dsn)
		if err != nil {
			return nil, err
		}
	}

	if err := parseOpts(dsn, o); err != nil {
		return nil, err
	}

	// Use the "fallback" application name if necessary
	if fallback, ok := o["fallback_application_name"]; ok {
		if _, ok := o["application_name"]; !ok {
			o["application_name"] = fallback
		}
	}

	// We can't work with any client_encoding other than UTF-8 currently.
	// However, we have historically allowed the user to set it to UTF-8
	// explicitly, and there's no reason to break such programs, so allow that.
	// Note that the "options" setting could also set client_encoding, but
	// parsing its value is not worth it.  Instead, we always explicitly send
	// client_encoding as a separate run-time parameter, which should override
	// anything set in options.
	if enc, ok := o["client_encoding"]; ok && !isUTF8(enc) {
		return nil, errors.New("client_encoding must be absent or 'UTF8'")
	}
	o["client_encoding"] = "UTF8"
	// DateStyle needs a similar treatment.
	if datestyle, ok := o["datestyle"]; ok {
		if datestyle != "ISO, MDY" {
			return nil, fmt.Errorf("setting datestyle must be absent or %v; got %v", "ISO, MDY", datestyle)
		}
	} else {
		o["datestyle"] = "ISO, MDY"
	}

	// If a user is not provided by any other means, the last
	// resort is to use the current operating system provided user
	// name.
	if _, ok := o["user"]; !ok {
		u, err := userCurrent()
		if err != nil {
			return nil, err
		}
		o["user"] = u
	}

	return &Connector{opts: o, dialer: defaultDialer{}}, nil
}

M vendor/github.com/lib/pq/doc.go => vendor/github.com/lib/pq/doc.go +1 -1
@@ 239,7 239,7 @@ for more information).  Note that the channel name will be truncated to 63
bytes by the PostgreSQL server.

You can find a complete, working example of Listener usage at
http://godoc.org/github.com/lib/pq/example/listen.
https://godoc.org/github.com/lib/pq/example/listen.

*/
package pq

M vendor/github.com/lib/pq/encode.go => vendor/github.com/lib/pq/encode.go +4 -5
@@ 117,11 117,10 @@ func textDecode(parameterStatus *parameterStatus, s []byte, typ oid.Oid) interfa
		}
		return i
	case oid.T_float4, oid.T_float8:
		bits := 64
		if typ == oid.T_float4 {
			bits = 32
		}
		f, err := strconv.ParseFloat(string(s), bits)
		// We always use 64 bit parsing, regardless of whether the input text is for
		// a float4 or float8, because clients expect float64s for all float datatypes
		// and returning a 32-bit parsed float64 produces lossy results.
		f, err := strconv.ParseFloat(string(s), 64)
		if err != nil {
			errorf("%s", err)
		}

A vendor/github.com/lib/pq/scram/scram.go => vendor/github.com/lib/pq/scram/scram.go +264 -0
@@ 0,0 1,264 @@
// Copyright (c) 2014 - Gustavo Niemeyer <gustavo@niemeyer.net>
//
// All rights reserved.
//
// 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.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.

// Pacakage scram implements a SCRAM-{SHA-1,etc} client per RFC5802.
//
// http://tools.ietf.org/html/rfc5802
//
package scram

import (
	"bytes"
	"crypto/hmac"
	"crypto/rand"
	"encoding/base64"
	"fmt"
	"hash"
	"strconv"
	"strings"
)

// Client implements a SCRAM-* client (SCRAM-SHA-1, SCRAM-SHA-256, etc).
//
// A Client may be used within a SASL conversation with logic resembling:
//
//    var in []byte
//    var client = scram.NewClient(sha1.New, user, pass)
//    for client.Step(in) {
//            out := client.Out()
//            // send out to server
//            in := serverOut
//    }
//    if client.Err() != nil {
//            // auth failed
//    }
//
type Client struct {
	newHash func() hash.Hash

	user string
	pass string
	step int
	out  bytes.Buffer
	err  error

	clientNonce []byte
	serverNonce []byte
	saltedPass  []byte
	authMsg     bytes.Buffer
}

// NewClient returns a new SCRAM-* client with the provided hash algorithm.
//
// For SCRAM-SHA-256, for example, use:
//
//    client := scram.NewClient(sha256.New, user, pass)
//
func NewClient(newHash func() hash.Hash, user, pass string) *Client {
	c := &Client{
		newHash: newHash,
		user:    user,
		pass:    pass,
	}
	c.out.Grow(256)
	c.authMsg.Grow(256)
	return c
}

// Out returns the data to be sent to the server in the current step.
func (c *Client) Out() []byte {
	if c.out.Len() == 0 {
		return nil
	}
	return c.out.Bytes()
}

// Err returns the error that ocurred, or nil if there were no errors.
func (c *Client) Err() error {
	return c.err
}

// SetNonce sets the client nonce to the provided value.
// If not set, the nonce is generated automatically out of crypto/rand on the first step.
func (c *Client) SetNonce(nonce []byte) {
	c.clientNonce = nonce
}

var escaper = strings.NewReplacer("=", "=3D", ",", "=2C")

// Step processes the incoming data from the server and makes the
// next round of data for the server available via Client.Out.
// Step returns false if there are no errors and more data is
// still expected.
func (c *Client) Step(in []byte) bool {
	c.out.Reset()
	if c.step > 2 || c.err != nil {
		return false
	}
	c.step++
	switch c.step {
	case 1:
		c.err = c.step1(in)
	case 2:
		c.err = c.step2(in)
	case 3:
		c.err = c.step3(in)
	}
	return c.step > 2 || c.err != nil
}

func (c *Client) step1(in []byte) error {
	if len(c.clientNonce) == 0 {
		const nonceLen = 16
		buf := make([]byte, nonceLen+b64.EncodedLen(nonceLen))
		if _, err := rand.Read(buf[:nonceLen]); err != nil {
			return fmt.Errorf("cannot read random SCRAM-SHA-256 nonce from operating system: %v", err)
		}
		c.clientNonce = buf[nonceLen:]
		b64.Encode(c.clientNonce, buf[:nonceLen])
	}
	c.authMsg.WriteString("n=")
	escaper.WriteString(&c.authMsg, c.user)
	c.authMsg.WriteString(",r=")
	c.authMsg.Write(c.clientNonce)

	c.out.WriteString("n,,")
	c.out.Write(c.authMsg.Bytes())
	return nil
}

var b64 = base64.StdEncoding

func (c *Client) step2(in []byte) error {
	c.authMsg.WriteByte(',')
	c.authMsg.Write(in)

	fields := bytes.Split(in, []byte(","))
	if len(fields) != 3 {
		return fmt.Errorf("expected 3 fields in first SCRAM-SHA-256 server message, got %d: %q", len(fields), in)
	}
	if !bytes.HasPrefix(fields[0], []byte("r=")) || len(fields[0]) < 2 {
		return fmt.Errorf("server sent an invalid SCRAM-SHA-256 nonce: %q", fields[0])
	}
	if !bytes.HasPrefix(fields[1], []byte("s=")) || len(fields[1]) < 6 {
		return fmt.Errorf("server sent an invalid SCRAM-SHA-256 salt: %q", fields[1])
	}
	if !bytes.HasPrefix(fields[2], []byte("i=")) || len(fields[2]) < 6 {
		return fmt.Errorf("server sent an invalid SCRAM-SHA-256 iteration count: %q", fields[2])
	}

	c.serverNonce = fields[0][2:]
	if !bytes.HasPrefix(c.serverNonce, c.clientNonce) {
		return fmt.Errorf("server SCRAM-SHA-256 nonce is not prefixed by client nonce: got %q, want %q+\"...\"", c.serverNonce, c.clientNonce)
	}

	salt := make([]byte, b64.DecodedLen(len(fields[1][2:])))
	n, err := b64.Decode(salt, fields[1][2:])
	if err != nil {
		return fmt.Errorf("cannot decode SCRAM-SHA-256 salt sent by server: %q", fields[1])
	}
	salt = salt[:n]
	iterCount, err := strconv.Atoi(string(fields[2][2:]))
	if err != nil {
		return fmt.Errorf("server sent an invalid SCRAM-SHA-256 iteration count: %q", fields[2])
	}
	c.saltPassword(salt, iterCount)

	c.authMsg.WriteString(",c=biws,r=")
	c.authMsg.Write(c.serverNonce)

	c.out.WriteString("c=biws,r=")
	c.out.Write(c.serverNonce)
	c.out.WriteString(",p=")
	c.out.Write(c.clientProof())
	return nil
}

func (c *Client) step3(in []byte) error {
	var isv, ise bool
	var fields = bytes.Split(in, []byte(","))
	if len(fields) == 1 {
		isv = bytes.HasPrefix(fields[0], []byte("v="))
		ise = bytes.HasPrefix(fields[0], []byte("e="))
	}
	if ise {
		return fmt.Errorf("SCRAM-SHA-256 authentication error: %s", fields[0][2:])
	} else if !isv {
		return fmt.Errorf("unsupported SCRAM-SHA-256 final message from server: %q", in)
	}
	if !bytes.Equal(c.serverSignature(), fields[0][2:]) {
		return fmt.Errorf("cannot authenticate SCRAM-SHA-256 server signature: %q", fields[0][2:])
	}
	return nil
}

func (c *Client) saltPassword(salt []byte, iterCount int) {
	mac := hmac.New(c.newHash, []byte(c.pass))
	mac.Write(salt)
	mac.Write([]byte{0, 0, 0, 1})
	ui := mac.Sum(nil)
	hi := make([]byte, len(ui))
	copy(hi, ui)
	for i := 1; i < iterCount; i++ {
		mac.Reset()
		mac.Write(ui)
		mac.Sum(ui[:0])
		for j, b := range ui {
			hi[j] ^= b
		}
	}
	c.saltedPass = hi
}

func (c *Client) clientProof() []byte {
	mac := hmac.New(c.newHash, c.saltedPass)
	mac.Write([]byte("Client Key"))
	clientKey := mac.Sum(nil)
	hash := c.newHash()
	hash.Write(clientKey)
	storedKey := hash.Sum(nil)
	mac = hmac.New(c.newHash, storedKey)
	mac.Write(c.authMsg.Bytes())
	clientProof := mac.Sum(nil)
	for i, b := range clientKey {
		clientProof[i] ^= b
	}
	clientProof64 := make([]byte, b64.EncodedLen(len(clientProof)))
	b64.Encode(clientProof64, clientProof)
	return clientProof64
}

func (c *Client) serverSignature() []byte {
	mac := hmac.New(c.newHash, c.saltedPass)
	mac.Write([]byte("Server Key"))
	serverKey := mac.Sum(nil)

	mac = hmac.New(c.newHash, serverKey)
	mac.Write(c.authMsg.Bytes())
	serverSignature := mac.Sum(nil)

	encoded := make([]byte, b64.EncodedLen(len(serverSignature)))
	b64.Encode(encoded, serverSignature)
	return encoded
}

M vendor/github.com/lib/pq/ssl.go => vendor/github.com/lib/pq/ssl.go +7 -1
@@ 58,7 58,13 @@ func ssl(o values) (func(net.Conn) (net.Conn, error), error) {
	if err != nil {
		return nil, err
	}
	sslRenegotiation(&tlsConf)

	// Accept renegotiation requests initiated by the backend.
	//
	// Renegotiation was deprecated then removed from PostgreSQL 9.5, but
	// the default configuration of older versions has it enabled. Redshift
	// also initiates renegotiations and cannot be reconfigured.
	tlsConf.Renegotiation = tls.RenegotiateFreelyAsClient

	return func(conn net.Conn) (net.Conn, error) {
		client := tls.Client(conn, &tlsConf)

D vendor/github.com/lib/pq/ssl_go1.7.go => vendor/github.com/lib/pq/ssl_go1.7.go +0 -14
@@ 1,14 0,0 @@
// +build go1.7

package pq

import "crypto/tls"

// Accept renegotiation requests initiated by the backend.
//
// Renegotiation was deprecated then removed from PostgreSQL 9.5, but
// the default configuration of older versions has it enabled. Redshift
// also initiates renegotiations and cannot be reconfigured.
func sslRenegotiation(conf *tls.Config) {
	conf.Renegotiation = tls.RenegotiateFreelyAsClient
}

D vendor/github.com/lib/pq/ssl_renegotiation.go => vendor/github.com/lib/pq/ssl_renegotiation.go +0 -8
@@ 1,8 0,0 @@
// +build !go1.7

package pq

import "crypto/tls"

// Renegotiation is not supported by crypto/tls until Go 1.7.
func sslRenegotiation(*tls.Config) {}

M vendor/modules.txt => vendor/modules.txt +2 -1
@@ 8,10 8,11 @@ github.com/golang/protobuf/proto
github.com/gorilla/context
# github.com/gorilla/mux v1.6.2
github.com/gorilla/mux
# github.com/lib/pq v1.0.0
# github.com/lib/pq v1.1.1
github.com/lib/pq
github.com/lib/pq/hstore
github.com/lib/pq/oid
github.com/lib/pq/scram
# golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9
golang.org/x/crypto/ssh/terminal
golang.org/x/crypto/acme/autocert