protocol

package
v1.7.11 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 29, 2022 License: Apache-2.0 Imports: 8 Imported by: 0

Documentation

Index

Constants

View Source
const (
	ComQuery byte
	ComFieldList

	ComStmtPrepare
	ComStmtExecute

	ComStmtClose
)

Protocol commands

View Source
const (
	ClientLongPassword uint32 = 1 << iota
	ClientFoundRows
	ClientLongFlag
	ClientConnectWithDB
	ClientNoSchema
	ClientCompress
	ClientODBC
	ClientLocalFiles
	ClientIgnoreSpace
	ClientProtocol41
	ClientInteractive
	ClientSSL
	ClientIgnoreSIGPIPE
	ClientTransactions
	ClientReserved
	ClientSecureConnection
	ClientMultiStatements
	ClientMultiResults
	ClientPSMultiResults
	ClientPluginAuth
	ClientConnectAttrs
	ClientPluginAuthLenEncClientData
	ClientCanHandleExpiredPasswords
	ClientSessionTrack
	ClientDeprecateEOF
)

Capability flags

View Source
const (
	CRUnknownError = 2000

	// CRSSLConnectionError is CR_SSL_CONNECTION_ERROR
	CRSSLConnectionError = 2026
)

MySQL Error Codes

View Source
const (
	// ErrorCodeInternalError indicates an unspecified internal error.
	ErrorCodeInternalError = "HY000"
)
View Source
const (
	ResponseErr = 0xff
)

Random constants

Variables

View Source
var ErrFieldTypeNotImplementedYet = errors.New("Protocol: Required field type not implemented yet")

ErrFieldTypeNotImplementedYet is for field types that are not yet implemented

View Source
var ErrInvalidPacketLength = errors.New("Protocol: Invalid packet length")

ErrInvalidPacketLength is for invalid packet lengths

View Source
var ErrInvalidPacketType = errors.New("Protocol: Invalid packet type")

ErrInvalidPacketType is for invalid packet types

View Source
var ErrNoTLS = Error{
	Code:     CRSSLConnectionError,
	SQLState: ErrorCodeInternalError,
	Message:  "SSL connection error: SSL is required but the server doesn't support it",
}

ErrNoTLS is a MySQL protocol error raised when SSL is required but the server doesn't support it.

Functions

func CheckPacketLength

func CheckPacketLength(expected int, packet []byte) error

CheckPacketLength checks if packet length meets expected value

func GetLenEncodedIntegerSize

func GetLenEncodedIntegerSize(firstByte byte) byte

GetLenEncodedIntegerSize returns bytes count for length encoded integer determined by it's 1st byte

func GetPacketHeader

func GetPacketHeader(r *bytes.Reader) (s []byte, e error)

GetPacketHeader rewinds reader to packet payload

func GetPacketType

func GetPacketType(packet []byte) byte

GetPacketType extracts the PacketType byte Part of basic packet structure shown below.

int<3> PacketLength
int<1> PacketNumber
int<1> PacketType (0xFF)
... more ...

func InjectCredentials

func InjectCredentials(clientHandshake *HandshakeResponse41, salt []byte, username string, password string) (err error)

InjectCredentials takes in a HandshakeResponse41 from the client, the salt from the server, and a username / password, and uses the salt from the server handshake to inject the username / password credentials into the client handshake response

func NativePassword

func NativePassword(password []byte, salt []byte) (nativePassword []byte, err error)

NativePassword calculates native password expected by server in HandshakeResponse41 https://dev.mysql.com/doc/internals/en/secure-password-authentication.html#packet-Authentication::Native41 SHA1( password ) XOR SHA1( "20-bytes random data from server" <concat> SHA1( SHA1( password ) ) )

func PackHandshakeResponse41

func PackHandshakeResponse41(clientHandshake *HandshakeResponse41) (packet []byte, err error)

PackHandshakeResponse41 takes in a HandshakeResponse41 object and returns a handshake response packet

func ProcessHandshake

func ProcessHandshake(client net.Conn, mysql net.Conn) (*HandshakeV10, *HandshakeResponse41, error)

ProcessHandshake handles handshake between server and client. Returns server and client handshake responses

func ProxyPacket

func ProxyPacket(src, dst net.Conn) ([]byte, error)

ProxyPacket ...

func ReadEOFLengthString

func ReadEOFLengthString(data []byte) string

ReadEOFLengthString returns parsed EOF-length string. EOF-length strings are those strings whose length will be calculated by the packet remaining length. See https://mariadb.com/kb/en/mariadb/protocol-data-types/#end-of-file-length-strings

func ReadErrMessage

func ReadErrMessage(errPacket []byte) string

ReadErrMessage reads the message in an error packet

func ReadLenEncodedInteger

func ReadLenEncodedInteger(r *bytes.Reader) (value uint64, err error)

ReadLenEncodedInteger returns parsed length-encoded integer and it's offset. See https://mariadb.com/kb/en/mariadb/protocol-data-types/#length-encoded-integers

