From f4d0ed69c0b3aae8531d83d6af4c57f22312c813 Mon Sep 17 00:00:00 2001
From: Vladimir Sitnikov <sitnikov.vladimir@gmail.com>
Date: Tue, 1 Feb 2022 15:27:13 +0300
Subject: [PATCH] Merge pull request from GHSA-v7wg-cpwc-24m4

This ensures arbitrary classes can't be passed instead of
AuthenticationPlugin, SocketFactory, SSLSocketFactory, CallbackHandler, HostnameVerifier
---
 .../postgresql/core/SocketFactoryFactory.java |   4 +-
 .../core/v3/AuthenticationPluginManager.java  |  10 +-
 .../java/org/postgresql/ssl/LibPQFactory.java |   2 +-
 .../main/java/org/postgresql/ssl/MakeSSL.java |   2 +-
 .../org/postgresql/util/ObjectFactory.java    |   7 +-
 .../test/util/ObjectFactoryTest.java          | 106 ++++++++++++++++++
 6 files changed, 120 insertions(+), 11 deletions(-)
 create mode 100644 pgjdbc/src/test/java/org/postgresql/test/util/ObjectFactoryTest.java

Index: src/postgresql-jdbc-42.2-10.src/pgjdbc/src/main/java/org/postgresql/core/SocketFactoryFactory.java
===================================================================
--- src.orig/postgresql-jdbc-42.2-10.src/pgjdbc/src/main/java/org/postgresql/core/SocketFactoryFactory.java
+++ src/postgresql-jdbc-42.2-10.src/pgjdbc/src/main/java/org/postgresql/core/SocketFactoryFactory.java
@@ -36,7 +36,7 @@ public class SocketFactoryFactory {
       return SocketFactory.getDefault();
     }
     try {
-      return (SocketFactory) ObjectFactory.instantiate(socketFactoryClassName, info, true,
+      return ObjectFactory.instantiate(SocketFactory.class, socketFactoryClassName, info, true,
           PGProperty.SOCKET_FACTORY_ARG.get(info));
     } catch (Exception e) {
       throw new PSQLException(
@@ -61,7 +61,7 @@ public class SocketFactoryFactory {
       return new LibPQFactory(info);
     }
     try {
-      return (SSLSocketFactory) ObjectFactory.instantiate(classname, info, true,
+      return ObjectFactory.instantiate(SSLSocketFactory.class, classname, info, true,
           PGProperty.SSL_FACTORY_ARG.get(info));
     } catch (Exception e) {
       throw new PSQLException(
Index: src/postgresql-jdbc-42.2-10.src/pgjdbc/src/main/java/org/postgresql/ssl/LibPQFactory.java
===================================================================
--- src.orig/postgresql-jdbc-42.2-10.src/pgjdbc/src/main/java/org/postgresql/ssl/LibPQFactory.java
+++ src/postgresql-jdbc-42.2-10.src/pgjdbc/src/main/java/org/postgresql/ssl/LibPQFactory.java
@@ -49,7 +49,7 @@ public class LibPQFactory extends Wrappe
     String sslpasswordcallback = PGProperty.SSL_PASSWORD_CALLBACK.get(info);
     if (sslpasswordcallback != null) {
       try {
-        cbh = (CallbackHandler) ObjectFactory.instantiate(sslpasswordcallback, info, false, null);
+        cbh = ObjectFactory.instantiate(CallbackHandler.class, sslpasswordcallback, info, false, null);
       } catch (Exception e) {
         throw new PSQLException(
           GT.tr("The password callback class provided {0} could not be instantiated.",
Index: src/postgresql-jdbc-42.2-10.src/pgjdbc/src/main/java/org/postgresql/ssl/MakeSSL.java
===================================================================
--- src.orig/postgresql-jdbc-42.2-10.src/pgjdbc/src/main/java/org/postgresql/ssl/MakeSSL.java
+++ src/postgresql-jdbc-42.2-10.src/pgjdbc/src/main/java/org/postgresql/ssl/MakeSSL.java
@@ -64,7 +64,7 @@ public class MakeSSL extends ObjectFacto
       sslhostnameverifier = "PgjdbcHostnameVerifier";
     } else {
       try {
-        hvn = (HostnameVerifier) instantiate(sslhostnameverifier, info, false, null);
+        hvn = instantiate(HostnameVerifier.class, sslhostnameverifier, info, false, null);
       } catch (Exception e) {
         throw new PSQLException(
             GT.tr("The HostnameVerifier class provided {0} could not be instantiated.",
Index: src/postgresql-jdbc-42.2-10.src/pgjdbc/src/main/java/org/postgresql/util/ObjectFactory.java
===================================================================
--- src.orig/postgresql-jdbc-42.2-10.src/pgjdbc/src/main/java/org/postgresql/util/ObjectFactory.java
+++ src/postgresql-jdbc-42.2-10.src/pgjdbc/src/main/java/org/postgresql/util/ObjectFactory.java
@@ -34,13 +34,14 @@ public class ObjectFactory {
    * @throws IllegalAccessException if something goes wrong
    * @throws InvocationTargetException if something goes wrong
    */
-  public static Object instantiate(String classname, Properties info, boolean tryString,
+  public static <T> T instantiate(Class<T> expectedClass, String classname, Properties info,
+      boolean tryString,
       String stringarg) throws ClassNotFoundException, SecurityException, NoSuchMethodException,
           IllegalArgumentException, InstantiationException, IllegalAccessException,
           InvocationTargetException {
     Object[] args = {info};
-    Constructor<?> ctor = null;
-    Class<?> cls = Class.forName(classname);
+    Constructor<? extends T> ctor = null;
+    Class<? extends T> cls = Class.forName(classname).asSubclass(expectedClass);
     try {
       ctor = cls.getConstructor(Properties.class);
     } catch (NoSuchMethodException nsme) {
