diff --git a/lib/frontend/frontends/v0/auth/md5.go b/lib/frontend/frontends/v0/auth/md5.go
new file mode 100644
index 0000000000000000000000000000000000000000..5ec1f5814ee5f643cccaf0bd042f5fcd2b16cf52
--- /dev/null
+++ b/lib/frontend/frontends/v0/auth/md5.go
@@ -0,0 +1,36 @@
+package auth
+
+import (
+	"crypto/md5"
+	"encoding/hex"
+	"strings"
+)
+
+func EncodeMD5(username, password string, salt [4]byte) string {
+	hash := md5.New()
+	hash.Write([]byte(password))
+	hash.Write([]byte(username))
+	sum1 := hash.Sum(nil)
+	hexEncoded := make([]byte, hex.EncodedLen(len(sum1)))
+	hex.Encode(hexEncoded, sum1)
+	hash.Reset()
+
+	hash.Write(hexEncoded)
+	hash.Write(salt[:])
+	sum2 := hash.Sum(nil)
+	hexEncoded = hexEncoded[:0]
+	for i := 0; i < hex.EncodedLen(len(sum2)); i++ {
+		hexEncoded = append(hexEncoded, 0)
+	}
+	hex.Encode(hexEncoded, sum2)
+
+	var out strings.Builder
+	out.Grow(3 + len(hexEncoded))
+	out.WriteString("md5")
+	out.Write(hexEncoded)
+	return out.String()
+}
+
+func CheckMD5(username, password string, salt [4]byte, encoded string) bool {
+	return EncodeMD5(username, password, salt) == encoded
+}
diff --git a/lib/frontend/frontends/v0/client.go b/lib/frontend/frontends/v0/client.go
index ac193052e47952a7ec01551e4396b958b89790d8..44fac2d4d7bcb01f9fd16ddb7046392107d9a7ea 100644
--- a/lib/frontend/frontends/v0/client.go
+++ b/lib/frontend/frontends/v0/client.go
@@ -6,13 +6,14 @@ import (
 	"net"
 
 	"pggat2/lib/frontend"
+	"pggat2/lib/frontend/frontends/v0/auth"
 	"pggat2/lib/perror"
 	"pggat2/lib/pnet"
 	"pggat2/lib/pnet/packet"
 )
 
 var ErrBadPacketFormat = perror.New(
-	perror.ERROR,
+	perror.FATAL,
 	perror.ProtocolViolation,
 	"Bad packet format",
 )
@@ -63,7 +64,7 @@ func (T *Client) accept() error {
 			case 5678:
 				// Cancel
 				err = T.Error(perror.New(
-					perror.ERROR,
+					perror.FATAL,
 					perror.FeatureNotSupported,
 					"Cancel is not supported yet",
 				))
@@ -87,7 +88,7 @@ func (T *Client) accept() error {
 				continue
 			default:
 				err = T.Error(perror.New(
-					perror.ERROR,
+					perror.FATAL,
 					perror.ProtocolViolation,
 					"Unknown request code",
 				))
@@ -100,7 +101,7 @@ func (T *Client) accept() error {
 
 		if majorVersion != 3 || minorVersion != 0 {
 			err = T.Error(perror.New(
-				perror.ERROR,
+				perror.FATAL,
 				perror.ProtocolViolation,
 				"Unsupported protocol version",
 			))
@@ -128,19 +129,19 @@ func (T *Client) accept() error {
 				T.database = value
 			case "options":
 				return T.Error(perror.New(
-					perror.ERROR,
+					perror.FATAL,
 					perror.FeatureNotSupported,
 					"Startup options are not supported yet",
 				))
 			case "replication":
 				return T.Error(perror.New(
-					perror.ERROR,
+					perror.FATAL,
 					perror.FeatureNotSupported,
 					"Replication mode is not supported yet",
 				))
 			default:
 				return T.Error(perror.New(
-					perror.ERROR,
+					perror.FATAL,
 					perror.ProtocolViolation,
 					"Unsupported startup parameter",
 				))
@@ -149,8 +150,8 @@ func (T *Client) accept() error {
 
 		if T.user == "" {
 			return T.Error(perror.New(
-				perror.ERROR,
-				perror.InvalidPassword,
+				perror.FATAL,
+				perror.InvalidAuthorizationSpecification,
 				"User is required",
 			))
 		}
@@ -190,7 +191,7 @@ func (T *Client) accept() error {
 	reader := packet.MakeReader(password)
 	if reader.Type() != packet.AuthenticationResponse {
 		return T.Error(perror.New(
-			perror.ERROR,
+			perror.FATAL,
 			perror.ProtocolViolation,
 			"Expected password",
 		))
@@ -202,6 +203,13 @@ func (T *Client) accept() error {
 	}
 
 	log.Print("password=", pw)
+	if !auth.CheckMD5("test", "password", salt, pw) {
+		return T.Error(perror.New(
+			perror.FATAL,
+			perror.InvalidPassword,
+			"Invalid password",
+		))
+	}
 
 	return nil
 }
diff --git a/lib/frontend/frontends/v0/frontend.go b/lib/frontend/frontends/v0/frontend.go
index 17020e8f95f9f13a964d452d0a3778a1d6dbd68a..ac982a7356006ef1cd96ebfab9e35dacd301b8cd 100644
--- a/lib/frontend/frontends/v0/frontend.go
+++ b/lib/frontend/frontends/v0/frontend.go
@@ -1,6 +1,7 @@
 package frontends
 
 import (
+	"log"
 	"net"
 
 	"pggat2/lib/frontend"
@@ -30,9 +31,10 @@ func (T *Frontend) Run() error {
 
 		client, err := NewClient(conn)
 		if err != nil {
-			return err
+			log.Println("rejected client:", err)
+		} else {
+			T.clients = append(T.clients, client)
 		}
-		T.clients = append(T.clients, client)
 	}
 }