func ReadLenEncodedString

func ReadLenEncodedString(r *bytes.Reader) (string, uint64, error)

ReadLenEncodedString returns parsed length-encoded string and it's length. Length-encoded strings are prefixed by a length-encoded integer which describes the length of the string, followed by the string value. See https://mariadb.com/kb/en/mariadb/protocol-data-types/#length-encoded-strings

func ReadNullTerminatedBytes

func ReadNullTerminatedBytes(r *bytes.Reader) (str []byte)

ReadNullTerminatedBytes reads bytes from reader until 0x00 byte

func ReadNullTerminatedString

func ReadNullTerminatedString(r *bytes.Reader) string

ReadNullTerminatedString reads bytes from reader until 0x00 byte See https://mariadb.com/kb/en/mariadb/protocol-data-types/#null-terminated-strings

func ReadPacket

func ReadPacket(conn net.Conn) ([]byte, error)

ReadPacket ...

func ReadPrepareResponse

func ReadPrepareResponse(conn net.Conn) ([]byte, byte, error)

ReadPrepareResponse reads response from MySQL server for COM_STMT_PREPARE query issued by client. ...

func ReadResponse

func ReadResponse(conn net.Conn, deprecateEOF bool) ([]byte, byte, error)

ReadResponse reads the response

func ReadShowFieldsResponse

func ReadShowFieldsResponse(conn net.Conn) ([]byte, byte, error)

ReadShowFieldsResponse reads the response with deprecateEof set to true

func ReadUint24

func ReadUint24(b []byte) (uint32, error)

ReadUint24 takes in a byte slice and returns a uint32

func RemoveSSLFromHandshakeV10

func RemoveSSLFromHandshakeV10(packet []byte) ([]byte, error)

RemoveSSLFromHandshakeV10 removes Client SSL Capability from Server Handshake Packet. Secretless needs to do this to force the client to communicate with Secretless without using SSL. That half of the connection is insecure by design. Secretless then (usually) adds SSL for the other half of the communication -- between Secretless and the MySQL server.

func UnpackErrResponse

func UnpackErrResponse(data []byte) error

UnpackErrResponse decodes ERR_Packet from server. Part of basic packet structure shown below.

int<3> PacketLength int<1> PacketNumber int<1> PacketType (0xFF) int<2> ErrorCode if clientCapabilities & clientProtocol41

{
		string<1> SqlStateMarker (#)
		string<5> SqlState
}

string<EOF> Error

func UpdateHeaderPayloadLength

func UpdateHeaderPayloadLength(origHeader []byte, diff int32) (header []byte, err error)

UpdateHeaderPayloadLength takes in a 4 byte header and a difference in length, and returns a new header

func WritePacket

func WritePacket(pkt []byte, conn net.Conn) (int, error)

WritePacket ...

func WriteUint24

func WriteUint24(u uint32) (b []byte)

WriteUint24 takes in a uint32 and returns a byte slice

Types

type ConnSettings

type ConnSettings struct {
	ClientCapabilities uint32
	ServerCapabilities uint32
	SelectedDb         string
}

ConnSettings contains the connection settings

func (*ConnSettings) DeprecateEOFSet

func (h *ConnSettings) DeprecateEOFSet() bool

DeprecateEOFSet checks whether ClientDeprecateEOF is set on the client or server

type Error

type Error struct {
	Code     uint16
	SQLState string
	Message  string
}

Error is a MySQL processing error.

func NewGenericError

func NewGenericError(goErr error) Error

NewGenericError returns a MySQL protocol specific error, to handle cases that don't fit neatly into the MySQL code categories. This makes sense, since a Go error, eg, is not a true "protocol" error but instead something resulting from Secretless's role as a proxy, which MySQL is unaware of.

That said, we should try to use MySQL specific error codes wherever we can, so that client error messages will be more meaningful.

TODO: Replace instances of generic error with specific MySQL error codes.

func (Error) Error

func (e Error) Error() string

func (Error) GetPacket

func (e Error) GetPacket() []byte

GetPacket formats an Error into a protocol message. https://dev.mysql.com/doc/internals/en/packet-ERR_Packet.html

type ErrorContainer

type ErrorContainer interface {
	GetPacket() []byte
}

ErrorContainer interface makes it possible to have Go errors that can contain rich protocol specific information and have the smarts to encode themselves into a MYSQL error packet

type HandshakeResponse41

type HandshakeResponse41 struct {
	Header          []byte
	CapabilityFlags uint32
	MaxPacketSize   uint32
	ClientCharset   uint8
	Username        string
	AuthLength      int64
	AuthPluginName  string
	AuthResponse    []byte
	Database        string
	PacketTail      []byte
}

HandshakeResponse41 represents handshake response packet sent by 4.1+ clients supporting clientProtocol41 capability, if the server announced it in its initial handshake packet. See http://imysql.com/mysql-internal-manual/connection-phase-packets.html#packet-Protocol::HandshakeResponse41

The format of the header is also described here:

  https://dev.mysql.com/doc/internals/en/mysql-packet.html

 +-------------+----------------+---------------------------------------------+
 |    Type     |      Name      |                 Description                 |
	+-------------+----------------+---------------------------------------------+
 | int<3>      | payload_length | Length of the payload. The number of bytes  |
 |             |                | in the packet beyond the initial 4 bytes    |
 |             |                | that make up the packet header.             |
 | int<1>      | sequence_id    | Sequence ID                                 |
 | string<var> | payload        | [len=payload_length] payload of the packet  |
 +-------------+----------------+---------------------------------------------+

func UnpackHandshakeResponse41

func UnpackHandshakeResponse41(packet []byte) (*HandshakeResponse41, error)

UnpackHandshakeResponse41 decodes handshake response packet send by client. TODO: Add packet struct comment TODO: Add packet length check

type HandshakeV10

type HandshakeV10 struct {
	ProtocolVersion    byte
	ServerVersion      string
	ConnectionID       uint32
	ServerCapabilities uint32
	AuthPlugin         string
	Salt               []byte
}

HandshakeV10 represents sever's initial handshake packet See https://mariadb.com/kb/en/mariadb/1-connecting-connecting/#initial-handshake-packet

func UnpackHandshakeV10

func UnpackHandshakeV10(packet []byte) (*HandshakeV10, error)

UnpackHandshakeV10 decodes initial handshake request from server. Basic packet structure shown below. See http://imysql.com/mysql-internal-manual/connection-phase-packets.html#packet-Protocol::HandshakeV10

int<3> PacketLength int<1> PacketNumber int<1> ProtocolVersion string<NUL> ServerVersion int<4> ConnectionID string<8> AuthPluginDataPart1 (authentication seed) string<1> Reserved (always 0x00) int<2> ServerCapabilities (1st part) int<1> ServerDefaultCollation int<2> StatusFlags int<2> ServerCapabilities (2nd part) if capabilities & clientPluginAuth

{
		int<1> AuthPluginDataLength
}

else

{
		int<1> 0x00
}

string<10> Reserved (all 0x00) if capabilities & clientSecureConnection

{
		string[$len] AuthPluginDataPart2 ($len=MAX(13, AuthPluginDataLength - 8))
}

if capabilities & clientPluginAuth

{
		string[NUL] AuthPluginName
}

type MessageBuffer

type MessageBuffer struct {
	// contains filtered or unexported fields
}

MessageBuffer is a variable-sized byte buffer used to read and write msgs

A separate instance of a MessageBuffer should be use for reading and writing.

func NewMessageBuffer

func NewMessageBuffer(message []byte) *MessageBuffer

NewMessageBuffer creates and intializes a new MessageBuffer using message as its initial contents.

func (*MessageBuffer) Bytes

func (message *MessageBuffer) Bytes() []byte

Bytes gets the contents of the message buffer. This function is only useful after 'Write' operations as the underlying implementation will return the 'unread' portion of the buffer.

func (*MessageBuffer) ReadByte

func (message *MessageBuffer) ReadByte() (byte, error)

ReadByte reads a byte from the message buffer.

This function will read and return the next available byte from the message buffer.

func (*MessageBuffer) ReadInt32

func (message *MessageBuffer) ReadInt32() (value int32, err error)

ReadInt32 reads an int32 from the message buffer.

This function will read the next 4 available bytes from the message buffer and return them as an int32.

panic on error.

func (*MessageBuffer) ReadString

func (message *MessageBuffer) ReadString() (string, error)

ReadString reads a string from the message buffer.

This function will read and return the next Null terminated string from the message buffer.

func (*MessageBuffer) ResetLength

func (message *MessageBuffer) ResetLength(offset int)

ResetLength will reset the message length for the message.

func (*MessageBuffer) WriteByte

func (message *MessageBuffer) WriteByte(value byte) error

WriteByte will write the specified byte to the message buffer.

func (*MessageBuffer) WriteInt32

func (message *MessageBuffer) WriteInt32(value int32) (err error)

WriteInt32 will write a 4 byte int32 to the message buffer.

func (*MessageBuffer) WriteString

func (message *MessageBuffer) WriteString(value string) (int, error)

WriteString will write a NULL terminated string to the buffer. It is assumed that the incoming string has *NOT* been NULL terminated.

type OkResponse

type OkResponse struct {
	PacketType   byte
	AffectedRows uint64
	LastInsertID uint64
	StatusFlags  uint16
	Warnings     uint16
}

OkResponse represents packet sent from the server to the client to signal successful completion of a command https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_basic_ok_packet.html

func UnpackOkResponse

func UnpackOkResponse(packet []byte) (*OkResponse, error)

UnpackOkResponse decodes OK_Packet from server. Part of basic packet structure shown below.

int<3> PacketLength int<1> PacketNumber int<1> PacketType (0x00 or 0xFE) int<lenenc> AffectedRows int<lenenc> LastInsertID ... more ...

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL