On 09/14/2012 02:32 PM, Tomas Lestach wrote:
[...]
> 
> Hi Johannes,
> 
> the patch look good.
> 
> However looking at [1] I see the code is licensed under the Apache License, 
> Version 2.0. I'm afraid this version isn't compatible with the Spacewalk's 
> GPLv2.
> Or is it? Cliff?

I reworked the code again and also simplified the regex, so I guess it could
be fine now? Attached is another version of the patch.

Regards,
Johannes

-- 
SUSE LINUX Products GmbH, HRB 16746 (AG Nürnberg)
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer
>From ebd7f06c7332a44974b95f51146e59a527356f29 Mon Sep 17 00:00:00 2001
From: Johannes Renner <jren...@suse.de>
Date: Tue, 18 Sep 2012 14:17:11 +0200
Subject: [PATCH] Validate proxy format on general config page

---
 .../rhn/common/validator/HostPortValidator.java    |  134 ++++++++++++++++++++
 .../validator/test/HostPortValidatorTest.java      |   63 +++++++++
 .../action/satellite/GeneralConfigAction.java      |   12 +-
 .../frontend/strings/java/StringResource_en_US.xml |    8 ++
 4 files changed, 216 insertions(+), 1 deletion(-)
 create mode 100644 java/code/src/com/redhat/rhn/common/validator/HostPortValidator.java
 create mode 100644 java/code/src/com/redhat/rhn/common/validator/test/HostPortValidatorTest.java

