Joseph --
Nice detective work. The changes you made should be sufficient to
solve the problem you observed. However, I do not fully understand the
conditions that caused you to have the problem in the first place. I
have not seen this problem before. But I have a few hunches about the
cause.
Background: The reason AuthorizationManager.checkStaticPermission()
works the way that it does is to support the ability for JSPWiki
deployers to define JSPWiki security policies across the entire JVM in
a single policy. This is useful in those cases where more than one
JSPWiki instance is running (for example, where multiple JSPWiki
webapps are running in a web container).
As you have observed from the source of checkStaticPermission(), we
call AccessController.checkPermission() to check the "global" JVM
policy before we check the local jspwiki.policy. What actually happens
under the covers in the global case is that AccessController consults
the Java security policy configured for the JVM. By default, this is
JAVA_HOME/lib/security/java.policy. However, it can also be overridden
by setting the java.security.policy system property when the JRE is
first invoked. MOST web containers, including Tomcat, implement "Java
2 security" by setting -Djava.security.policy=someURL, and then
starting the SecurityManager (which enforces the policy) when they
start up. I believe WebSphere works this way too.
What you might not fully appreciate is that Java 2 security polices
are ALWAYS available, even if they are not always enforced by via the
JVM SecurityManager. In other words, when we call
AccessController.checkPermission, the JVM's security policy is still
being checked, even though the SecurityManager is not running. This
particular subtlety (you can perform policy checks without requiring a
SecurityManager) isn't obvious from a casual reading of the Java
security documentation, but nonetheless it does work.
Now, according to your tests, AccessController.checkPermission() is
ALWAYS allowing any permission that it's asked about. That can only
happen for one reason: something has told the JRE to use a security
policy that grants all privileges to everything via "grant
{ permission java.security.AllPermission; };" or something similar.
That something is almost certainly WebSphere.
In other words, your observation...
Since I don't have Java Security enabled on the JVM, the JVM-wide
policy will not deny ANY actions.
...is close, but not quite right.
It's more accurate to say that the JVM-wide policy is ALLOWING all
actions. That's not what the default java.policy does, so it's
probably due to a policy that WebSphere has configured. You can verify
this by checking JAVA_HOME/lib/security/java.policy. You'll see that
the generic grant{} block does not grant java.security.AllPermission.
But it does grant a few permissions, like java.util.PropertyPermission
"os.name", "read". (Indeed, this is exactly why we used it as a dummy
permission -- because it is always available, on all platforms and for
all grantees.)
---
Ok, so that should give you some clues about what is happening with
WebSphere. If you do any more digging about what/how WebShere installs
its default policy, I'd be curious to hear what you found.
But the real question, prompted by your particular issue, is "do we
need JVM-wide security policies any more?" I am not sure that we do,
but I'd like to hear from the rest of the devs about this. Local
security policies (implemented by LocalPolicy in 2.6) mostly
eliminated the need to worry about JVM-wide policies for ~90% of
deployers. If we did get rid of JVM-wide security policies, we'd
probably want to do it in 3.0, rather than in 2.8.
Regards,
Andrew
On Dec 1, 2008, at 6:37 PM, Hobbs, Joseph wrote:
I dug into this a bit deeper and think I finally got it working.
Again
I don't know the implications of making these changes overall,
though I
did run into 1 issue I had to work around :-). Feedback on these
changes would be appreciated. If they make sense, I would be happy to
submit them through JIRA.
The first thing I did was comment out the policy check within
AuthorizationManager.checkStaticPermissions(). So
checkStaticPermissions() looked something like this:
if( !m_useJAAS ) return true;
Boolean allowed = (Boolean)WikiSession.doPrivileged( session, new
PrivilegedAction()
{
public Object run()
{
// We're not going to check the JVM-wide policy at all...
/*
try
{
// Check the JVM-wide security policy first
AccessController.checkPermission( permission );
return Boolean.TRUE;
}
catch( AccessControlException e )
{
// Global policy denied the permission
}
*/
// Try the local policy - check each Role/Group and User
Principal
if ( allowedByLocalPolicy( session.getRoles(), permission )
||
allowedByLocalPolicy( session.getPrincipals(),
permission ) )
{
return Boolean.TRUE;
}
return Boolean.FALSE;
}
} );
return allowed.booleanValue();
When I commented this out, testing showed that the local policy was
being applied as expected. With that said, I ran into an issue when
attempting to view my profile. Inspection of the logs showed this
entry:
2008-12-01 17:40:36,874 [WebContainer : 1] INFO
com.ecyrd.jspwiki.WikiContext JSPWiki:/et/ops/UserPreferences.jsp
JSPWiki:https://myhost/et/ops/UserPreferences.jsp - User testAuthor
has
no access - forbidden (permission=(java.util.PropertyPermission
os.name
read))
This struck me as odd that we'd be testing for a PropertyPermission
for
reading os.name. Digging through the source a bit more I came up with
the reasoning. Since we're assuming os.name will always be readable,
it's being used as the dummy permissions check by
WikiContext.requiredPermission(). Since I took the JVM policy out of
the loop, this check won't be allowed! Oops!
To get around this issue, I actually created a DummyPermission
class. I
then updated WikiContext.DUMMY_PERMISSION to point to it instead of
using PropertyPermission(os.name, read).
private static final Permission DUMMY_PERMISSION = new
DummyPermission("dummy");
After that, I updated checkStaticPermission() again and added the
following check ABOVE the existing Local Policy checks.
// Is this a DummyPermission? if so, return TRUE!
if ( permission instanceof DummyPermission )
{
return Boolean.TRUE;
}
After doing this, the wiki started working as expected. I still have
testing to do so I can make sure I didn't break anything else, but the
results look promising so far.
Joseph Hobbs
Email : [EMAIL PROTECTED]
-----Original Message-----
From: Hobbs, Joseph
Sent: Monday, December 01, 2008 3:56 PM
To: 'JSPWiki-dev ([email protected])'
Subject: jspwiki.policy and java.policy
Hi All! New to the list, but not to JSPWiki. I've been using it
internally for a few years, and just recently started digging into it
deeper. Good stuff! I did run into one issue that confused me, and I
was curious to get some else's take on it.
I'm running IBM's WebSphere Application Server 6.1.0.15 running on AIX
5.3 and JSPWiki 2.6.4. WebSphere is using an LDAP Registry and I also
have RSA's Cleartrust for Single Sign On configured within WebSphere.
I've been successful in getting everything working (even SSO) with
JSPWiki through Container Managed security. I was able to do all of
this through modification of some XML (web.xml) and
jspwiki.properties.
One note... I do NOT have Java 2 security enabled (this is critical
for
later).
The issue I've run into relates to JSPWiki and how it handles
jspwiki.policy. Even though I've defined roles and the container is
providing them, I'm still an admin. No matter what I do, I've got
full
privileges. I can do anything an admin does, even though I don't have
the privileges per jspwiki.policy. Page ACL's don't seem to apply
either.
After digging into the issue, I discovered that JSPWiki wasn't even
checking the policies defined within the jspwiki.policy file.
Com
.ecyrd.jspwiki.auth.AuthorizationManager.checkStaticPermission(WikiSe
ssion,Permission) checks the JVM-wide security policy first, and only
checks the local policy if the JVM-wide policy denies the action.
Since
I don't have Java Security enabled on the JVM, the JVM-wide policy
will
not deny ANY actions.
So, all that leads me to my question. Don't take this as a dig or
challenge. I've learned in my life that while I can't think of
reasons,
there are plenty out there. Just trying to understand the reasoning.
This is especially true for me currently, as I'm still learning the
JSPWiki codebase and don't have a great deal of background with java
policies! Sooo....
Question: Why does the JVM-wide policy apply at this point? If
JSPWiki
is loading its own jspwiki.policy file, should we be deferring to the
JVM-wide policy at all? That policy should be governing what my
application can do to the system/etc, not what my users can do within
the application. Will anything obvious break if I 'eliminate' the JVM
policy check from AuthorizationManager?
On a side note... I've tried enabling Java Security and was able to
verify that the policies were being processed as expected. With that
said, it's caused me some other pain that I'm still working through
(mainly around the SSO component). I'm not looking for a quick fix
here. I'm just curious as to why JVM-wide is even taken into
account if
JSPWiki is loading a local policy separate.
I appreciate your time, as well as any responses! Thank you and
have a
good holiday!
Joseph Hobbs
Email : [EMAIL PROTECTED]
This e-mail transmission contains information that is confidential
and may be privileged. It is intended only for the addressee(s)
named above. If you receive this e-mail in error, please do not
read, copy or disseminate it in any manner. If you are not the
intended recipient, any disclosure, copying, distribution or use of
the contents of this information is prohibited. Please reply to the
message immediately by informing the sender that the message was
misdirected. After replying, please erase it from your computer
system. Your assistance in correcting this error is appreciated.