No this is not the way to do this. Elsewhere when the driver has
different functionality/requirements for JDBC1 vs JDBC2 this is
impelmented via subclassing (see the jdbc1 and jdbc2 packages). That
pattern should be followed here, not the kludgy fake ifdef support
provided by configure. Driver.java needs this as that determines which
Connection object is used, but from there on there shouldn't be any
other uses of .in files.
thanks,
--Barry
David Daney wrote:
> Sorry about that, things are never as easy as they seem. The answer
> appears to be to filter PG_Stream.java in a similar manner as is done to
> Driver.java
>
> Attached please find two files.
>
> 1) diffs for build.xml.
>
> 2) PG_Stream.java.in
>
> I hope this can now be put to bed.
>
> David Daney.
>
>
> Bruce Momjian wrote:
>
>>Patch reversed. Please advise how to continue.
>>
>>>Please pull this patch. It breaks JDBC1 support. The JDBC1 code no
>>>longer compiles, due to objects being referenced in this patch that do
>>>not exist in JDK1.1.
>>>
>>>thanks,
>>>--Barry
>>>
>>>
>>> [copy] Copying 1 file to
>>>/home/blind/temp/pgsql/src/interfaces/jdbc/org/postgresql
>>> [echo] Configured build for the JDBC1 edition driver
>>>
>>>compile:
>>> [javac] Compiling 38 source files to
>>>/home/blind/temp/pgsql/src/interfaces/jdbc/build
>>> [javac]
>>>/home/blind/temp/pgsql/src/interfaces/jdbc/org/postgresql/PG_Stream.java:33:
>>>Interface org.postgresql.PrivilegedExceptionAction of nested class
>>>org.postgresql.PG_Stream. PrivilegedSocket not found.
>>> [javac] implements PrivilegedExceptionAction
>>> [javac] ^
>>> [javac]
>>>/home/blind/temp/pgsql/src/interfaces/jdbc/org/postgresql/PG_Stream.java:63:
>>>Undefined variable or class name: AccessController
>>> [javac] co
>>>nnection = (Socket)AccessController.doPrivileged(ps);
>>> [javac] ^
>>> [javac]
>>>/home/blind/temp/pgsql/src/interfaces/jdbc/org/postgresql/PG_Stream.java:65:
>>>Class org.postgresql.PrivilegedActionException not found in type
>>>declaration.
>>> [javac] catch(PrivilegedActionException pae){
>>> [javac] ^
>>> [javac] 3 errors
>>>
>>>BUILD FAILED
>>>
>>>
>>>
>>>Bruce Momjian wrote:
>>>
>>>>Patch applied. Thanks.
>>>>
>>>>
>>>>>I am sorry to keep going back and forth on this, but:
>>>>>
>>>>>The original patch is correct and does the proper thing. I should have
>>>>>tested this before sounding the alarm.
>>>>>
>>>>>AccessController.doPrivileged()
>>>>>
>>>>>Propagates SecurityExceptions without wrapping them in a PrivilegedActionException so it appears that there is not the possibility of a ClassCastException.
>>>>>
>>>>>David Daney.
>>>>>
>>>>>
>>>>>Bruce Momjian wrote:
>>>>>
>>>>>
>>>>>>OK, patch removed from queue.
>>>>>>
>>>>>>
>>>>>>>It is now unclear to me the the
>>>>>>>
>>>>>>>catch(PrivilegedActionException pae)
>>>>>>>
>>>>>>>part of the patch is correct. If a SecurityException is thrown in
>>>>>>>Socket() (as might happen if the policy file did not give the proper
>>>>>>>permissions), then it might be converted into a ClassCastException,
>>>>>>>which is probably the wrong thing to do.
>>>>>>>
>>>>>>>Perhaps I should look into this a bit further.
>>>>>>>
>>>>>>>David Daney.
>>>>>>>
>>>>>>>
>>>>>>>Bruce Momjian wrote:
>>>>>>>
>>>>>>>
>>>>>>>>Your patch has been added to the PostgreSQL unapplied patches list at:
>>>>>>>>
>>>>>>>> http://candle.pha.pa.us/cgi-bin/pgpatches
>>>>>>>>
>>>>>>>>I will try to apply it within the next 48 hours.
>>>>>>>>
>>>>>>>>
>>>>>>>>>David Daney (David(dot)Daney(at)avtrex(dot)com) reports a bug with a severity of 3
>>>>>>>>>The lower the number the more severe it is.
>>>>>>>>>
>>>>>>>>>Short Description
>>>>>>>>>Another security issue with the JDBC driver.
>>>>>>>>>
>>>>>>>>>Long Description
>>>>>>>>>The JDBC driver requires
>>>>>>>>>
>>>>>>>>>permission java.net.SocketPermission "host:port", "connect";
>>>>>>>>>
>>>>>>>>>in the policy file of the application using the JDBC driver
>>>>>>>>>in the postgresql.jar file. Since the Socket() call in the
>>>>>>>>>driver is not protected by AccessController.doPrivileged() this
>>>>>>>>>permission must also be granted to the entire application.
>>>>>>>>>
>>>>>>>>>The attached diff fixes it so that the connect permission can be
>>>>>>>>>restricted just the the postgresql.jar codeBase if desired.
>>>>>>>>>
>>>>>>>>>Sample Code
>>>>>>>>>*** PG_Stream.java.orig Fri Aug 24 09:27:40 2001
>>>>>>>>>--- PG_Stream.java Fri Aug 24 09:42:14 2001
>>>>>>>>>***************
>>>>>>>>>*** 5,10 ****
>>>>>>>>>--- 5,11 ----
>>>>>>>>>imp
>>>>>>>>>ort java.net.*;
>>>>>>>>>import java.util.*;
>>>>>>>>>import java.sql.*;
>>>>>>>>>+ import java.security.*;
>>>>>>>>>import org.postgresql.*;
>>>>>>>>>import org.postgresql.core.*;
>>>>>>>>>import org.postgresql.util.*;
>>>>>>>>>***************
>>>>>>>>>*** 27,32 ****
>>>>>>>>>--- 28,52 ----
>>>>>>>>> BytePoolDim1 bytePoolDim1 = new BytePoolDim1();
>>>>>>>>> BytePoolDim2 bytePoolDim2 = new BytePoolDim2();
>>>>>>>>>
>>>>>>>>>+ private static class PrivilegedSocket
>>>>>>>>>+ implements PrivilegedExceptionAction
>>>>>>>>>+ {
>>>>>>>>>+ private String host;
>>>>>>>>>+ private int port;
>>>>>>>>>+
>>>>>>>>>+ PrivilegedSocket(String host, int port)
>>>>>>>>>+ {
>>>>>>>>>+ this.host = host;
>>>>>>>>>+ this.port = port;
>>>>>>>>>+ }
>>>>>>>>>+
>>>>>>>>>+ public Object run() throws Exception
>>>>>>>>>+ {
>>>>>>>>>+ return new Socket(host, port);
>>>>>>>>>+ }
>>>>>>>>>+ }
>>>>>>>>>+
>>>>>>>>>+
>>>>>>>>> /**
>>>>>>>>> * Constructor: Connect to the PostgreSQL back end and return
>>>>>>>>> * a stream connection.
>>>>>>>>>***************
>>>>>>>>>*** 37,43 ****
>>>>>>>>> */
>>>>>>>>> public PG_Stream(St
>>>>>>>>>ring host, int port) throws IOException
>>>>>>>>> {
>>>>>>>>>! connection = new Socket(host, port);
>>>>>>>>>
>>>>>>>>> // Submitted by Jason Venner <jason(at)idiom(dot)com> adds a 10x speed
>>>>>>>>> // improvement on FreeBSD machines (caused by a bug in their TCP Stack)
>>>>>>>>>--- 57,69 ----
>>>>>>>>> */
>>>>>>>>> public PG_Stream(String host, int port) throws IOException
>>>>>>>>> {
>>>>>>>>>! PrivilegedSocket ps = new PrivilegedSocket(host, port);
>>>>>>>>>! try {
>>>>>>>>>! connection = (Socket)AccessController.doPrivileged(ps);
>>>>>>>>>! }
>>>>>>>>>! catch(PrivilegedActionException pae){
>>>>>>>>>! throw (IOException)pae.getException();
>>>>>>>>>! }
>>>>>>>>>
>>>>>>>>> // Submitted by Jason Venner <jason(at)idiom(dot)com> adds a 10x speed
>>>>>>>>> // improvement on FreeBSD machines (caused by a bug in their TCP Stack)
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>No file was uploaded with this report
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>------------------
>>>>>>>>>---------(end of broadcast)---------------------------
>>>>>>>>>TIP 5: Have you checked our extensive FAQ?
>>>>>>>>>
>>>>>>>>>http://www.postgresql.org/users-lounge/docs/faq.html
>>>>>>>>>
>>>>>>>>>
>>>
>>>
>>>---------------------------(end of broadcast)---------------------------
>>>TIP 5: Have you checked our extensive FAQ?
>>>
>>>http://www.postgresql.org/users-lounge/docs/faq.html
>>>
>>
>
>
>
> ------------------------------------------------------------------------
>
> *** build.xml.orig Sun Mar 11 03:07:00 2001
> --- build.xml Mon Aug 27 10:10:04 2001
> ***************
> *** 44,49 ****
> --- 44,50 ----
>
> <!--
> This generates Driver.java from Driver.java.in
> + and PG_Stream.java from PG_Stream.java.in
> It's required for importing the driver version properties
> -->
> <target name="driver" depends="prepare,check_versions">
> ***************
> *** 63,68 ****
> --- 64,79 ----
> <available property="jdk13only" value="" classname="java.lang.StrictMath" />
> <filter token="JDK1.3ONLY" value="${jdk13only}" />
>
> + <!-- comment out java2 stuff -->
> + <property name="java2only" value="//" />
> + <available property="java2only" value="" classname="java.security.AccessController" />
> + <filter token="JAVA2ONLY" value="${java2only}" />
> +
> + <property name="java1only" value="" />
> + <available property="java1only" value="//" classname="java.security.AccessController" />
> + <filter token="JAVA1ONLY" value="${java1only}" />
> +
> +
> <!-- Some defaults -->
> <filter token="MAJORVERSION" value="${major}" />
> <filter token="MINORVERSION" value="${minor}" />
> ***************
> *** 72,82 ****
>
> <!-- Put a check for the current version here -->
>
> ! <!-- now copy and filter the file -->
> <copy file="${package}/Driver.java.in"
> tofile="${package}/Driver.java"
> filtering="yes" />
>
> <echo message="Configured build for the ${edition} edition driver." />
>
> </target>
> --- 83,97 ----
>
> <!-- Put a check for the current version here -->
>
> ! <!-- now copy and filter the files -->
> <copy file="${package}/Driver.java.in"
> tofile="${package}/Driver.java"
> filtering="yes" />
>
> + <copy file="${package}/PG_Stream.java.in"
> + tofile="${package}/PG_Stream.java"
> + filtering="yes" />
> +
> <echo message="Configured build for the ${edition} edition driver." />
>
> </target>
> ***************
> *** 86,91 ****
> --- 101,107 ----
> <delete dir="${dest}" />
> <delete dir="${jars}" />
> <delete file="${package}/Driver.java" />
> + <delete file="${package}/PG_Stream.java" />
> </target>
>
> <!-- Prepares the build directory -->
>
>
> ------------------------------------------------------------------------
>
> package org.postgresql;
>
> import java.io.*;
> import java.lang.*;
> import java.net.*;
> import java.util.*;
> import java.sql.*;
> @JAVA2ONLY(at)import java.security.*;
> import org.postgresql.*;
> import org.postgresql.core.*;
> import org.postgresql.util.*;
>
> /**
> * @version 1.0 15-APR-1997
> *
> * This class is used by Connection & PGlobj for communicating with the
> * backend.
> *
> * @see java.sql.Connection
> */
> // This class handles all the Streamed I/O for a org.postgresql connection
> public class PG_Stream
> {
> private Socket connection;
> private InputStream pg_input;
> private BufferedOutputStream pg_output;
>
> BytePoolDim1 bytePoolDim1 = new BytePoolDim1();
> BytePoolDim2 bytePoolDim2 = new BytePoolDim2();
>
> @JAVA2ONLY@ private static class PrivilegedSocket
> @JAVA2ONLY@ implements PrivilegedExceptionAction
> @JAVA2ONLY@ {
> @JAVA2ONLY@ private String host;
> @JAVA2ONLY@ private int port;
> @JAVA2ONLY@
> @JAVA2ONLY@ PrivilegedSocket(String host, int port)
> @JAVA2ONLY@ {
> @JAVA2ONLY@ this.host = host;
> @JAVA2ONLY@ this.port = port;
> @JAVA2ONLY@ }
> @JAVA2ONLY@
> @JAVA2ONLY@ public Object run() throws Exception
> @JAVA2ONLY@ {
> @JAVA2ONLY@ return new Socket(host, port);
> @JAVA2ONLY@ }
> @JAVA2ONLY@ }
>
>
> /**
> * Constructor: Connect to the PostgreSQL back end and return
> * a stream connection.
> *
> * @param host the hostname to connect to
> * @param port the port number that the postmaster is sitting on
> * @exception IOException if an IOException occurs below it.
> */
> public PG_Stream(String host, int port) throws IOException
> {
> @JAVA2ONLY@ PrivilegedSocket ps = new PrivilegedSocket(host, port);
> @JAVA2ONLY@ try {
> @JAVA2ONLY@ connection = (Socket)AccessController.doPrivileged(ps);
> @JAVA2ONLY@ }
> @JAVA2ONLY@ catch(PrivilegedActionException pae){
> @JAVA2ONLY@ throw (IOException)pae.getException();
> @JAVA2ONLY@ }
> @JAVA1ONLY@ connection = new Socket(host, port);
>
> // Submitted by Jason Venner <jason(at)idiom(dot)com> adds a 10x speed
> // improvement on FreeBSD machines (caused by a bug in their TCP Stack)
> connection.setTcpNoDelay(true);
>
> // Buffer sizes submitted by Sverre H Huseby <sverrehu(at)online(dot)no>
> pg_input = new BufferedInputStream(connection.getInputStream(), 8192);
> pg_output = new BufferedOutputStream(connection.getOutputStream(), 8192);
> }
>
> /**
> * Sends a single character to the back end
> *
> * @param val the character to be sent
> * @exception IOException if an I/O error occurs
> */
> public void SendChar(int val) throws IOException
> {
> // Original code
> //byte b[] = new byte[1];
> //b[0] = (byte)val;
> //pg_output.write(b);
>
> // Optimised version by Sverre H. Huseby Aug 22 1999 Applied Sep 13 1999
> pg_output.write((byte)val);
> }
>
> /**
> * Sends an integer to the back end
> *
> * @param val the integer to be sent
> * @param siz the length of the integer in bytes (size of structure)
> * @exception IOException if an I/O error occurs
> */
> public void SendInteger(int val, int siz) throws IOException
> {
> byte[] buf = bytePoolDim1.allocByte(siz);
>
> while (siz-- > 0)
> {
> buf[siz] = (byte)(val & 0xff);
> val >>= 8;
> }
> Send(buf);
> }
>
> /**
> * Sends an integer to the back end in reverse order.
> *
> * This is required when the backend uses the routines in the
> * src/backend/libpq/pqcomprim.c module.
> *
> * As time goes by, this should become obsolete.
> *
> * @param val the integer to be sent
> * @param siz the length of the integer in bytes (size of structure)
> * @exception IOException if an I/O error occurs
> */
> public void SendIntegerReverse(int val, int siz) throws IOException
> {
> byte[] buf = bytePoolDim1.allocByte(siz);
> int p=0;
> while (siz-- > 0)
> {
> buf[p++] = (byte)(val & 0xff);
> val >>= 8;
> }
> Send(buf);
> }
>
> /**
> * Send an array of bytes to the backend
> *
> * @param buf The array of bytes to be sent
> * @exception IOException if an I/O error occurs
> */
> public void Send(byte buf[]) throws IOException
> {
> pg_output.write(buf);
> }
>
> /**
> * Send an exact array of bytes to the backend - if the length
> * has not been reached, send nulls until it has.
> *
> * @param buf the array of bytes to be sent
> * @param siz the number of bytes to be sent
> * @exception IOException if an I/O error occurs
> */
> public void Send(byte buf[], int siz) throws IOException
> {
> Send(buf,0,siz);
> }
>
> /**
> * Send an exact array of bytes to the backend - if the length
> * has not been reached, send nulls until it has.
> *
> * @param buf the array of bytes to be sent
> * @param off offset in the array to start sending from
> * @param siz the number of bytes to be sent
> * @exception IOException if an I/O error occurs
> */
> public void Send(byte buf[], int off, int siz) throws IOException
> {
> int i;
>
> pg_output.write(buf, off, ((buf.length-off) < siz ? (buf.length-off) : siz));
> if((buf.length-off) < siz)
> {
> for (i = buf.length-off ; i < siz ; ++i)
> {
> pg_output.write(0);
> }
> }
> }
>
> /**
> * Sends a packet, prefixed with the packet's length
> * @param buf buffer to send
> * @exception SQLException if an I/O Error returns
> */
> public void SendPacket(byte[] buf) throws IOException
> {
> SendInteger(buf.length+4,4);
> Send(buf);
> }
>
> /**
> * Receives a single character from the backend
> *
> * @return the character received
> * @exception SQLException if an I/O Error returns
> */
> public int ReceiveChar() throws SQLException
> {
> int c = 0;
>
> try
> {
> c = pg_input.read();
> if (c < 0) throw new PSQLException("postgresql.stream.eof");
> } catch (IOException e) {
> throw new PSQLException("postgresql.stream.ioerror",e);
> }
> return c;
> }
>
> /**
> * Receives an integer from the backend
> *
> * @param siz length of the integer in bytes
> * @return the integer received from the backend
> * @exception SQLException if an I/O error occurs
> */
> public int ReceiveInteger(int siz) throws SQLException
> {
> int n = 0;
>
> try
> {
> for (int i = 0 ; i < siz ; i++)
> {
> int b = pg_input.read();
>
> if (b < 0)
> throw new PSQLException("postgresql.stream.eof");
> n = n | (b << (8 * i)) ;
> }
> } catch (IOException e) {
> throw new PSQLException("postgresql.stream.ioerror",e);
> }
> return n;
> }
>
> /**
> * Receives an integer from the backend
> *
> * @param siz length of the integer in bytes
> * @return the integer received from the backend
> * @exception SQLException if an I/O error occurs
> */
> public int ReceiveIntegerR(int siz) throws SQLException
> {
> int n = 0;
>
> try
> {
> for (int i = 0 ; i < siz ; i++)
> {
> int b = pg_input.read();
>
> if (b < 0)
> throw new PSQLException("postgresql.stream.eof");
> n = b | (n << 8);
> }
> } catch (IOException e) {
> throw new PSQLException("postgresql.stream.ioerror",e);
> }
> return n;
> }
>
> /**
> * Receives a null-terminated string from the backend. Maximum of
> * maxsiz bytes - if we don't see a null, then we assume something
> * has gone wrong.
> *
> * @param maxsiz maximum length of string
> * @return string from back end
> * @exception SQLException if an I/O error occurs
> */
> public String ReceiveString(int maxsiz) throws SQLException
> {
> byte[] rst = bytePoolDim1.allocByte(maxsiz);
> return ReceiveString(rst, maxsiz, null);
> }
>
> /**
> * Receives a null-terminated string from the backend. Maximum of
> * maxsiz bytes - if we don't see a null, then we assume something
> * has gone wrong.
> *
> * @param maxsiz maximum length of string
> * @param encoding the charset encoding to use.
> * @param maxsiz maximum length of string in bytes
> * @return string from back end
> * @exception SQLException if an I/O error occurs
> */
> public String ReceiveString(int maxsiz, String encoding) throws SQLException
> {
> byte[] rst = bytePoolDim1.allocByte(maxsiz);
> return ReceiveString(rst, maxsiz, encoding);
> }
>
> /**
> * Receives a null-terminated string from the backend. Maximum of
> * maxsiz bytes - if we don't see a null, then we assume something
> * has gone wrong.
> *
> * @param rst byte array to read the String into. rst.length must
> * equal to or greater than maxsize.
> * @param maxsiz maximum length of string in bytes
> * @param encoding the charset encoding to use.
> * @return string from back end
> * @exception SQLException if an I/O error occurs
> */
> public String ReceiveString(byte rst[], int maxsiz, String encoding)
> throws SQLException
> {
> int s = 0;
>
> try
> {
> while (s < maxsiz)
> {
> int c = pg_input.read();
> if (c < 0)
> throw new PSQLException("postgresql.stream.eof");
> else if (c == 0) {
> rst[s] = 0;
> break;
> } else
> rst[s++] = (byte)c;
> }
> if (s >= maxsiz)
> throw new PSQLException("postgresql.stream.toomuch");
> } catch (IOException e) {
> throw new PSQLException("postgresql.stream.ioerror",e);
> }
> String v = null;
> if (encoding == null)
> v = new String(rst, 0, s);
> else {
> try {
> v = new String(rst, 0, s, encoding);
> } catch (UnsupportedEncodingException unse) {
> throw new PSQLException("postgresql.stream.encoding", unse);
> }
> }
> return v;
> }
>
> /**
> * Read a tuple from the back end. A tuple is a two dimensional
> * array of bytes
> *
> * @param nf the number of fields expected
> * @param bin true if the tuple is a binary tuple
> * @return null if the current response has no more tuples, otherwise
> * an array of strings
> * @exception SQLException if a data I/O error occurs
> */
> public byte[][] ReceiveTuple(int nf, boolean bin) throws SQLException
> {
> int i, bim = (nf + 7)/8;
> byte[] bitmask = Receive(bim);
> byte[][] answer = bytePoolDim2.allocByte(nf);
>
> int whichbit = 0x80;
> int whichbyte = 0;
>
> for (i = 0 ; i < nf ; ++i)
> {
> boolean isNull = ((bitmask[whichbyte] & whichbit) == 0);
> whichbit >>= 1;
> if (whichbit == 0)
> {
> ++whichbyte;
> whichbit = 0x80;
> }
> if (isNull)
> answer[i] = null;
> else
> {
> int len = ReceiveIntegerR(4);
> if (!bin)
> len -= 4;
> if (len < 0)
> len = 0;
> answer[i] = Receive(len);
> }
> }
> return answer;
> }
>
> /**
> * Reads in a given number of bytes from the backend
> *
> * @param siz number of bytes to read
> * @return array of bytes received
> * @exception SQLException if a data I/O error occurs
> */
> private byte[] Receive(int siz) throws SQLException
> {
> byte[] answer = bytePoolDim1.allocByte(siz);
> Receive(answer,0,siz);
> return answer;
> }
>
> /**
> * Reads in a given number of bytes from the backend
> *
> * @param buf buffer to store result
> * @param off offset in buffer
> * @param siz number of bytes to read
> * @exception SQLException if a data I/O error occurs
> */
> public void Receive(byte[] b,int off,int siz) throws SQLException
> {
> int s = 0;
>
> try
> {
> while (s < siz)
> {
> int w = pg_input.read(b, off+s, siz - s);
> if (w < 0)
> throw new PSQLException("postgresql.stream.eof");
> s += w;
> }
> } catch (IOException e) {
> throw new PSQLException("postgresql.stream.ioerror",e);
> }
> }
>
> /**
> * This flushes any pending output to the backend. It is used primarily
> * by the Fastpath code.
> * @exception SQLException if an I/O error occurs
> */
> public void flush() throws SQLException
> {
> try {
> pg_output.flush();
> } catch (IOException e) {
> throw new PSQLException("postgresql.stream.flush",e);
> }
> }
>
> /**
> * Closes the connection
> *
> * @exception IOException if a IO Error occurs
> */
> public void close() throws IOException
> {
> pg_output.write("X\0".getBytes());
> pg_output.flush();
> pg_output.close();
> pg_input.close();
> connection.close();
> }
>
> }
>
>
> build.xml.diffs
>
> Content-Type:
>
> text/plain
> Content-Encoding:
>
> 7bit
>
>
> ------------------------------------------------------------------------
> PG_Stream.java.in
>
> Content-Type:
>
> text/plain
> Content-Encoding:
>
> 7bit
>
>