diff --git a/java/code/src/com/redhat/rhn/common/validator/HostPortValidator.java b/java/code/src/com/redhat/rhn/common/validator/HostPortValidator.java
new file mode 100644
index 0000000..cff8ad7
--- /dev/null
+++ b/java/code/src/com/redhat/rhn/common/validator/HostPortValidator.java
@@ -0,0 +1,134 @@
+/**
+ * Copyright (c) 2012 Novell
+ *
+ * This software is licensed to you under the GNU General Public License,
+ * version 2 (GPLv2). There is NO WARRANTY for this software, express or
+ * implied, including the implied warranties of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
+ * along with this software; if not, see
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * Red Hat trademarks are not licensed under GPLv2. No permission is
+ * granted to use or replicate Red Hat trademarks that are incorporated
+ * in this software or its documentation.
+ */
+package com.redhat.rhn.common.validator;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Input validation for host[:port], where the host part can be either an IP address
+ * (IPv4 or IPv6) or a hostname.
+ */
+public class HostPortValidator {
+
+    // Singleton instance
+    private static HostPortValidator instance;
+
+    // Pattern to match IPv6 address in bracket notation
+    private static final Pattern IPV6_BRACKETS = Pattern.compile("^\\[(.*)\\](:(\\d*))?$");
+
+    // Private constructor
+    private HostPortValidator() {
+    }
+
+    /**
+     * Return the singleton instance of {@link HostPortValidator}.
+     * @return {@link HostPortValidator} instance
+     */
+    public static HostPortValidator getInstance() {
+        if (instance == null) {
+            instance = new HostPortValidator();
+        }
+        return instance;
+    }
+
+    /**
+     * Return true if the given string is a valid host[:port] representation.
+     * @param hostPort
+     * @return true if hostPort represents a valid host and port, else false.
+     */
+    public boolean isValid(String hostPort) {
+        if (hostPort == null || hostPort.isEmpty()) {
+            return false;
+        }
+        String host;
+        String port;
+
+        if (hostPort.startsWith("[")) {
+          // Parse an IPv6 address in bracket notation
+          Matcher matcher = IPV6_BRACKETS.matcher(hostPort);
+          if (!matcher.matches()) {
+              return false;
+          }
+          host = matcher.group(1);
+          port = matcher.group(3);
+        }
+        else {
+          int colonIndex = hostPort.indexOf(':');
+          if (colonIndex != -1 && colonIndex == hostPort.lastIndexOf(':')) {
+            // Split into host:port
+            host = hostPort.substring(0, colonIndex);
+            port = hostPort.substring(colonIndex + 1);
+          }
+          else {
+            host = hostPort;
+            port = null;
+          }
+        }
+
+        // Validate host and port separately
+        boolean isValidHost = true;
+        // Validate IP addresses externally (v4 and v6)
+        if (host.replaceAll("[\\d\\.]", "").isEmpty() || host.contains(":")) {
+            isValidHost = isValidIP(host);
+        }
+        boolean isValidPort = true;
+        if (port != null) {
+            isValidPort = isValidPort(port);
+        }
+
+        return isValidHost && isValidPort;
+    }
+
+    /**
+     * Validate IP address format for a given string.
+     * @param ipString
+     * @return true if the given string is a valid IP, else false.
+     */
+    private boolean isValidIP(String ipString) {
+        boolean ret = false;
+        if (ipString != null && !ipString.isEmpty()) {
+            try {
+                InetAddress.getByName(ipString);
+                ret = true;
+            }
+            catch (UnknownHostException e) {
+                // Stay silent
+            }
+        }
+        return ret;
+    }
+
+    /**
+     * Parse a port number from a given string and validate it.
+     * @param portString
+     * @return true if the given string is a valid port, else false.
+     */
+    private boolean isValidPort(String portString) {
+        boolean ret = false;
+        if (portString != null && !portString.isEmpty()) {
+            try {
+                int port = Integer.parseInt(portString);
+                ret = port >= 0 && port < 65535;
+            }
+            catch (NumberFormatException e) {
+                // Stay silent
+            }
+        }
+        return ret;
+    }
+}
diff --git a/java/code/src/com/redhat/rhn/common/validator/test/HostPortValidatorTest.java b/java/code/src/com/redhat/rhn/common/validator/test/HostPortValidatorTest.java
new file mode 100644
index 0000000..e96bd91
--- /dev/null
+++ b/java/code/src/com/redhat/rhn/common/validator/test/HostPortValidatorTest.java
@@ -0,0 +1,63 @@
+/**
+ * Copyright (c) 2012 Novell
+ *
+ * This software is licensed to you under the GNU General Public License,
+ * version 2 (GPLv2). There is NO WARRANTY for this software, express or
+ * implied, including the implied warranties of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
+ * along with this software; if not, see
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * Red Hat trademarks are not licensed under GPLv2. No permission is
+ * granted to use or replicate Red Hat trademarks that are incorporated
+ * in this software or its documentation.
+ */
+package com.redhat.rhn.common.validator.test;
+
+import com.redhat.rhn.common.validator.HostPortValidator;
+
+import junit.framework.TestCase;
+
+/**
+ * Test class for the {@link HostPortValidator}.
+ */
+public class HostPortValidatorTest extends TestCase {
+
+    public void testIPv4() {
+        assertTrue(HostPortValidator.getInstance().isValid("192.168.1.2"));
+        assertTrue(HostPortValidator.getInstance().isValid("192.168.1.2:8888"));
+        assertTrue(HostPortValidator.getInstance().isValid("192.168.1"));
+
+        assertFalse(HostPortValidator.getInstance().isValid("192.168.1.2:"));
+        assertFalse(HostPortValidator.getInstance().isValid("192.168.1.2.3"));
+        assertFalse(HostPortValidator.getInstance().isValid("1200.5.4.3"));
+        assertFalse(HostPortValidator.getInstance().isValid("192.168.2.1:888888"));
+        assertFalse(HostPortValidator.getInstance().isValid("http://192.168.2.1:8888";));
+    }
+
+    public void testIPv6() {
+        assertTrue(HostPortValidator.getInstance().isValid("2001:0db8:85a3:08d3:1319:8a2e:0370:7344"));
+        assertTrue(HostPortValidator.getInstance().isValid("[2001:0db8:85a3:08d3:1319:8a2e:0370:7344]"));
+        assertTrue(HostPortValidator.getInstance().isValid("[2001:0db8:85a3:08d3:1319:8a2e:0370:7344]:8888"));
+        assertTrue(HostPortValidator.getInstance().isValid("[2607:f0d0:1002:51::4]:8888"));
+        assertTrue(HostPortValidator.getInstance().isValid("[::1]"));
+        assertTrue(HostPortValidator.getInstance().isValid("[::1]:8888"));
+
+        assertFalse(HostPortValidator.getInstance().isValid("2001:0db8:85a3:08d3:1319:8a2e:0370:7344:8888"));
+        assertFalse(HostPortValidator.getInstance().isValid("[2001:0db8:85a3:08d3:1319:8a2e:0370:7344]]:8888"));
+        assertFalse(HostPortValidator.getInstance().isValid("[2001:0db8:85a3:08d3:1319:8a2e:0370:7344:8888"));
+        assertFalse(HostPortValidator.getInstance().isValid("2001:0db8:85a3:08d3:1319:8a2e:0370:7344]:8888"));
+        assertFalse(HostPortValidator.getInstance().isValid("[::1]:"));
+        assertFalse(HostPortValidator.getInstance().isValid("[]"));
+    }
+
+    public void testHostnames() {
+        assertTrue(HostPortValidator.getInstance().isValid("myproxy"));
+        assertTrue(HostPortValidator.getInstance().isValid("myproxy:8888"));
+        assertTrue(HostPortValidator.getInstance().isValid("proxy.example.com"));
+        assertTrue(HostPortValidator.getInstance().isValid("proxy.example.com:8888"));
+
+        assertFalse(HostPortValidator.getInstance().isValid("http://proxy.example.com";));
+        assertFalse(HostPortValidator.getInstance().isValid("http://proxy.example.com:8888";));
+    }
+}
diff --git a/java/code/src/com/redhat/rhn/frontend/action/satellite/GeneralConfigAction.java b/java/code/src/com/redhat/rhn/frontend/action/satellite/GeneralConfigAction.java
index 257d296..5514537 100644
--- a/java/code/src/com/redhat/rhn/frontend/action/satellite/GeneralConfigAction.java
+++ b/java/code/src/com/redhat/rhn/frontend/action/satellite/GeneralConfigAction.java
@@ -16,6 +16,7 @@ package com.redhat.rhn.frontend.action.satellite;
 
 import com.redhat.rhn.common.conf.Config;
 import com.redhat.rhn.common.conf.ConfigDefaults;
