You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

SecurityManagerTest.java 5.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /*
  2. * Copyright (C) 2019 Nail Samatov <sanail@yandex.ru> and others
  3. *
  4. * This program and the accompanying materials are made available under the
  5. * terms of the Eclipse Distribution License v. 1.0 which is available at
  6. * https://www.eclipse.org/org/documents/edl-v10.php.
  7. *
  8. * SPDX-License-Identifier: BSD-3-Clause
  9. */
  10. package org.eclipse.jgit.api;
  11. import static org.junit.Assert.assertEquals;
  12. import static org.junit.Assert.assertNotNull;
  13. import static org.junit.Assert.assertTrue;
  14. import java.io.File;
  15. import java.io.FilePermission;
  16. import java.io.IOException;
  17. import java.lang.reflect.ReflectPermission;
  18. import java.nio.file.Files;
  19. import java.security.Permission;
  20. import java.security.SecurityPermission;
  21. import java.util.ArrayList;
  22. import java.util.List;
  23. import java.util.PropertyPermission;
  24. import java.util.logging.LoggingPermission;
  25. import javax.security.auth.AuthPermission;
  26. import org.eclipse.jgit.api.errors.GitAPIException;
  27. import org.eclipse.jgit.junit.JGitTestUtil;
  28. import org.eclipse.jgit.junit.MockSystemReader;
  29. import org.eclipse.jgit.junit.SeparateClassloaderTestRunner;
  30. import org.eclipse.jgit.revwalk.RevCommit;
  31. import org.eclipse.jgit.treewalk.TreeWalk;
  32. import org.eclipse.jgit.util.FileUtils;
  33. import org.eclipse.jgit.util.SystemReader;
  34. import org.junit.After;
  35. import org.junit.Before;
  36. import org.junit.Test;
  37. import org.junit.runner.RunWith;
  38. /**
  39. * <p>
  40. * Tests if jgit works if SecurityManager is enabled.
  41. * </p>
  42. *
  43. * <p>
  44. * Note: JGit's classes shouldn't be used before SecurityManager is configured.
  45. * If you use some JGit's class before SecurityManager is replaced then part of
  46. * the code can be invoked outside of our custom SecurityManager and this test
  47. * becomes useless.
  48. * </p>
  49. *
  50. * <p>
  51. * For example the class {@link org.eclipse.jgit.util.FS} is used widely in jgit
  52. * sources. It contains DETECTED static field. At the first usage of the class
  53. * FS the field DETECTED is initialized and during initialization many system
  54. * operations that SecurityManager can forbid are invoked.
  55. * </p>
  56. *
  57. * <p>
  58. * For this reason this test doesn't extend LocalDiskRepositoryTestCase (it uses
  59. * JGit's classes in setUp() method) and other JGit's utility classes. It's done
  60. * to affect SecurityManager as less as possible.
  61. * </p>
  62. *
  63. * <p>
  64. * We use SeparateClassloaderTestRunner to isolate FS.DETECTED field
  65. * initialization between different tests run.
  66. * </p>
  67. */
  68. @RunWith(SeparateClassloaderTestRunner.class)
  69. public class SecurityManagerTest {
  70. private File root;
  71. private SecurityManager originalSecurityManager;
  72. private List<Permission> permissions = new ArrayList<>();
  73. @Before
  74. public void setUp() throws Exception {
  75. // Create working directory
  76. SystemReader.setInstance(new MockSystemReader());
  77. root = Files.createTempDirectory("jgit-security").toFile();
  78. // Add system permissions
  79. permissions.add(new RuntimePermission("*"));
  80. permissions.add(new SecurityPermission("*"));
  81. permissions.add(new AuthPermission("*"));
  82. permissions.add(new ReflectPermission("*"));
  83. permissions.add(new PropertyPermission("*", "read,write"));
  84. permissions.add(new LoggingPermission("control", null));
  85. permissions.add(new FilePermission(
  86. System.getProperty("java.home") + "/-", "read"));
  87. String tempDir = System.getProperty("java.io.tmpdir");
  88. permissions.add(new FilePermission(tempDir, "read,write,delete"));
  89. permissions
  90. .add(new FilePermission(tempDir + "/-", "read,write,delete"));
  91. // Add permissions to dependent jar files.
  92. String classPath = System.getProperty("java.class.path");
  93. if (classPath != null) {
  94. for (String path : classPath.split(File.pathSeparator)) {
  95. permissions.add(new FilePermission(path, "read"));
  96. }
  97. }
  98. // Add permissions to jgit class files.
  99. String jgitSourcesRoot = new File(System.getProperty("user.dir"))
  100. .getParent();
  101. permissions.add(new FilePermission(jgitSourcesRoot + "/-", "read"));
  102. // Add permissions to working dir for jgit. Our git repositories will be
  103. // initialized and cloned here.
  104. permissions.add(new FilePermission(root.getPath() + "/-",
  105. "read,write,delete,execute"));
  106. // Replace Security Manager
  107. originalSecurityManager = System.getSecurityManager();
  108. System.setSecurityManager(new SecurityManager() {
  109. @Override
  110. public void checkPermission(Permission requested) {
  111. for (Permission permission : permissions) {
  112. if (permission.implies(requested)) {
  113. return;
  114. }
  115. }
  116. super.checkPermission(requested);
  117. }
  118. });
  119. }
  120. @After
  121. public void tearDown() throws Exception {
  122. System.setSecurityManager(originalSecurityManager);
  123. // Note: don't use this method before security manager is replaced in
  124. // setUp() method. The method uses FS.DETECTED internally and can affect
  125. // the test.
  126. FileUtils.delete(root, FileUtils.RECURSIVE | FileUtils.RETRY);
  127. }
  128. @Test
  129. public void testInitAndClone() throws IOException, GitAPIException {
  130. File remote = new File(root, "remote");
  131. File local = new File(root, "local");
  132. try (Git git = Git.init().setDirectory(remote).call()) {
  133. JGitTestUtil.write(new File(remote, "hello.txt"), "Hello world!");
  134. git.add().addFilepattern(".").call();
  135. git.commit().setMessage("Initial commit").call();
  136. }
  137. try (Git git = Git.cloneRepository().setURI(remote.toURI().toString())
  138. .setDirectory(local).call()) {
  139. assertTrue(new File(local, ".git").exists());
  140. JGitTestUtil.write(new File(local, "hi.txt"), "Hi!");
  141. git.add().addFilepattern(".").call();
  142. RevCommit commit1 = git.commit().setMessage("Commit on local repo")
  143. .call();
  144. assertEquals("Commit on local repo", commit1.getFullMessage());
  145. assertNotNull(TreeWalk.forPath(git.getRepository(), "hello.txt",
  146. commit1.getTree()));
  147. }
  148. }
  149. }