Java SecurityManager - how to ensure a method is run only by another method?

Java SecurityManager - how to ensure a method is run only by another method?



I want B to be run only by the private method A#getSensitiveData() that uses or does some processing on sensitive data (example: cryptographic keys, national id, whatever).


private


A#getSensitiveData()


public final class A
private transient final B sensitiveHolder; //set at Constructor
public A(B sensitiveHolder)
this.sensitiveHolder = sensitiveHolder;

private final byte getSensitiveData()
return sensitiveHolder.getSensitiveData();



public final class B
private transient final byte sensitiveData;//encrypt and set at Constructor
public final byte getSensitiveData()
//check if it is run by A#getSensitiveData(); if it is, decrypt by DEK and give plaintext.




Please take into account that the code would be obfuscated, so please refrain from putting in any package names as String.


String



What must I write with SecurityManager#checkPrivilege() and AccessController.doPrivileged() before I can achieve such an effect?


SecurityManager#checkPrivilege()


AccessController.doPrivileged()



EDIT: Obviously this is different because the so called "answer" does not contain any CODE. WORKING CODE is worth infinitely more than "oh, just do this and that".





For a working answer with code that solves the question of how B.getSensitiveData can check and limit who is calling it, see stackoverflow.com/a/41420960/14955 It does not use a SecurityManager, though.
– Thilo
May 19 at 1:30


B.getSensitiveData




2 Answers
2



You could do something like this:


private boolean verify(final StackTraceElement e)
boolean doNext = false;
for (final StackTraceElement s : e)
if (doNext && s.getClassName().equals("A") && s.getMethodName().equals("getSensitiveData"))
return true;
doNext = s.getMethodName().equals("getStackTrace");

return false;



And to call the method:


public final byte getSensitiveData(StackTraceElement e)
if (verify(e))
// Do something good




In your A class call your B class like this:


A


B


return sensitiveHolder.getSensitiveData(Thread.currentThread().getStackTrace());



I don't know if this is what you need or it is near that. You could play around the values in the equals section of the if. I got and modified the example from this site.


equals


if



If you're able to use JDK 9+, which introduces StackWalker, this sort of thing might work for you. This technique seems to supersede use of sun.reflect.Reflection#getCallerClass(int). (I hope you weren't counting on a SecurityManager-related answer.)


StackWalker


sun.reflect.Reflection#getCallerClass(int)


package asdf;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import java.util.EnumSet;
import java.util.List;
import java.util.stream.Collectors;

public class Asdf

@Test
public void what()
get();


void get()
StackWalker.StackFrame stackFrame =
StackWalker.getInstance(EnumSet.of(StackWalker.Option.RETAIN_CLASS_REFERENCE))
.walk(stream ->
List<StackWalker.StackFrame> stackFrames = stream.collect(Collectors.toList());
return stackFrames.get(1);
);
Assertions.assertEquals(Asdf.class, stackFrame.getDeclaringClass());
Assertions.assertEquals("what", stackFrame.getMethodName());
Assertions.assertEquals(0, stackFrame.getMethodType().parameterCount());

// now do caller-sensitive stuff







By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)