Commit 3a306eef authored by Barry Lind's avatar Barry Lind

Commit to support MD5 passwords as per the backend for 7.2. This patch was...

Commit to support MD5 passwords as per the backend for 7.2.  This patch was submitted by Jeremy Wohl jeremyw-pgjdbc@igmus.org
parent d7a343d5
...@@ -11,7 +11,7 @@ import org.postgresql.util.*; ...@@ -11,7 +11,7 @@ import org.postgresql.util.*;
import org.postgresql.core.*; 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 * This abstract class is used by org.postgresql.Driver to open either the JDBC1 or
* JDBC2 versions of the Connection class. * JDBC2 versions of the Connection class.
...@@ -63,6 +63,7 @@ public abstract class Connection ...@@ -63,6 +63,7 @@ public abstract class Connection
private static final int AUTH_REQ_KRB5 = 2; private static final int AUTH_REQ_KRB5 = 2;
private static final int AUTH_REQ_PASSWORD = 3; private static final int AUTH_REQ_PASSWORD = 3;
private static final int AUTH_REQ_CRYPT = 4; 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 // New for 6.3, salt value for crypt authorisation
private String salt; private String salt;
...@@ -180,22 +181,34 @@ public abstract class Connection ...@@ -180,22 +181,34 @@ public abstract class Connection
// Get the type of request // Get the type of request
areq = pg_stream.ReceiveIntegerR(4); 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) if (areq == AUTH_REQ_CRYPT)
{ {
byte[] rst = new byte[2]; byte[] rst = new byte[2];
rst[0] = (byte)pg_stream.ReceiveChar(); rst[0] = (byte)pg_stream.ReceiveChar();
rst[1] = (byte)pg_stream.ReceiveChar(); rst[1] = (byte)pg_stream.ReceiveChar();
salt = new String(rst, 0, 2); 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 // now send the auth packet
switch (areq) switch (areq)
{ {
case AUTH_REQ_OK: case AUTH_REQ_OK:
break; break;
case AUTH_REQ_KRB4: case AUTH_REQ_KRB4:
DriverManager.println("postgresql: KRB4"); DriverManager.println("postgresql: KRB4");
throw new PSQLException("postgresql.con.kerb4"); throw new PSQLException("postgresql.con.kerb4");
...@@ -221,6 +234,15 @@ public abstract class Connection ...@@ -221,6 +234,15 @@ public abstract class Connection
pg_stream.flush(); pg_stream.flush();
break; 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: default:
throw new PSQLException("postgresql.con.auth", new Integer(areq)); throw new PSQLException("postgresql.con.auth", new Integer(areq));
} }
......
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];
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment