public static byte[] Create(InitialHandshakePacket handshake, ConnectionSettings cs)
        {
            // TODO: verify server capabilities

            var writer = CreateCapabilitiesPayload(handshake.ProtocolCapabilities, cs);

            writer.WriteNullTerminatedString(cs.UserID);
            var authenticationResponse = AuthenticationUtility.CreateAuthenticationResponse(handshake.AuthPluginData, 0, cs.Password);

            writer.WriteByte((byte)authenticationResponse.Length);
            writer.Write(authenticationResponse);

            if (!string.IsNullOrWhiteSpace(cs.Database))
            {
                writer.WriteNullTerminatedString(cs.Database);
            }

            if ((handshake.ProtocolCapabilities & ProtocolCapabilities.PluginAuth) != 0)
            {
                writer.WriteNullTerminatedString("mysql_native_password");
            }

            return(writer.ToBytes());
        }
Example #2
0
        public async Task ConnectAsync(ConnectionSettings cs, IOBehavior ioBehavior, CancellationToken cancellationToken)
        {
            var connected = false;

            if (cs.ConnectionType == ConnectionType.Tcp)
            {
                connected = await OpenTcpSocketAsync(cs, ioBehavior, cancellationToken).ConfigureAwait(false);
            }
            else if (cs.ConnectionType == ConnectionType.Unix)
            {
                connected = await OpenUnixSocketAsync(cs, ioBehavior, cancellationToken).ConfigureAwait(false);
            }
            if (!connected)
            {
                throw new MyCatException("Unable to connect to any of the specified MySQL hosts.");
            }

            var socketByteHandler = new SocketByteHandler(m_socket);

            m_payloadHandler = new StandardPayloadHandler(socketByteHandler);

            var payload = await ReceiveAsync(ioBehavior, cancellationToken).ConfigureAwait(false);

            var reader           = new ByteArrayReader(payload.ArraySegment.Array, payload.ArraySegment.Offset, payload.ArraySegment.Count);
            var initialHandshake = new InitialHandshakePacket(reader);

            // if PluginAuth is supported, then use the specified auth plugin; else, fall back to protocol capabilities to determine the auth type to use
            string authPluginName;

            if ((initialHandshake.ProtocolCapabilities & ProtocolCapabilities.PluginAuth) != 0)
            {
                authPluginName = initialHandshake.AuthPluginName;
            }
            else
            {
                authPluginName = (initialHandshake.ProtocolCapabilities & ProtocolCapabilities.SecureConnection) == 0 ? "mysql_old_password" : "mysql_native_password";
            }
            if (authPluginName != "mysql_native_password")
            {
                throw new NotSupportedException("Authentication method '{0}' is not supported.".FormatInvariant(initialHandshake.AuthPluginName));
            }

            ServerVersion  = new ServerVersion(Encoding.ASCII.GetString(initialHandshake.ServerVersion));
            ConnectionId   = initialHandshake.ConnectionId;
            AuthPluginData = initialHandshake.AuthPluginData;
            if (cs.UseCompression && (initialHandshake.ProtocolCapabilities & ProtocolCapabilities.Compress) == 0)
            {
                cs = cs.WithUseCompression(false);
            }

            if (cs.SslMode != MyCatSslMode.None)
            {
                await InitSslAsync(initialHandshake.ProtocolCapabilities, cs, ioBehavior, cancellationToken).ConfigureAwait(false);
            }

            var response = HandshakeResponse41Packet.Create(initialHandshake, cs);

            payload = new PayloadData(new ArraySegment <byte>(response));
            await SendReplyAsync(payload, ioBehavior, cancellationToken).ConfigureAwait(false);

            payload = await ReceiveReplyAsync(ioBehavior, cancellationToken).ConfigureAwait(false);

            OkPayload.Create(payload);

            if (cs.UseCompression)
            {
                m_payloadHandler = new CompressedPayloadHandler(m_payloadHandler.ByteHandler);
            }
        }