]> granicus.if.org Git - postgresql/commitdiff
Commit to support MD5 passwords as per the backend for 7.2. This patch was submitted...
authorBarry Lind <barry@xythos.com>
Mon, 12 Nov 2001 19:11:56 +0000 (19:11 +0000)
committerBarry Lind <barry@xythos.com>
Mon, 12 Nov 2001 19:11:56 +0000 (19:11 +0000)
src/interfaces/jdbc/org/postgresql/Connection.java
src/interfaces/jdbc/org/postgresql/util/MD5Digest.java [new file with mode: 0644]

index 0982428e9ec3ef396cfbac1711bf311926de75f7..0d53b96e4868a698234c533702dbee1ade726823 100644 (file)
@@ -11,7 +11,7 @@ import org.postgresql.util.*;
 import org.postgresql.core.*;
 
 /**
- * $Id: Connection.java,v 1.34 2001/11/01 01:08:36 barry Exp $
+ * $Id: Connection.java,v 1.35 2001/11/12 19:11:56 barry Exp $
  *
  * This abstract class is used by org.postgresql.Driver to open either the JDBC1 or
  * JDBC2 versions of the Connection class.
@@ -63,6 +63,7 @@ public abstract class Connection
        private static final int AUTH_REQ_KRB5 = 2;
        private static final int AUTH_REQ_PASSWORD = 3;
        private static final int AUTH_REQ_CRYPT = 4;
+        private static final int AUTH_REQ_MD5 = 5;
 
        // New for 6.3, salt value for crypt authorisation
        private String salt;
@@ -180,22 +181,34 @@ public abstract class Connection
                                        // Get the type of request
                                        areq = pg_stream.ReceiveIntegerR(4);
 
-                                       // Get the password salt if there is one
+                                       // Get the crypt password salt if there is one
                                        if (areq == AUTH_REQ_CRYPT)
                                        {
                                                byte[] rst = new byte[2];
                                                rst[0] = (byte)pg_stream.ReceiveChar();
                                                rst[1] = (byte)pg_stream.ReceiveChar();
                                                salt = new String(rst, 0, 2);
-                                               DriverManager.println("Salt=" + salt);
+                                               DriverManager.println("Crypt salt=" + salt);
+                                       }
+
+                                       // Or get the md5 password salt if there is one
+                                       if (areq == AUTH_REQ_MD5)
+                                       {
+                                               byte[] rst = new byte[4];
+                                               rst[0] = (byte)pg_stream.ReceiveChar();
+                                               rst[1] = (byte)pg_stream.ReceiveChar();
+                                               rst[2] = (byte)pg_stream.ReceiveChar();
+                                               rst[3] = (byte)pg_stream.ReceiveChar();
+                                               salt = new String(rst, 0, 4);
+                                               DriverManager.println("MD5 salt=" + salt);
                                        }
 
                                        // now send the auth packet
                                        switch (areq)
                                        {
                                        case AUTH_REQ_OK:
-                                               break;
-
+                                           break;
+                                               
                                        case AUTH_REQ_KRB4:
                                                DriverManager.println("postgresql: KRB4");
                                                throw new PSQLException("postgresql.con.kerb4");
@@ -221,6 +234,15 @@ public abstract class Connection
                                                pg_stream.flush();
                                                break;
 
+                                       case AUTH_REQ_MD5:
+                                               DriverManager.println("postgresql: MD5");
+                                               byte[] digest = MD5Digest.encode(PG_USER, PG_PASSWORD, salt);
+                                               pg_stream.SendInteger(5 + digest.length, 4);
+                                               pg_stream.Send(digest);
+                                               pg_stream.SendInteger(0, 1);
+                                               pg_stream.flush();
+                                               break;
+
                                        default:
                                                throw new PSQLException("postgresql.con.auth", new Integer(areq));
                                        }
diff --git a/src/interfaces/jdbc/org/postgresql/util/MD5Digest.java b/src/interfaces/jdbc/org/postgresql/util/MD5Digest.java
new file mode 100644 (file)
index 0000000..450f242
--- /dev/null
@@ -0,0 +1,73 @@
+package org.postgresql.util;
+
+/**
+ * MD5-based utility function to obfuscate passwords before network transmission
+ *
+ * @author Jeremy Wohl
+ *
+ */
+
+import java.security.*;
+
+public class MD5Digest
+{
+    private MD5Digest() {}
+
+
+    /**
+     * Encodes user/password/salt information in the following way:
+     *   MD5(MD5(password + user) + salt)
+     *
+     * @param user      The connecting user.
+     * @param password  The connecting user's password.
+     * @param salt      A four-character string sent by the server.
+     *
+     * @return  A 35-byte array, comprising the string "md5", followed by an MD5 digest.
+     */
+    public static byte[] encode(String user, String password, String salt)
+    {
+       MessageDigest  md;
+       byte[]         temp_digest, pass_digest;
+       byte[]         hex_digest = new byte[35];
+           
+
+       try {
+           md = MessageDigest.getInstance("MD5");
+
+           md.update(password.getBytes());
+           md.update(user.getBytes());
+           temp_digest = md.digest();
+
+           bytesToHex(temp_digest, hex_digest, 0);
+           md.update(hex_digest, 0, 32);
+           md.update(salt.getBytes());
+           pass_digest = md.digest();
+
+           bytesToHex(pass_digest, hex_digest, 3);
+           hex_digest[0] = (byte) 'm'; hex_digest[1] = (byte) 'd'; hex_digest[2] = (byte) '5';
+       } catch (Exception e) {
+           ; // "MessageDigest failure; " + e
+       }
+
+       return hex_digest;
+    }
+
+
+    /**
+     * Turn 16-byte stream into a human-readable 32-byte hex string
+     */
+    private static void bytesToHex(byte[] bytes, byte[] hex, int offset)
+    {
+       final char lookup[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+                               'a', 'b', 'c', 'd', 'e', 'f' };
+       
+       int i, c, j, pos = offset;
+       
+       for (i = 0; i < 16; i++) {
+           c = bytes[i] & 0xFF; j = c >> 4;
+           hex[pos++] = (byte) lookup[j];
+           j = (c & 0xF);
+           hex[pos++] = (byte) lookup[j];
+       }
+    }
+}