Commit 1cc55168 authored by Barry Lind's avatar Barry Lind

Added support for SSL in the jdbc driver

 Modified Files:
 	jdbc/build.xml jdbc/org/postgresql/Driver.java.in
 	jdbc/org/postgresql/PG_Stream.java
 	jdbc/org/postgresql/errors.properties
 	jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java
 	jdbc/org/postgresql/util/PSQLException.java
parent 9ff872a2
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
This file now requires Ant 1.4.1. 2002-04-18 This file now requires Ant 1.4.1. 2002-04-18
$Header: /cvsroot/pgsql/src/interfaces/jdbc/Attic/build.xml,v 1.31 2002/12/11 12:27:47 davec Exp $ $Header: /cvsroot/pgsql/src/interfaces/jdbc/Attic/build.xml,v 1.32 2003/02/27 05:45:43 barry Exp $
--> -->
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
<property name="builddir" value="build" /> <property name="builddir" value="build" />
<property name="package" value="org/postgresql" /> <property name="package" value="org/postgresql" />
<property name="debug" value="on" /> <property name="debug" value="on" />
<property name="ssl" value="false" />
<property file="build.properties"/> <property file="build.properties"/>
...@@ -47,6 +48,7 @@ ...@@ -47,6 +48,7 @@
<equals arg1="${ant.java.version}" arg2="1.4"/> <equals arg1="${ant.java.version}" arg2="1.4"/>
</condition> </condition>
<available property="datasource" classname="javax.sql.DataSource"/> <available property="datasource" classname="javax.sql.DataSource"/>
<available property="ssl" classname="javax.net.ssl.SSLSocketFactory"/>
<available property="junit" classname="junit.framework.Test" /> <available property="junit" classname="junit.framework.Test" />
<condition property="jdbc2tests"> <condition property="jdbc2tests">
<and> <and>
...@@ -160,12 +162,27 @@ ...@@ -160,12 +162,27 @@
<equals arg1="${jdbc3}" arg2="true"/> <equals arg1="${jdbc3}" arg2="true"/>
</condition> </condition>
<!-- determine the ssl status -->
<condition property="ssl_config" value="">
<equals arg1="${ssl}" arg2="true"/>
</condition>
<condition property="ssl_config" value="//">
<equals arg1="${ssl}" arg2="false"/>
</condition>
<condition property="ssl_edition" value="SSL">
<equals arg1="${ssl}" arg2="true"/>
</condition>
<condition property="ssl_edition" value="NO SSL">
<equals arg1="${ssl}" arg2="false"/>
</condition>
<!-- Some defaults --> <!-- Some defaults -->
<filter token="MAJORVERSION" value="${major}" /> <filter token="MAJORVERSION" value="${major}" />
<filter token="MINORVERSION" value="${minor}" /> <filter token="MINORVERSION" value="${minor}" />
<filter token="VERSION" value="PostgreSQL ${fullversion} ${edition}" /> <filter token="VERSION" value="PostgreSQL ${fullversion} ${edition} with ${ssl_edition}" />
<filter token="JDBCCONNECTCLASS" value="${connectclass}" /> <filter token="JDBCCONNECTCLASS" value="${connectclass}" />
<filter token="DEF_PGPORT" value="${def_pgport}" /> <filter token="DEF_PGPORT" value="${def_pgport}" />
<filter token="SSL" value="${ssl_config}" />
<fail unless="major" message="'major' undefined. Please follow the directions in README."/> <fail unless="major" message="'major' undefined. Please follow the directions in README."/>
<fail unless="minor" message="'minor' undefined. Please follow the directions in README."/> <fail unless="minor" message="'minor' undefined. Please follow the directions in README."/>
...@@ -181,7 +198,7 @@ ...@@ -181,7 +198,7 @@
tofile="${package}/Driver.java" tofile="${package}/Driver.java"
filtering="yes" /> filtering="yes" />
<echo message="Configured build for the ${edition} edition driver" /> <echo message="Configured build for the ${edition} edition driver with ${ssl_edition}" />
</target> </target>
......
package org.postgresql; package org.postgresql;
import java.io.*;
import java.sql.*; import java.sql.*;
import java.util.*; import java.util.*;
...@@ -66,10 +67,12 @@ public class Driver implements java.sql.Driver ...@@ -66,10 +67,12 @@ public class Driver implements java.sql.Driver
* *
* user - (optional) The user to connect as * user - (optional) The user to connect as
* password - (optional) The password for the user * password - (optional) The password for the user
* ssl - (optional) Use SSL when connecting to the server
* charSet - (optional) The character set to be used for converting * charSet - (optional) The character set to be used for converting
* to/from the database to unicode. If multibyte is enabled on the * to/from the database to unicode. If multibyte is enabled on the
* server then the character set of the database is used as the default, * server then the character set of the database is used as the default,
* otherwise the jvm character encoding is used as the default. * otherwise the jvm character encoding is used as the default.
* This value is only used when connecting to a 7.2 or older server.
* loglevel - (optional) Enable logging of messages from the driver. * loglevel - (optional) Enable logging of messages from the driver.
* The value is an integer from 1 to 2 where: * The value is an integer from 1 to 2 where:
* INFO = 1, DEBUG = 2 * INFO = 1, DEBUG = 2
...@@ -136,8 +139,9 @@ public class Driver implements java.sql.Driver ...@@ -136,8 +139,9 @@ public class Driver implements java.sql.Driver
} }
catch (Exception ex2) catch (Exception ex2)
{ {
if (Driver.logDebug) if (Driver.logDebug) {
Driver.debug("error", ex2); Driver.debug("error", ex2);
}
throw new PSQLException("postgresql.unusual", ex2); throw new PSQLException("postgresql.unusual", ex2);
} }
} }
...@@ -211,7 +215,7 @@ public class Driver implements java.sql.Driver ...@@ -211,7 +215,7 @@ public class Driver implements java.sql.Driver
*/ */
public static String getVersion() public static String getVersion()
{ {
return "@VERSION@ jdbc driver build " + m_buildNumber; return "@VERSION@ (build " + m_buildNumber + ")";
} }
/* /*
...@@ -248,7 +252,17 @@ public class Driver implements java.sql.Driver ...@@ -248,7 +252,17 @@ public class Driver implements java.sql.Driver
String key = ""; String key = "";
String value = ""; String value = "";
StringTokenizer st = new StringTokenizer(url, ":/;=&?", true); String l_urlServer = url;
String l_urlArgs = "";
int l_qPos = url.indexOf('?');
if (l_qPos != -1) {
l_urlServer = url.substring(0,l_qPos);
l_urlArgs = url.substring(l_qPos+1);
}
//parse the server part of the url
StringTokenizer st = new StringTokenizer(l_urlServer, ":/", true);
for (int count = 0; (st.hasMoreTokens()); count++) for (int count = 0; (st.hasMoreTokens()); count++)
{ {
String token = st.nextToken(); String token = st.nextToken();
...@@ -318,25 +332,19 @@ public class Driver implements java.sql.Driver ...@@ -318,25 +332,19 @@ public class Driver implements java.sql.Driver
urlProps.put("PGDBNAME", token); urlProps.put("PGDBNAME", token);
state = -2; state = -2;
} }
else if (state <= -2 && (count % 2) == 1)
{
// PM Aug 2 1997 - added tests for ? and &
if (token.equals(";") || token.equals("?") || token.equals("&") )
state = -3;
else if (token.equals("="))
state = -5;
}
else if (state <= -2 && (count % 2) == 0)
{
if (state == -3)
key = token;
else if (state == -5)
{
value = token;
urlProps.put(key, value);
state = -2;
} }
} }
//parse the args part of the url
StringTokenizer qst = new StringTokenizer(l_urlArgs, "&");
for (int count = 0; (qst.hasMoreTokens()); count++)
{
String token = qst.nextToken();
int l_pos = token.indexOf('=');
if (l_pos == -1) {
urlProps.put(token, "");
} else {
urlProps.put(token.substring(0,l_pos), token.substring(l_pos+1));
} }
} }
...@@ -419,7 +427,10 @@ public class Driver implements java.sql.Driver ...@@ -419,7 +427,10 @@ public class Driver implements java.sql.Driver
{ {
if (logDebug) if (logDebug)
{ {
DriverManager.println(msg + ex != null ? ex.getMessage() : "null Exception"); DriverManager.println(msg);
if(ex != null) {
DriverManager.println(ex.toString());
}
} }
} }
/* /*
...@@ -441,10 +452,30 @@ public class Driver implements java.sql.Driver ...@@ -441,10 +452,30 @@ public class Driver implements java.sql.Driver
{ {
if (logInfo) if (logInfo)
{ {
DriverManager.println(msg + ex != null ? ex.getMessage() : "null Exception"); DriverManager.println(msg);
if(ex != null) {
DriverManager.println(ex.toString());
}
} }
} }
public static void makeSSL(PG_Stream p_stream) throws IOException {
@SSL@ if (logDebug)
@SSL@ debug("converting regular socket connection to ssl");
@SSL@ javax.net.ssl.SSLSocketFactory factory = (javax.net.ssl.SSLSocketFactory) javax.net.ssl.SSLSocketFactory.getDefault();
@SSL@ p_stream.connection = (javax.net.ssl.SSLSocket) factory.createSocket(p_stream.connection,p_stream.host,p_stream.port,true);
@SSL@ p_stream.pg_input = new BufferedInputStream(p_stream.connection.getInputStream(), 8192);
@SSL@ p_stream.pg_output = new BufferedOutputStream(p_stream.connection.getOutputStream(), 8192);
}
public static boolean sslEnabled() {
boolean l_return = false;
@SSL@ l_return = true;
return l_return;
}
//The build number should be incremented for every new build //The build number should be incremented for every new build
private static int m_buildNumber = 201; private static int m_buildNumber = 201;
......
...@@ -10,7 +10,7 @@ import org.postgresql.core.*; ...@@ -10,7 +10,7 @@ import org.postgresql.core.*;
import org.postgresql.util.*; import org.postgresql.util.*;
/* /*
* $Id: PG_Stream.java,v 1.17 2002/08/20 04:26:02 barry Exp $ * $Id: PG_Stream.java,v 1.18 2003/02/27 05:45:44 barry Exp $
* *
* This class is used by Connection & PGlobj for communicating with the * This class is used by Connection & PGlobj for communicating with the
* backend. * backend.
...@@ -20,9 +20,11 @@ import org.postgresql.util.*; ...@@ -20,9 +20,11 @@ import org.postgresql.util.*;
// This class handles all the Streamed I/O for a org.postgresql connection // This class handles all the Streamed I/O for a org.postgresql connection
public class PG_Stream public class PG_Stream
{ {
private Socket connection; public String host;
private InputStream pg_input; public int port;
private BufferedOutputStream pg_output; public Socket connection;
public InputStream pg_input;
public BufferedOutputStream pg_output;
private byte[] byte_buf = new byte[8*1024]; private byte[] byte_buf = new byte[8*1024];
/* /*
...@@ -33,8 +35,10 @@ public class PG_Stream ...@@ -33,8 +35,10 @@ public class PG_Stream
* @param port the port number that the postmaster is sitting on * @param port the port number that the postmaster is sitting on
* @exception IOException if an IOException occurs below it. * @exception IOException if an IOException occurs below it.
*/ */
public PG_Stream(String host, int port) throws IOException public PG_Stream(String p_host, int p_port) throws IOException
{ {
host = p_host;
port = p_port;
connection = new Socket(host, port); connection = new Socket(host, port);
// Submitted by Jason Venner <jason@idiom.com> adds a 10x speed // Submitted by Jason Venner <jason@idiom.com> adds a 10x speed
......
...@@ -19,6 +19,8 @@ postgresql.con.multres:Cannot handle multiple result groups. ...@@ -19,6 +19,8 @@ postgresql.con.multres:Cannot handle multiple result groups.
postgresql.con.pass:The password property is missing. It is mandatory. postgresql.con.pass:The password property is missing. It is mandatory.
postgresql.con.refused:Connection refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections. postgresql.con.refused:Connection refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
postgresql.con.setup:Protocol error. Session setup failed. postgresql.con.setup:Protocol error. Session setup failed.
postgresql.con.sslfail:An error occured while getting setting up the SSL connection.
postgresql.con.sslnotsupported:The server does not support SSL
postgresql.con.strobj:The object could not be stored. Check that any tables required have already been created in the database. postgresql.con.strobj:The object could not be stored. Check that any tables required have already been created in the database.
postgresql.con.strobjex:Failed to store object - {0} postgresql.con.strobjex:Failed to store object - {0}
postgresql.con.toolong:The SQL Statement is too long - {0} postgresql.con.toolong:The SQL Statement is too long - {0}
......
...@@ -14,7 +14,7 @@ import org.postgresql.largeobject.LargeObjectManager; ...@@ -14,7 +14,7 @@ import org.postgresql.largeobject.LargeObjectManager;
import org.postgresql.util.*; import org.postgresql.util.*;
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Connection.java,v 1.15 2003/02/05 11:12:39 davec Exp $ /* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Connection.java,v 1.16 2003/02/27 05:45:44 barry Exp $
* This class defines methods of the jdbc1 specification. This class is * This class defines methods of the jdbc1 specification. This class is
* extended by org.postgresql.jdbc2.AbstractJdbc2Connection which adds the jdbc2 * extended by org.postgresql.jdbc2.AbstractJdbc2Connection which adds the jdbc2
* methods. The real Connection class (for jdbc1) is org.postgresql.jdbc1.Jdbc1Connection * methods. The real Connection class (for jdbc1) is org.postgresql.jdbc1.Jdbc1Connection
...@@ -34,6 +34,7 @@ public abstract class AbstractJdbc1Connection implements org.postgresql.PGConnec ...@@ -34,6 +34,7 @@ public abstract class AbstractJdbc1Connection implements org.postgresql.PGConnec
protected String PG_DATABASE; protected String PG_DATABASE;
protected boolean PG_STATUS; protected boolean PG_STATUS;
protected String compatible; protected String compatible;
protected boolean useSSL;
// The PID an cancellation key we get from the backend process // The PID an cancellation key we get from the backend process
protected int pid; protected int pid;
...@@ -121,6 +122,15 @@ public abstract class AbstractJdbc1Connection implements org.postgresql.PGConnec ...@@ -121,6 +122,15 @@ public abstract class AbstractJdbc1Connection implements org.postgresql.PGConnec
PG_HOST = host; PG_HOST = host;
PG_STATUS = CONNECTION_BAD; PG_STATUS = CONNECTION_BAD;
if (info.getProperty("ssl") != null && this_driver.sslEnabled())
{
useSSL = true;
}
else
{
useSSL = false;
}
if (info.getProperty("compatible") == null) if (info.getProperty("compatible") == null)
{ {
compatible = d.getMajorVersion() + "." + d.getMinorVersion(); compatible = d.getMajorVersion() + "." + d.getMinorVersion();
...@@ -156,6 +166,11 @@ public abstract class AbstractJdbc1Connection implements org.postgresql.PGConnec ...@@ -156,6 +166,11 @@ public abstract class AbstractJdbc1Connection implements org.postgresql.PGConnec
//Print out the driver version number //Print out the driver version number
if (org.postgresql.Driver.logInfo) if (org.postgresql.Driver.logInfo)
org.postgresql.Driver.info(org.postgresql.Driver.getVersion()); org.postgresql.Driver.info(org.postgresql.Driver.getVersion());
if (org.postgresql.Driver.logDebug) {
org.postgresql.Driver.debug(" ssl = " + useSSL);
org.postgresql.Driver.debug(" compatible = " + compatible);
org.postgresql.Driver.debug(" loglevel = " + l_logLevel);
}
// Now make the initial connection // Now make the initial connection
try try
...@@ -174,6 +189,56 @@ public abstract class AbstractJdbc1Connection implements org.postgresql.PGConnec ...@@ -174,6 +189,56 @@ public abstract class AbstractJdbc1Connection implements org.postgresql.PGConnec
throw new PSQLException ("postgresql.con.failed", e); throw new PSQLException ("postgresql.con.failed", e);
} }
// Now we need to construct and send an ssl startup packet
try
{
if (useSSL) {
if (org.postgresql.Driver.logDebug)
org.postgresql.Driver.debug("Asking server if it supports ssl");
pg_stream.SendInteger(8,4);
pg_stream.SendInteger(80877103,4);
// now flush the ssl packets to the backend
pg_stream.flush();
// Now get the response from the backend, either an error message
// or an authentication request
int beresp = pg_stream.ReceiveChar();
if (org.postgresql.Driver.logDebug)
org.postgresql.Driver.debug("Server response was (S=Yes,N=No): "+(char)beresp);
switch (beresp)
{
case 'E':
// An error occured, so pass the error message to the
// user.
//
// The most common one to be thrown here is:
// "User authentication failed"
//
throw new PSQLException("postgresql.con.misc", pg_stream.ReceiveString(encoding));
case 'N':
// Server does not support ssl
throw new PSQLException("postgresql.con.sslnotsupported");
case 'S':
// Server supports ssl
if (org.postgresql.Driver.logDebug)
org.postgresql.Driver.debug("server does support ssl");
org.postgresql.Driver.makeSSL(pg_stream);
break;
default:
throw new PSQLException("postgresql.con.sslfail");
}
}
}
catch (IOException e)
{
throw new PSQLException("postgresql.con.failed", e);
}
// Now we need to construct and send a startup packet // Now we need to construct and send a startup packet
try try
{ {
......
...@@ -27,7 +27,7 @@ public class PSQLException extends SQLException ...@@ -27,7 +27,7 @@ public class PSQLException extends SQLException
*/ */
public PSQLException(String error, Object[] args) public PSQLException(String error, Object[] args)
{ {
//super(); super();
translate(error, args); translate(error, args);
} }
......
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