Есть ли способ для приложения Java получить права root?

17

При запуске Files.walk(Paths.get("/var/")).count() как непривилегированного пользователя выполнение может вызвать исключение, так как есть папки внутри /var/ , которым необходимо пройти разрешение root.

Я not ищет способ выполнить команду bash как root (например, sudo find /var ), используя Process и т. д.

Я просто хочу убедиться, что Files.walk(Paths.get("/var/")).count() не выбрасывает AccessDeniedException :

Exception in thread "restartedMain" java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0
    at sun.reflect.NativeMethodAccessorImpl.invoke
    at sun.reflect.DelegatingMethodAccessorImpl.invoke
    at java.lang.reflect.Method.invoke
    at org.springframework.boot.devtools.restart.RestartLauncher.run
Caused by: java.io.UncheckedIOException: java.nio.file.AccessDeniedException: /var/cache/httpd
    at java.nio.file.FileTreeIterator.fetchNextIfNeeded
    at java.nio.file.FileTreeIterator.hasNext
    at java.util.Iterator.forEachRemaining
    at java.util.Spliterators$IteratorSpliterator.forEachRemaining
    at java.util.stream.AbstractPipeline.copyInto
    at java.util.stream.AbstractPipeline.wrapAndCopyInto
    at java.util.stream.ReduceOps$ReduceOp.evaluateSequential
    at java.util.stream.AbstractPipeline.evaluate
    at java.util.stream.LongPipeline.reduce
    at java.util.stream.LongPipeline.sum
    at java.util.stream.ReferencePipeline.count
    at com.example.DemoApplication.main
    ... 5 more
Caused by: java.nio.file.AccessDeniedException: /var/cache/httpd
    at sun.nio.fs.UnixException.translateToIOException
    at sun.nio.fs.UnixException.rethrowAsIOException
    at sun.nio.fs.UnixException.rethrowAsIOException
    at sun.nio.fs.UnixFileSystemProvider.newDirectoryStream
    at java.nio.file.Files.newDirectoryStream
    at java.nio.file.FileTreeWalker.visit
    at java.nio.file.FileTreeWalker.next
    at java.nio.file.FileTreeIterator.fetchNextIfNeeded

Это просто пример. Используя filter(...) , можно обойти исключение. Но этот пример можно расширить и в других случаях использования.

Итак, возможно ли это вообще, для приложений CLI, JavaFX и т. д., чтобы получить права root после того, как они были выполнены из командной строки с помощью метода, например java -jar app.jar ?

    
задан Behrang 24.04.2016 в 21:42
источник
  • Если бы это было возможно, это было бы серьезной проблемой безопасности ... Представьте, что приложение получает доступ root и делает rm -rf /. OOOPS. –  Tunaki 24.04.2016 в 21:43
  • Приложение может открыть диалоговое окно и попросить пользователя ввести пароль sudo / root. У многих собственных приложений уже есть эта возможность. Например. Программное обеспечение Gnome, Дисковая утилита и т. Д. OOOPS. ;-) –  Behrang 24.04.2016 в 21:45
  • Правильный вопрос: «Как игнорировать места, где у меня нет доступа». –  Arkadiy 05.05.2016 в 22:54
  • Будьте честны и попросите выполнить sudo вашего приложения. Все пользователи Linux предпочтут такой подход –  Joaozito Polo 05.05.2016 в 23:00
  • Связано: stackoverflow.com/questions/2483755/... –  Kedar Mhaswade 06.05.2016 в 00:24
Показать остальные комментарии

3 ответа

9

Если то, что вы хотите, фактически пропускает пути, в которых у вас нет доступа, вы имеете два подхода:

Струйные

В ответе на этот вопрос он объясняется, как получить поток всех файлов поддерева, к которым вы можете получить доступ.

  

Но этот пример может быть расширен и в других случаях использования.

FileVisitor

