From ee1c11a8e77b47d9219bf1f80e675d0c650f7fd8 Mon Sep 17 00:00:00 2001 From: Reinier Schoof Date: Mon, 23 Aug 2021 16:24:43 +0200 Subject: [PATCH] allow to set certain client-side capabilities --- client/auth.go | 13 +++++++++++-- client/client_test.go | 35 +++++++++++++++++++++++++++++++++++ client/conn.go | 13 +++++++++++++ 3 files changed, 59 insertions(+), 2 deletions(-) diff --git a/client/auth.go b/client/auth.go index 01217f834..1a045be44 100644 --- a/client/auth.go +++ b/client/auth.go @@ -140,9 +140,18 @@ func (c *Conn) writeAuthHandshake() error { if !authPluginAllowed(c.authPluginName) { return fmt.Errorf("unknow auth plugin name '%s'", c.authPluginName) } - // Adjust client capability flags based on server support + + // Set default client capabilities that reflect the abilities of this library capability := CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION | - CLIENT_LONG_PASSWORD | CLIENT_TRANSACTIONS | CLIENT_PLUGIN_AUTH | c.capability&CLIENT_LONG_FLAG + CLIENT_LONG_PASSWORD | CLIENT_TRANSACTIONS | CLIENT_PLUGIN_AUTH + // Adjust client capability flags based on server support + capability |= c.capability & CLIENT_LONG_FLAG + // Adjust client capability flags on specific client requests + // Only flags that would make any sense setting and aren't handled elsewhere + // in the library are supported here + capability |= c.ccaps&CLIENT_FOUND_ROWS | c.ccaps&CLIENT_IGNORE_SPACE | + c.ccaps&CLIENT_MULTI_STATEMENTS | c.ccaps&CLIENT_MULTI_RESULTS | + c.ccaps&CLIENT_PS_MULTI_RESULTS | c.ccaps&CLIENT_CONNECT_ATTRS // To enable TLS / SSL if c.tlsConfig != nil { diff --git a/client/client_test.go b/client/client_test.go index 53d43c199..121051f1b 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -94,6 +94,41 @@ func (s *clientTestSuite) TestConn_Ping(c *C) { c.Assert(err, IsNil) } +func (s *clientTestSuite) TestConn_SetCapability(c *C) { + caps := []uint32{ + mysql.CLIENT_LONG_PASSWORD, + mysql.CLIENT_FOUND_ROWS, + mysql.CLIENT_LONG_FLAG, + mysql.CLIENT_CONNECT_WITH_DB, + mysql.CLIENT_NO_SCHEMA, + mysql.CLIENT_COMPRESS, + mysql.CLIENT_ODBC, + mysql.CLIENT_LOCAL_FILES, + mysql.CLIENT_IGNORE_SPACE, + mysql.CLIENT_PROTOCOL_41, + mysql.CLIENT_INTERACTIVE, + mysql.CLIENT_SSL, + mysql.CLIENT_IGNORE_SIGPIPE, + mysql.CLIENT_TRANSACTIONS, + mysql.CLIENT_RESERVED, + mysql.CLIENT_SECURE_CONNECTION, + mysql.CLIENT_MULTI_STATEMENTS, + mysql.CLIENT_MULTI_RESULTS, + mysql.CLIENT_PS_MULTI_RESULTS, + mysql.CLIENT_PLUGIN_AUTH, + mysql.CLIENT_CONNECT_ATTRS, + mysql.CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA, + } + + for _, cap := range caps { + c.Assert(s.c.ccaps&cap > 0, IsFalse) + s.c.SetCapability(cap) + c.Assert(s.c.ccaps&cap > 0, IsTrue) + s.c.UnsetCapability(cap) + c.Assert(s.c.ccaps&cap > 0, IsFalse) + } +} + // NOTE for MySQL 5.5 and 5.6, server side has to config SSL to pass the TLS test, otherwise, it will throw error that // MySQL server does not support TLS required by the client. However, for MySQL 5.7 and above, auto generated certificates // are used by default so that manual config is no longer necessary. diff --git a/client/conn.go b/client/conn.go index 1b3744466..02c10cffc 100644 --- a/client/conn.go +++ b/client/conn.go @@ -21,7 +21,10 @@ type Conn struct { tlsConfig *tls.Config proto string + // server capabilities capability uint32 + // client-set capabilities only + ccaps uint32 status uint16 @@ -120,6 +123,16 @@ func (c *Conn) Ping() error { return nil } +// SetCapability enables the use of a specific capability +func (c *Conn) SetCapability(cap uint32) { + c.ccaps |= cap +} + +// UnsetCapability disables the use of a specific capability +func (c *Conn) UnsetCapability(cap uint32) { + c.ccaps &= ^cap +} + // UseSSL: use default SSL // pass to options when connect func (c *Conn) UseSSL(insecureSkipVerify bool) {