зеркало из https://github.com/github/vitess-gh.git
mysql: Pass mysql.Conn through {Hash,PlainText,Caching}Storage interfaces
The TLS client certificates can simply be derived based on the mysql.Conn passed through, but passing through the actual Conn, gives us access to Conn.ClientData or anything else an Auth{Method,Server} might need to implement. It's arguable that if we need access to the lower level Conn, we could simply implement the actual HandleAuthPluginData instead of these *Storage interfaces, and that's true. But not all AuthMethods can get away with this because they need to write to the Conn's connection using private functions. For example, the `mysqlCachingSha2AuthMethod` needs to write more data on the socket after calling `UserEntryWithCacheHash`, so to write a new `UserEntryWithCacheHash` that needs data from `mysql.Conn`, I'm left wtih no other options since I can't vendor or reimplement the rest of the logic without having access to the private functions/methods within the `mysql` package. Signed-off-by: Matt Robenolt <matt@ydekproductions.com>
This commit is contained in:
Родитель
8245b11cb5
Коммит
7c247f4b82
|
@ -22,7 +22,6 @@ import (
|
|||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
"crypto/subtle"
|
||||
"crypto/x509"
|
||||
"encoding/hex"
|
||||
"net"
|
||||
"sync"
|
||||
|
@ -132,7 +131,7 @@ const (
|
|||
// such a hash based on the salt and auth response provided here after retrieving
|
||||
// the hashed password from the storage.
|
||||
type HashStorage interface {
|
||||
UserEntryWithHash(userCerts []*x509.Certificate, salt []byte, user string, authResponse []byte, remoteAddr net.Addr) (Getter, error)
|
||||
UserEntryWithHash(conn *Conn, salt []byte, user string, authResponse []byte, remoteAddr net.Addr) (Getter, error)
|
||||
}
|
||||
|
||||
// PlainTextStorage describes an object that is suitable to retrieve user information
|
||||
|
@ -146,7 +145,7 @@ type HashStorage interface {
|
|||
// When comparing plain text passwords directly, please ensure to use `subtle.ConstantTimeCompare`
|
||||
// to prevent timing based attacks on the password.
|
||||
type PlainTextStorage interface {
|
||||
UserEntryWithPassword(userCerts []*x509.Certificate, user string, password string, remoteAddr net.Addr) (Getter, error)
|
||||
UserEntryWithPassword(conn *Conn, user string, password string, remoteAddr net.Addr) (Getter, error)
|
||||
}
|
||||
|
||||
// CachingStorage describes an object that is suitable to retrieve user information
|
||||
|
@ -159,7 +158,7 @@ type PlainTextStorage interface {
|
|||
// such a hash based on the salt and auth response provided here after retrieving
|
||||
// the hashed password from the cache.
|
||||
type CachingStorage interface {
|
||||
UserEntryWithCacheHash(userCerts []*x509.Certificate, salt []byte, user string, authResponse []byte, remoteAddr net.Addr) (Getter, CacheState, error)
|
||||
UserEntryWithCacheHash(conn *Conn, salt []byte, user string, authResponse []byte, remoteAddr net.Addr) (Getter, CacheState, error)
|
||||
}
|
||||
|
||||
// NewMysqlNativeAuthMethod will create a new AuthMethod that implements the
|
||||
|
@ -432,7 +431,7 @@ func (n *mysqlNativePasswordAuthMethod) HandleAuthPluginData(conn *Conn, user st
|
|||
}
|
||||
|
||||
salt := serverAuthPluginData[:len(serverAuthPluginData)-1]
|
||||
return n.storage.UserEntryWithHash(conn.GetTLSClientCerts(), salt, user, clientAuthPluginData, remoteAddr)
|
||||
return n.storage.UserEntryWithHash(conn, salt, user, clientAuthPluginData, remoteAddr)
|
||||
}
|
||||
|
||||
type mysqlClearAuthMethod struct {
|
||||
|
@ -457,7 +456,7 @@ func (n *mysqlClearAuthMethod) AllowClearTextWithoutTLS() bool {
|
|||
}
|
||||
|
||||
func (n *mysqlClearAuthMethod) HandleAuthPluginData(conn *Conn, user string, serverAuthPluginData []byte, clientAuthPluginData []byte, remoteAddr net.Addr) (Getter, error) {
|
||||
return n.storage.UserEntryWithPassword(conn.GetTLSClientCerts(), user, string(clientAuthPluginData[:len(clientAuthPluginData)-1]), remoteAddr)
|
||||
return n.storage.UserEntryWithPassword(conn, user, string(clientAuthPluginData[:len(clientAuthPluginData)-1]), remoteAddr)
|
||||
}
|
||||
|
||||
type mysqlDialogAuthMethod struct {
|
||||
|
@ -482,7 +481,7 @@ func (n *mysqlDialogAuthMethod) AuthPluginData() ([]byte, error) {
|
|||
}
|
||||
|
||||
func (n *mysqlDialogAuthMethod) HandleAuthPluginData(conn *Conn, user string, serverAuthPluginData []byte, clientAuthPluginData []byte, remoteAddr net.Addr) (Getter, error) {
|
||||
return n.storage.UserEntryWithPassword(conn.GetTLSClientCerts(), user, string(clientAuthPluginData[:len(clientAuthPluginData)-1]), remoteAddr)
|
||||
return n.storage.UserEntryWithPassword(conn, user, string(clientAuthPluginData[:len(clientAuthPluginData)-1]), remoteAddr)
|
||||
}
|
||||
|
||||
func (n *mysqlDialogAuthMethod) AllowClearTextWithoutTLS() bool {
|
||||
|
@ -524,7 +523,7 @@ func (n *mysqlCachingSha2AuthMethod) HandleAuthPluginData(c *Conn, user string,
|
|||
}
|
||||
|
||||
salt := serverAuthPluginData[:len(serverAuthPluginData)-1]
|
||||
result, cacheState, err := n.cache.UserEntryWithCacheHash(c.GetTLSClientCerts(), salt, user, clientAuthPluginData, remoteAddr)
|
||||
result, cacheState, err := n.cache.UserEntryWithCacheHash(c, salt, user, clientAuthPluginData, remoteAddr)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -560,7 +559,7 @@ func (n *mysqlCachingSha2AuthMethod) HandleAuthPluginData(c *Conn, user string,
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return n.storage.UserEntryWithPassword(c.GetTLSClientCerts(), user, password, remoteAddr)
|
||||
return n.storage.UserEntryWithPassword(c, user, password, remoteAddr)
|
||||
default:
|
||||
// Somehow someone returned an unknown state, let's error with access denied.
|
||||
return nil, NewSQLError(ERAccessDeniedError, SSAccessDeniedError, "Access denied for user '%v'", user)
|
||||
|
|
|
@ -17,7 +17,6 @@ limitations under the License.
|
|||
package mysql
|
||||
|
||||
import (
|
||||
"crypto/x509"
|
||||
"flag"
|
||||
"fmt"
|
||||
"net"
|
||||
|
@ -85,7 +84,8 @@ func (asl *AuthServerClientCert) HandleUser(user string) bool {
|
|||
}
|
||||
|
||||
// UserEntryWithPassword is part of the PlaintextStorage interface
|
||||
func (asl *AuthServerClientCert) UserEntryWithPassword(userCerts []*x509.Certificate, user string, password string, remoteAddr net.Addr) (Getter, error) {
|
||||
func (asl *AuthServerClientCert) UserEntryWithPassword(conn *Conn, user string, password string, remoteAddr net.Addr) (Getter, error) {
|
||||
userCerts := conn.GetTLSClientCerts()
|
||||
if len(userCerts) == 0 {
|
||||
return nil, fmt.Errorf("no client certs for connection")
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@ limitations under the License.
|
|||
package mysql
|
||||
|
||||
import (
|
||||
"crypto/x509"
|
||||
"net"
|
||||
|
||||
querypb "vitess.io/vitess/go/vt/proto/query"
|
||||
|
@ -51,7 +50,7 @@ func (a *AuthServerNone) HandleUser(user string) bool {
|
|||
|
||||
// UserEntryWithHash validates the user if it exists and returns the information.
|
||||
// Always accepts any user.
|
||||
func (a *AuthServerNone) UserEntryWithHash(userCerts []*x509.Certificate, salt []byte, user string, authResponse []byte, remoteAddr net.Addr) (Getter, error) {
|
||||
func (a *AuthServerNone) UserEntryWithHash(conn *Conn, salt []byte, user string, authResponse []byte, remoteAddr net.Addr) (Getter, error) {
|
||||
return &NoneGetter{}, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@ package mysql
|
|||
import (
|
||||
"bytes"
|
||||
"crypto/subtle"
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"net"
|
||||
|
@ -161,7 +160,7 @@ func (a *AuthServerStatic) HandleUser(user string) bool {
|
|||
|
||||
// UserEntryWithPassword implements password lookup based on a plain
|
||||
// text password that is negotiated with the client.
|
||||
func (a *AuthServerStatic) UserEntryWithPassword(userCerts []*x509.Certificate, user string, password string, remoteAddr net.Addr) (Getter, error) {
|
||||
func (a *AuthServerStatic) UserEntryWithPassword(conn *Conn, user string, password string, remoteAddr net.Addr) (Getter, error) {
|
||||
a.mu.Lock()
|
||||
entries, ok := a.entries[user]
|
||||
a.mu.Unlock()
|
||||
|
@ -181,7 +180,7 @@ func (a *AuthServerStatic) UserEntryWithPassword(userCerts []*x509.Certificate,
|
|||
|
||||
// UserEntryWithHash implements password lookup based on a
|
||||
// mysql_native_password hash that is negotiated with the client.
|
||||
func (a *AuthServerStatic) UserEntryWithHash(userCerts []*x509.Certificate, salt []byte, user string, authResponse []byte, remoteAddr net.Addr) (Getter, error) {
|
||||
func (a *AuthServerStatic) UserEntryWithHash(conn *Conn, salt []byte, user string, authResponse []byte, remoteAddr net.Addr) (Getter, error) {
|
||||
a.mu.Lock()
|
||||
entries, ok := a.entries[user]
|
||||
a.mu.Unlock()
|
||||
|
@ -214,7 +213,7 @@ func (a *AuthServerStatic) UserEntryWithHash(userCerts []*x509.Certificate, salt
|
|||
|
||||
// UserEntryWithCacheHash implements password lookup based on a
|
||||
// caching_sha2_password hash that is negotiated with the client.
|
||||
func (a *AuthServerStatic) UserEntryWithCacheHash(userCerts []*x509.Certificate, salt []byte, user string, authResponse []byte, remoteAddr net.Addr) (Getter, CacheState, error) {
|
||||
func (a *AuthServerStatic) UserEntryWithCacheHash(conn *Conn, salt []byte, user string, authResponse []byte, remoteAddr net.Addr) (Getter, CacheState, error) {
|
||||
a.mu.Lock()
|
||||
entries, ok := a.entries[user]
|
||||
a.mu.Unlock()
|
||||
|
|
|
@ -17,7 +17,6 @@ limitations under the License.
|
|||
package ldapauthserver
|
||||
|
||||
import (
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
|
@ -118,7 +117,7 @@ func (asl *AuthServerLdap) HandleUser(user string) bool {
|
|||
|
||||
// UserEntryWithPassword is part of the PlaintextStorage interface
|
||||
// and called after the password is sent by the client.
|
||||
func (asl *AuthServerLdap) UserEntryWithPassword(userCerts []*x509.Certificate, user string, password string, remoteAddr net.Addr) (mysql.Getter, error) {
|
||||
func (asl *AuthServerLdap) UserEntryWithPassword(conn *mysql.Conn, user string, password string, remoteAddr net.Addr) (mysql.Getter, error) {
|
||||
return asl.validate(user, password)
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@ package vault
|
|||
|
||||
import (
|
||||
"crypto/subtle"
|
||||
"crypto/x509"
|
||||
"flag"
|
||||
"fmt"
|
||||
"net"
|
||||
|
@ -166,7 +165,7 @@ func (a *AuthServerVault) HandleUser(user string) bool {
|
|||
}
|
||||
|
||||
// UserEntryWithHash is called when mysql_native_password is used.
|
||||
func (a *AuthServerVault) UserEntryWithHash(userCerts []*x509.Certificate, salt []byte, user string, authResponse []byte, remoteAddr net.Addr) (mysql.Getter, error) {
|
||||
func (a *AuthServerVault) UserEntryWithHash(conn *mysql.Conn, salt []byte, user string, authResponse []byte, remoteAddr net.Addr) (mysql.Getter, error) {
|
||||
a.mu.Lock()
|
||||
userEntries, ok := a.entries[user]
|
||||
a.mu.Unlock()
|
||||
|
|
Загрузка…
Ссылка в новой задаче