Использование FileVisitor добавляет много кода, но при использовании дерева каталогов предоставляет вам большую гибкость. Чтобы решить ту же проблему, вы можете заменить Files.walk() на:

Files.walkFileTree(Path start, FileVisitor<? super Path> visitor);

расширение SimpleFileVisitor (для подсчета файлов) и переопределение некоторых методов.

Вы можете:

  1. Переопределите метод visitFileFailed , чтобы обработать дело, вы не можете получить доступ к файлу по некоторым причинам; (Совет Лукаша_Лланы)
  2. (необязательно) Переопределите метод preVisitDirectory , проверяя разрешения перед доступом к каталогу: если вы не можете получить к нему доступ, вы можете просто пропустить его поддерево (помните, что вы можете получить доступ к каталогу, но не все его файлы);

например. 1

@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) {
    // you can log the exception 'exc'
    return FileVisitResult.SKIP_SUBTREE;
}

например. 2

@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {

    if(!Files.isReadable(dir))
        return FileVisitResult.SKIP_SUBTREE;

    return FileVisitResult.CONTINUE;

}

Документы FileVisitor

Учебник FileVisitor

Надеюсь, что это поможет.

    
ответ дан Linuslabo 06.05.2016 в 12:05
  • Мое предложение - реализовать метод visitFileFailed из FileVisitor, который вызывается, когда файл не может быть посещен. Когда вы добавляете return FileVisitResult.SKIP_SUBTREE; к этому методу, тогда AccessDeniedException не будет выбрано. –  Lukasz_Plawny 06.05.2016 в 23:51
  • Вы правы! Я буду обновлять ответ как можно скорее. –  Linuslabo 07.05.2016 в 00:40
3

Всего несколько непроверенных идей:

1) Запустите приложение с привилегиями root, чтобы начать с:

sudo java -jar myapp.jar

2) Пусть ваше приложение запускает класс-пуск, который запрашивает права root, а затем продолжает работу с остальной частью вашего приложения:

java -jar myapp.jar

Это, в свою очередь, выполняет команду оболочки, но только xterm, которая запрашивает пароль root, а затем продолжает запускать java-программу с правами root:

xterm -e "sudo sh -c 'java -jar /tmp/myrootapp.jar'"

или, возможно, использовать что-то приятное, используя gksudo. Обратите внимание на ' и " .

Возможно, myapp.jar извлекает себя в временный каталог . myapp.jar содержит myrootapp.jar и, следовательно, может запускать его, как описано выше. /tmp , конечно, должно быть извлечено из java и предпочтительно быть каталогом со случайным именем, к которому имеет доступ только пользователь, на котором запущен myapp.jar , чтобы предотвратить вложение myrootapp.jar .

Кросс-платформенная

Вы упомянули /var/ самостоятельно, поэтому я предположил, что вы на каком-то Linux. Если предполагается, что он работает на межплатформенной платформе, например. на Macintosh или Microsoft Windows, вы должны сначала выполнить некоторую идентификацию системы. Затем вы можете применить StrategyPattern в коде, чтобы обрабатывать различные способы предоставления myrootapp.jar получения прав root или администратора.

    
ответ дан Stephan Henningsen 05.05.2016 в 23:32
  • Однако, в зависимости от вашего приложения, имейте в виду, что запуск вашего приложения с привилегиями root может привести к более опасным уязвимостям. Например, когда вы используете движок Rhino, существуют уязвимости в инъекциях, которые позволяют злоумышленнику вводить произвольный Java-код через движок. В этом случае, конечно, этот введенный код запускается с привилегиями root. –  Max 11.05.2016 в 10:04
2

Нет простого способа изменить разрешения. Java не подходит для этих задач. Есть только некоторые трюки, такие как проверка разрешений при запуске и попытка изменения разрешений через su / sudo, а затем перезапуск приложения или использование Java-gnome. Подробнее читайте здесь: Java: спросите права root на Ubuntu

    
ответ дан Vladislav Kysliy 08.05.2016 в 14:47