|
63 | 63 | import java.nio.file.FileVisitResult; |
64 | 64 | import java.nio.file.Files; |
65 | 65 | import java.nio.file.Path; |
| 66 | +import java.nio.file.Paths; |
66 | 67 | import java.nio.file.SimpleFileVisitor; |
67 | 68 | import java.nio.file.StandardCopyOption; |
68 | 69 | import java.nio.file.attribute.BasicFileAttributes; |
@@ -329,10 +330,31 @@ private Path download(InstallablePlugin plugin, Path tmpDir) throws Exception { |
329 | 330 | } |
330 | 331 | throw new UserException(ExitCodes.USAGE, msg); |
331 | 332 | } |
| 333 | + |
| 334 | + verifyLocationNotInPluginsDirectory(pluginLocation); |
| 335 | + |
332 | 336 | terminal.println(logPrefix + "Downloading " + URLDecoder.decode(pluginLocation, StandardCharsets.UTF_8)); |
333 | 337 | return downloadZip(pluginLocation, tmpDir); |
334 | 338 | } |
335 | 339 |
|
| 340 | + @SuppressForbidden(reason = "Need to use Paths#get") |
| 341 | + private void verifyLocationNotInPluginsDirectory(String pluginLocation) throws URISyntaxException, IOException, UserException { |
| 342 | + if (pluginLocation == null) { |
| 343 | + return; |
| 344 | + } |
| 345 | + URI uri = new URI(pluginLocation); |
| 346 | + if ("file".equalsIgnoreCase(uri.getScheme())) { |
| 347 | + Path pluginRealPath = Paths.get(uri).toRealPath(); |
| 348 | + Path pluginsDirectory = env.pluginsDir().toRealPath(); |
| 349 | + if (pluginRealPath.startsWith(pluginsDirectory)) { |
| 350 | + throw new UserException( |
| 351 | + ExitCodes.USAGE, |
| 352 | + "Installation of plugin in location [" + pluginLocation + "] from inside the plugins directory is not permitted." |
| 353 | + ); |
| 354 | + } |
| 355 | + } |
| 356 | + } |
| 357 | + |
336 | 358 | @SuppressForbidden(reason = "Need to use PathUtils#get") |
337 | 359 | private Path getPluginArchivePath(String pluginId, String pluginArchiveDir) throws UserException { |
338 | 360 | final Path path = PathUtils.get(pluginArchiveDir); |
@@ -462,9 +484,9 @@ private static List<String> checkMisspelledPlugin(String pluginId) { |
462 | 484 | /** Downloads a zip from the url, into a temp file under the given temp dir. */ |
463 | 485 | // pkg private for tests |
464 | 486 | @SuppressForbidden(reason = "We use getInputStream to download plugins") |
465 | | - Path downloadZip(String urlString, Path tmpDir) throws IOException { |
| 487 | + Path downloadZip(String urlString, Path tmpDir) throws IOException, URISyntaxException { |
466 | 488 | terminal.println(VERBOSE, "Retrieving zip from " + urlString); |
467 | | - URL url = new URL(urlString); |
| 489 | + URL url = new URI(urlString).toURL(); |
468 | 490 | Path zip = Files.createTempFile(tmpDir, null, ".zip"); |
469 | 491 | URLConnection urlConnection = this.proxy == null ? url.openConnection() : url.openConnection(this.proxy); |
470 | 492 | urlConnection.addRequestProperty("User-Agent", "elasticsearch-plugin-installer"); |
@@ -548,9 +570,10 @@ private InputStream urlOpenStream(final URL url) throws IOException { |
548 | 570 | * @throws IOException if an I/O exception occurs download or reading files and resources |
549 | 571 | * @throws PGPException if an exception occurs verifying the downloaded ZIP signature |
550 | 572 | * @throws UserException if checksum validation fails |
| 573 | + * @throws URISyntaxException is the url is invalid |
551 | 574 | */ |
552 | 575 | private Path downloadAndValidate(final String urlString, final Path tmpDir, final boolean officialPlugin) throws IOException, |
553 | | - PGPException, UserException { |
| 576 | + PGPException, UserException, URISyntaxException { |
554 | 577 | Path zip = downloadZip(urlString, tmpDir); |
555 | 578 | pathsToDeleteOnShutdown.add(zip); |
556 | 579 | String checksumUrlString = urlString + ".sha512"; |
|
0 commit comments