Skip to content

Commit

Permalink
[SECURITY-1641]
Browse files Browse the repository at this point in the history
  • Loading branch information
Wadeck committed Jan 14, 2020
1 parent c0d3c04 commit cd28a6d
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 2 deletions.
2 changes: 1 addition & 1 deletion core/src/main/java/hudson/DNSMultiCast.java
Original file line number Diff line number Diff line change
Expand Up @@ -88,5 +88,5 @@ public void close() {

private static final Logger LOGGER = Logger.getLogger(DNSMultiCast.class.getName());

public static boolean disabled = SystemProperties.getBoolean(DNSMultiCast.class.getName()+".disabled");
public static boolean disabled = SystemProperties.getBoolean(DNSMultiCast.class.getName()+".disabled", true);
}
3 changes: 2 additions & 1 deletion core/src/main/java/hudson/UDPBroadcastThread.java
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@ public void shutdown() {
interrupt();
}

public static final int PORT = SystemProperties.getInteger("hudson.udp",33848);
// The previous default port was 33848, before the "disabled by default" change
public static final int PORT = SystemProperties.getInteger("hudson.udp", -1);

private static final Logger LOGGER = Logger.getLogger(UDPBroadcastThread.class.getName());

Expand Down
29 changes: 29 additions & 0 deletions test/src/test/java/hudson/UDPBroadcastThreadSEC1641Test.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package hudson;

import jenkins.model.Jenkins;
import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.JenkinsRule;

import java.lang.reflect.Field;

import static org.junit.Assert.assertNull;

public class UDPBroadcastThreadSEC1641Test {

@Rule
public JenkinsRule j = new JenkinsRule();

@Test
public void ensureThereIsNoThreadRunningByDefault() throws Exception {
UDPBroadcastThread thread = getPrivateThread(j.jenkins);
assertNull(thread);
}

private static UDPBroadcastThread getPrivateThread(Jenkins jenkins) throws Exception {
Field threadField = Jenkins.class.getDeclaredField("udpBroadcastThread");
threadField.setAccessible(true);

return (UDPBroadcastThread) threadField.get(jenkins);
}
}
57 changes: 57 additions & 0 deletions test/src/test/java/hudson/UDPBroadcastThreadTest.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
package hudson;

import jenkins.model.Jenkins;
import org.hamcrest.Matchers;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.net.DatagramSocket;
import java.net.DatagramPacket;
import java.net.InetAddress;
Expand All @@ -17,18 +23,40 @@
import org.junit.Test;
import org.jvnet.hudson.test.JenkinsRule;

import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

/**
* @author Kohsuke Kawaguchi
*/
public class UDPBroadcastThreadTest {

@Rule public JenkinsRule j = new JenkinsRule();

@BeforeClass
public static void forceActivateUDPMulticast() throws Exception {
// required to be done before JenkinsRule starts the Jenkins instance
// as the usage of this port is in the constructor
updatePort(33848);
}

private static void updatePort(int newValue) throws Exception {
Field portField = UDPBroadcastThread.class.getField("PORT");

Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(portField, portField.getModifiers() & ~Modifier.FINAL);

portField.setInt(null, newValue);
}

/**
* Old unicast based clients should still be able to receive some reply,
* as we haven't changed the port.
*/
@Test public void legacy() throws Exception {
updatePort(33848);
DatagramSocket s = new DatagramSocket();
sendQueryTo(s, InetAddress.getLocalHost());
s.setSoTimeout(15000); // to prevent test hang
Expand Down Expand Up @@ -60,18 +88,38 @@ public class UDPBroadcastThreadTest {

// we should at least get two replies since we run two broadcasts
try {
// from first (Jenkins one) (order does not matter)
receiveAndVerify(s);
// from second
receiveAndVerify(s);
// from third
receiveAndVerify(s);
} catch (SocketTimeoutException x) {
Assume.assumeFalse(UDPBroadcastThread.udpHandlingProblem);
throw x;
}

// to fail fast
s.setSoTimeout(2000);
try {
receiveAndVerify(s);
fail("There should be only 3 listeners");
} catch (SocketTimeoutException x) {
// expected to throw
}
} finally {
third.interrupt();
second.interrupt();
}
}

@Test
public void ensureTheThreadIsRunningWithSysProp() throws Exception {
UDPBroadcastThread thread = getPrivateThread(j.jenkins);
assertNotNull(thread);
assertTrue(thread.isAlive());
}

private void sendQueryTo(DatagramSocket s, InetAddress dest) throws IOException {
DatagramPacket p = new DatagramPacket(new byte[1024],1024);
p.setAddress(dest);
Expand All @@ -86,11 +134,20 @@ private void receiveAndVerify(DatagramSocket s) throws IOException, SAXException
DatagramPacket p = new DatagramPacket(new byte[1024],1024);
s.receive(p);
String xml = new String(p.getData(), 0, p.getLength(), "UTF-8");
//example: <hudson><version>2.164.4-SNAPSHOT</version><url>http://localhost:23146/jenkins/</url><server-id>be6757793486931ff50c259b66c77704</server-id><slave-port>23149</slave-port></hudson>
System.out.println(xml);
Assert.assertThat(xml, Matchers.containsString("<hudson>"));

// make sure at least this XML parses
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setNamespaceAware(true);
spf.newSAXParser().parse(new InputSource(new StringReader(xml)),new DefaultHandler());
}

private static UDPBroadcastThread getPrivateThread(Jenkins jenkins) throws Exception {
Field threadField = Jenkins.class.getDeclaredField("udpBroadcastThread");
threadField.setAccessible(true);

return (UDPBroadcastThread) threadField.get(jenkins);
}
}

0 comments on commit cd28a6d

Please # to comment.