MCPcopy
hub / github.com/jackc/pgx / scramAuth

Method scramAuth

pgconn/auth_scram.go:43–112  ·  view source on GitHub ↗

Perform SCRAM authentication.

(serverAuthMechanisms []string)

Source from the content-addressed store, hash-verified

41
42// Perform SCRAM authentication.
43func (c *PgConn) scramAuth(serverAuthMechanisms []string) error {
44 sc, err := newScramClient(serverAuthMechanisms, c.config.Password)
45 if err != nil {
46 return err
47 }
48
49 serverHasPlus := slices.Contains(sc.serverAuthMechanisms, scramSHA256PlusName)
50 if c.config.ChannelBinding == "require" && !serverHasPlus {
51 return errors.New("channel binding required but server does not support SCRAM-SHA-256-PLUS")
52 }
53
54 // If we have a TLS connection and channel binding is not disabled, attempt to
55 // extract the server certificate hash for tls-server-end-point channel binding.
56 if tlsConn, ok := c.conn.(*tls.Conn); ok && c.config.ChannelBinding != "disable" {
57 certHash, err := getTLSCertificateHash(tlsConn)
58 if err != nil && c.config.ChannelBinding == "require" {
59 return fmt.Errorf("channel binding required but failed to get server certificate hash: %w", err)
60 }
61
62 // Upgrade to SCRAM-SHA-256-PLUS if we have binding data and the server supports it.
63 if certHash != nil && serverHasPlus {
64 sc.authMechanism = scramSHA256PlusName
65 }
66
67 sc.channelBindingData = certHash
68 sc.hasTLS = true
69 }
70
71 if c.config.ChannelBinding == "require" && sc.channelBindingData == nil {
72 return errors.New("channel binding required but channel binding data is not available")
73 }
74
75 // Send client-first-message in a SASLInitialResponse
76 saslInitialResponse := &pgproto3.SASLInitialResponse{
77 AuthMechanism: sc.authMechanism,
78 Data: sc.clientFirstMessage(),
79 }
80 c.frontend.Send(saslInitialResponse)
81 err = c.flushWithPotentialWriteReadDeadlock()
82 if err != nil {
83 return err
84 }
85
86 // Receive server-first-message payload in an AuthenticationSASLContinue.
87 saslContinue, err := c.rxSASLContinue()
88 if err != nil {
89 return err
90 }
91 err = sc.recvServerFirstMessage(saslContinue.Data)
92 if err != nil {
93 return err
94 }
95
96 // Send client-final-message in a SASLResponse
97 saslResponse := &pgproto3.SASLResponse{
98 Data: []byte(sc.clientFinalMessage()),
99 }
100 c.frontend.Send(saslResponse)

Callers 1

connectOneFunction · 0.80

Calls 10

rxSASLContinueMethod · 0.95
rxSASLFinalMethod · 0.95
newScramClientFunction · 0.85
getTLSCertificateHashFunction · 0.85
clientFirstMessageMethod · 0.80
clientFinalMessageMethod · 0.80
SendMethod · 0.45

Tested by

no test coverage detected