Java Security Manager checkExec

У меня проблема с попыткой реализовать проверку безопасности в Java Security Manager.

Кажется, я неправильно понял назначение метода checkExec() в диспетчере безопасности. Я думал, что он будет вызван, когда мое приложение попытается вызвать другое Java-приложение через командную строку, но, похоже, этого не происходит.

Вот что я хочу сделать: вызывающее приложение, использующее мой собственный менеджер безопасности, выполняет "java SomeApp" в командной строке. Менеджер безопасности проверяет, все ли в порядке, и выполняет соответствующее действие.

Чтобы добиться этого, я сделал следующее:

1) Создан собственный менеджер безопасности, который переопределяет метод checkExec. Подпись метода - "public void checkExec (String cmd)".

2) Создан тестовый класс SecurityTest.

3) SecurityTest назначает моего собственного менеджера безопасности своим менеджером безопасности.

4) SecurityTest затем запускает "Java InvokeMe" в командной строке.

5) Пользовательский менеджер безопасности перехватывает это и что-то делает.

С 1 по 4 все в порядке, но 5 никогда не бывает. Я проверил, что мой пользовательский менеджер безопасности действителен, он успешно назначен SecurityTest, и SecurityTest успешно запускает InvokeMe. Однако, насколько я могу судить, метод checkExec() в моем собственном менеджере безопасности никогда не вызывается.

Куда я иду не так? Является ли вообще возможным то, что я пытаюсь сделать (сделать, чтобы менеджер безопасности что-то делал, когда приложение вызывает "java SomeApp")?

Спасибо за ваше время.

РЕДАКТИРОВАТЬ:

Вот некоторый код и вывод, полученный в результате выполнения теста. Это стиль быстрого прототипа, код стиля "проверь и очисти позже", так что он не будет красивым:

Пользовательский менеджер безопасности:

import java.util.*;
import java.io.*;
class DTESecurityManager extends SecurityManager {
    // instance variables

    DTESecurityManager() {
        super();
        //assign a bunch of variables
        System.out.println("TEST 1");
    }

    public void checkExec(String cmd) {
        if (cmd.toLowerCase().startsWith("java ")) {
            if (cmd.matches("(?i).*-djava.security.manager.*")) {
                throw new SecurityException("Cannot assign a security manager to invoked Java applications.");
            }
            StringBuffer intermediateCommand = new StringBuffer(cmd).insert(5, "-Djava.security.manager=DTESecurityManager ");
            String modifiedCommand = new String(intermediateCommand);
            try {
                Runtime rt = Runtime.getRuntime();
                Process pr = rt.exec(modifiedCommand);
            } catch (Exception e) {
                System.err.println("Error: " + e.getMessage());
            }
            try {
                FileWriter fstream = new FileWriter("Verification.txt");
                BufferedWriter out= new BufferedWriter(fstream);
                out.write("I worked.");
                out.close();
            } catch (Exception e) {
                System.err.println("Error: " + e.getMessage());
            }
            throw new SecurityException("Command was executed, but was modified to force invoked application to use this security manager.");
        }
    }
}

SecurityTest:

import java.io.*;

class SecurityTest {

    public static void main(String[] args) {
        try {
            System.setSecurityManager(new DTESecurityManager());
        } catch (Exception e) {
            System.out.println("Error: " + e.getMessage());
        }
        try {
            System.out.println("If we got this far, we had no problems setting our security manager.");
            System.out.println("Now let's try to invoke another Java application.");
            Runtime rt = Runtime.getRuntime();
            Process pr = rt.exec("java InvokeMe");
            System.out.println("I reached the end of my test without crashing. Now terminating.");
        } catch (Exception e) {
            System.out.println("Exception message: " + e.getMessage());
        }
    }

}

InvokeMe:

import java.io.*;

class InvokeMe {

    public static void main(String[] args) {
        System.out.println("I, InvokeMe, have been invoked successfully.");
        try {
        FileWriter fstream = new FileWriter("InvokeMeWasCalled.txt");
            BufferedWriter out= new BufferedWriter(fstream);
            out.write("It worked.");
            out.close();
        } catch (Exception e) {
            System.err.println("Error: " + e.getMessage());
        }
    }

}

Тестовый вывод:

TEST 1
If we got this far, we had no problems setting our security manager.
Now let's try to invoke another Java application.
I reached the end of my test without crashing. Now terminating.

Нет никаких признаков того, что вызывается checkExec() - нет вывода на консоль, и Verification.txt не существует нигде в моей файловой системе. (Конечно, я не уверен, что поведение подкласса менеджера безопасности должно быть при выполнении таких действий - возможно, это нормально. Если это так, мне нужен другой быстрый и грязный метод, чтобы проверить, Я бью определенные строки кода.) InvokeMeWasCalled.txt действительно существует, так что эта часть определенно работает.

2 ответа

Решение

Проблема в переопределении вашего менеджера по безопасности checkExec, cmd параметр передан checkExec содержит только первое "слово" в выполняемой команде, поэтому в вашей программе "java" является cmd параметр. В результате строка не начинается с "java ", а checkExec не выполняет блок if, что приводит к "чистой" проверке от менеджера безопасности.

public void checkExec(String cmd) {
    System.out.println(cmd); // prints "java"
    if (cmd.toLowerCase().startsWith("java ") { ... } // is false
    // no security exception is thrown, allowing your command
}

Также, как примечание, модифицированное выполнение команды приведет к StackruError потому что в метод передается только первое "слово".

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

Для начала, после вашего блока if должен быть метод else super.checkExec(), чтобы запустить обычную обработку, если мы не хотим делать что-то особенное. Это бы подхватило вашу проблему прямо здесь.

Другие вопросы по тегам