+import com.redhat.rhn.common.validator.HostPortValidator;
 import com.redhat.rhn.common.validator.ValidatorError;
 import com.redhat.rhn.domain.user.User;
 import com.redhat.rhn.frontend.struts.RequestContext;
@@ -212,7 +213,16 @@ public class GeneralConfigAction extends BaseConfigAction {
      */
     private ActionErrors validateForm(DynaActionForm form) {
         ActionErrors errors = new ActionErrors();
-        String email = (String) form.get(translateFormPropertyName("traceback_mail"));
+
+        // Check if proxy is given as host:port
+        String proxy = (String) form.get(
+                translateFormPropertyName("server.satellite.http_proxy"));
+        HostPortValidator validator = HostPortValidator.getInstance();
+        if (!(proxy.equals("") || validator.isValid(proxy))) {
+            errors.add(ActionMessages.GLOBAL_MESSAGE,
+                    new ActionMessage("error.proxy_invalid"));
+        }
+
         String password = (String) form.get(
                    translateFormPropertyName("server.satellite.http_proxy_password"));
         String confirmationPassword = (String) form.get(
diff --git a/java/code/src/com/redhat/rhn/frontend/strings/java/StringResource_en_US.xml b/java/code/src/com/redhat/rhn/frontend/strings/java/StringResource_en_US.xml
index 86e3bd7..507e32d 100644
--- a/java/code/src/com/redhat/rhn/frontend/strings/java/StringResource_en_US.xml
+++ b/java/code/src/com/redhat/rhn/frontend/strings/java/StringResource_en_US.xml
@@ -1179,6 +1179,14 @@ http://www.oasis-open.org/committees/xliff/documents/xliff-core-1.1.xsd";
           <context context-type="sourcefile">com.redhat.rhn.frontend.action.monitoring.notification.AbstractFilterEditAction</context>
         </context-group>
       </trans-unit>
+
+      <trans-unit id="error.proxy_invalid">
+<source>HTTP proxy needs to be specified as host:port.</source>
+        <context-group name="ctx">
+          <context context-type="sourcefile">/rhn/admin/config/GeneralConfig</context>
+        </context-group>
+      </trans-unit>
+
       <trans-unit id="/rhn/">
 <source>That username is already taken; please choose another.</source>
         <context-group name="ctx">
-- 
1.7.10.4

_______________________________________________
Spacewalk-devel mailing list
Spacewalk-devel@redhat.com
https://www.redhat.com/mailman/listinfo/spacewalk-devel

Reply via email to