1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * See LICENSE.txt included in this distribution for the specific 9 * language governing permissions and limitations under the License. 10 * 11 * When distributing Covered Code, include this CDDL HEADER in each 12 * file and include the License file at LICENSE.txt. 13 * If applicable, add the following below this CDDL HEADER, with the 14 * fields enclosed by brackets "[]" replaced with your own identifying 15 * information: Portions Copyright [yyyy] [name of copyright owner] 16 * 17 * CDDL HEADER END 18 */ 19 20 /* 21 * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. 22 */ 23 package opengrok.auth.plugin.configuration; 24 25 import java.beans.ExceptionListener; 26 import java.beans.XMLDecoder; 27 import java.beans.XMLEncoder; 28 import java.io.ByteArrayInputStream; 29 import java.io.ByteArrayOutputStream; 30 import java.io.File; 31 import java.io.IOException; 32 import java.util.ArrayList; 33 import java.util.LinkedList; 34 import java.util.List; 35 36 import opengrok.auth.plugin.ldap.LdapServer; 37 import opengrok.auth.plugin.util.WebHook; 38 import opengrok.auth.plugin.util.WebHooks; 39 import org.junit.jupiter.api.Test; 40 import org.junit.jupiter.params.ParameterizedTest; 41 import org.junit.jupiter.params.provider.ValueSource; 42 43 import static org.junit.jupiter.api.Assertions.assertEquals; 44 import static org.junit.jupiter.api.Assertions.assertNotNull; 45 import static org.junit.jupiter.api.Assertions.assertThrows; 46 47 /** 48 * 49 * @author Krystof Tulinger 50 */ 51 class ConfigurationTest { 52 53 @Test testEncodeDecode()54 void testEncodeDecode() { 55 // Create an exception listener to detect errors while encoding and 56 // decoding 57 final LinkedList<Exception> exceptions = new LinkedList<>(); 58 ExceptionListener listener = exceptions::addLast; 59 60 ByteArrayOutputStream out = new ByteArrayOutputStream(); 61 XMLEncoder enc = new XMLEncoder(out); 62 enc.setExceptionListener(listener); 63 64 Configuration configuration1 = new Configuration(); 65 configuration1.setInterval(500); 66 configuration1.setSearchTimeout(1000); 67 configuration1.setConnectTimeout(42); 68 configuration1.setCountLimit(10); 69 configuration1.setServers(new ArrayList<>(List.of(new LdapServer("http://server.com")))); 70 WebHooks webHooks = new WebHooks(); 71 WebHook hook = new WebHook(); 72 hook.setContent("foo"); 73 hook.setURI("http://localhost:8080/source/api/v1/messages"); 74 webHooks.setFail(hook); 75 configuration1.setWebHooks(webHooks); 76 77 enc.writeObject(configuration1); 78 enc.close(); 79 80 // verify that the write didn't fail 81 if (!exceptions.isEmpty()) { 82 throw new AssertionError( "Got " + exceptions.size() + " exception(s)", exceptions.getFirst()); 83 } 84 85 ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); 86 XMLDecoder dec = new XMLDecoder(in, null, listener); 87 Configuration configuration2 = (Configuration) dec.readObject(); 88 assertNotNull(configuration2); 89 assertEquals(configuration1.getXMLRepresentationAsString(), 90 configuration2.getXMLRepresentationAsString()); 91 92 dec.close(); 93 // verify that the read didn't fail 94 if (!exceptions.isEmpty()) { 95 throw new AssertionError( "Got " + exceptions.size() + " exception(s)", exceptions.getFirst()); 96 } 97 } 98 99 @ParameterizedTest 100 @ValueSource(strings = { 101 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + 102 "<java version=\"11.0.8\" class=\"java.beans.XMLDecoder\">\n" + 103 " <object class=\"java.lang.Runtime\" method=\"getRuntime\">\n" + 104 " <void method=\"exec\">\n" + 105 " <array class=\"java.lang.String\" length=\"2\">\n" + 106 " <void index=\"0\">\n" + 107 " <string>/usr/bin/nc</string>\n" + 108 " </void>\n" + 109 " <void index=\"1\">\n" + 110 " <string>-l</string>\n" + 111 " </void>\n" + 112 " </array>\n" + 113 " </void>\n" + 114 " </object>\n" + 115 "</java>", 116 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + 117 "<java version=\"11.0.8\" class=\"java.beans.XMLDecoder\">\n" + 118 " <object class=\"java.lang.ProcessBuilder\">\n" + 119 " <array class=\"java.lang.String\" length=\"1\" >\n" + 120 " <void index=\"0\"> \n" + 121 " <string>/usr/bin/curl https://oracle.com</string>\n" + 122 " </void>\n" + 123 " </array>\n" + 124 " <void method=\"start\"/>\n" + 125 " </object>\n" + 126 "</java>", 127 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + 128 "<java version=\"11.0.8\" class=\"java.beans.XMLDecoder\">\n" + 129 " <object class = \"java.io.FileOutputStream\"> \n" + 130 " <string>opengrok_test.txt</string>\n" + 131 " <method name = \"write\">\n" + 132 " <array class=\"byte\" length=\"3\">\n" + 133 " <void index=\"0\"><byte>96</byte></void>\n" + 134 " <void index=\"1\"><byte>96</byte></void>\n" + 135 " <void index=\"2\"><byte>96</byte></void>\n" + 136 " </array>\n" + 137 " </method>\n" + 138 " <method name=\"close\"/>\n" + 139 " </object>\n" + 140 "</java>" 141 }) testDeserializationOfNotWhiteListedClassThrowsError(final String exploit)142 void testDeserializationOfNotWhiteListedClassThrowsError(final String exploit) { 143 assertThrows(IllegalAccessError.class, () -> Configuration.makeXMLStringAsConfiguration(exploit)); 144 } 145 146 @Test testReadCacheValid()147 void testReadCacheValid() throws IOException { 148 File testFile = new File(ConfigurationTest.class.getClassLoader(). 149 getResource("opengrok/auth/plugin/configuration/plugin-config.xml").getFile()); 150 Configuration config = Configuration.read(testFile); 151 assertNotNull(config); 152 assertEquals(2, config.getServers().size()); 153 } 154 } 155