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,15 +67,17 @@ public class Driver implements java.sql.Driver ...@@ -66,15 +67,17 @@ 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.
* loglevel - (optional) Enable logging of messages from the driver. * This value is only used when connecting to a 7.2 or older server.
* The value is an integer from 1 to 2 where: * loglevel - (optional) Enable logging of messages from the driver.
* INFO = 1, DEBUG = 2 * The value is an integer from 1 to 2 where:
* The output is sent to DriverManager.getPrintWriter() if set, * INFO = 1, DEBUG = 2
* otherwise it is sent to System.out. * The output is sent to DriverManager.getPrintWriter() if set,
* otherwise it is sent to System.out.
* compatible - (optional) This is used to toggle * compatible - (optional) This is used to toggle
* between different functionality as it changes across different releases * between different functionality as it changes across different releases
* of the jdbc driver code. The values here are versions of the jdbc * of the jdbc driver code. The values here are versions of the jdbc
...@@ -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("&") ) //parse the args part of the url
state = -3; StringTokenizer qst = new StringTokenizer(l_urlArgs, "&");
else if (token.equals("=")) for (int count = 0; (qst.hasMoreTokens()); count++)
state = -5; {
} String token = qst.nextToken();
else if (state <= -2 && (count % 2) == 0) int l_pos = token.indexOf('=');
{ if (l_pos == -1) {
if (state == -3) urlProps.put(token, "");
key = token; } else {
else if (state == -5) urlProps.put(token.substring(0,l_pos), token.substring(l_pos+1));
{
value = token;
urlProps.put(key, value);
state = -2;
}
}
} }
} }
...@@ -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;
...@@ -100,7 +101,7 @@ public abstract class AbstractJdbc1Connection implements org.postgresql.PGConnec ...@@ -100,7 +101,7 @@ public abstract class AbstractJdbc1Connection implements org.postgresql.PGConnec
* @exception SQLException if a database access error occurs * @exception SQLException if a database access error occurs
*/ */
public void openConnection(String host, int port, Properties info, String database, String url, org.postgresql.Driver d) throws SQLException public void openConnection(String host, int port, Properties info, String database, String url, org.postgresql.Driver d) throws SQLException
{ {
firstWarning = null; firstWarning = null;
// Throw an exception if the user or password properties are missing // Throw an exception if the user or password properties are missing
...@@ -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