Dan Creswell wrote:
So...
On 23 December 2011 11:32, Peter Firmstone <j...@zeus.net.au> wrote:
Hmmm, scratches beard, ok, you're right, up for some brainstorming?
1. If I reimplement SocketPermission, what sort of behaviour do we need?
2. Or a faster DNS provider? www.xbill.org/dnsjava -
*sun.net.spi.nameservice.provider.1=dns,dnsjava*
Well, I'm always going to lean towards fixing the root cause of the
problem which IMHO is DNS and its usage/performance in JDK. Which
means that a faster or at least smarter provider will be where I'd
want to go. JDK's default cache approach is kinda busted in any case.
A faster provider will help, and we can bundle dnsjava if we want,
unfortunately though DNS lookup is oversubscribed in Sun's jdk, so we
need to eliminate the sources of overuse also.
I was able to successfully replace URL with URI in
PreferredClassProvider and in CodeSource.implies(CodeSource cs) with
URLGrant.implies(URI grant, URI implied), this avoids DNS lookup completely.
With regard to a SocketPermissionCollection, if you have a number of
domain name granted SocketPermission's, that aren't wildcards, each one
will cause an unnecessary DNS lookup, until a suitable match is found.
Even domain names that are obviously different are resolved, in case
they share an identical ip address. Even identical domain addresses are
resolved, to see if their IP addresses match. If one has a IP address
and the other a domain name, SocketPermission.implies will perform a dns
lookup to get the missing IP address and then a reverse dns lookup to
obtain the other domain name, if the IP addresses don't match.
A reimplementation of SocketPermission would allow the
SocketPermissionCollection to take responsibility for DNS lookup after
it checks every SocketPermission for a direct match without DNS:
wildcards, IP address etc. Make the domain name implies a separate
check that's performed after all wildcards and IP addresses.
A Comparator is good for ensuring the Permission object's are sorted into an
efficient order before creating a PermissionCollection. The Comparator
isn't much good for a cache that contains a previously checked Permission,
since equals will be executed (I don't currently cache SocketPermission for
this reason). Collection.contains(Permission p)?
Collection.contains will surely use equals()?
In externally sorted Collections, yes, but not in TreeSet, so that's an
option, thanks ;) Pays to read the docs properly.
With a SecurityManager and our own PolicyFile implementation, it is possible
to replace / substitute SocketPermission, from both ends, but both the
policy and SM must be in place or it won't work. PolicyFile must be
Smells like we're heading towards part of a standard platform. A
security manager and policy generally need to be available to support
downloadable code so I don't see this being an issue?
Yep, got that smell about it.
instantiated early, or we risk having static ProtectionDomain's that still
contain java.net.SocketPermission. ConcurrentPermissions, a replacement for
Permissions that ProtectionDomain's use to hold static Permissions could
also be used to convert any stray SocketPermission objects.
One question I've asked myself when creating my own policy implementation
was CodeSource.implies(CodeSource cs), the implementation seemed like a bad
idea, it uses DNS, an attacker could use DNS cache poisoning to gain
elevated permission using an untrusted CodeSource URL, simply because the
policy thinks the CodeSource is implied. I changed PolicyFile to
specifically not use CodeSource.implies(). In reality a signer Certificate
is required to identify the CodeSource with any level of trust.
Well, I think a more general point here would be that JDK's default
set of behaviours are designed to "protect" against DNS based attacks
(i.e. a successful lookup result is cached forever and so changes
can't leak in). This is bogus, because if the first lookup is
compromised you're dead and buried.
The correct solution (and more practical these days) is to properly
secure your DNS.
Which brings me to a general statement in respect of DNS security - do
it in that system, don't attempt to compensate in the application. Any
firm that generally cares about security will have done this
already....
Then there's the internet, where DNS can't be trusted. The current root
key certificate system in DNS-SEC could also be compromised at some
point in the future. Certificate authorities are proving that they
can't be trusted.
The only system that appears to be resistant is OpenPGP's model, a web
of trust, with certificate revocation.
Now a IPv4 address can be converted to an IPv6, so IP addresses could be
converted to IPv6 format and compared. Host names could be compared using
string comparison. But without DNS an IP address couldn't equal a domain
name and a domain name couldn't be resolved to imply an IP address.
The intended purpose of SocketPermission is to check if a user and or code
is allowed to connect, listen, etc to a network address. How can we trust
the DNS to give the right information?
See above, DNS can give you the wrong information because it's
mis-configured, this isn't just a security problem.
How do we know the DNS has resolved a domain name correctly?
You don't unless it's secured and you're confident spoofing options
are eliminated (which means you'd need to be sure physical network
compromise for example is reasonably addressed).
The most logical way to identify the remote end, would be via a connection
that requires it to authenticate. We have that now with secure JERI.
And secure JERI handshakes are horribly slow (to be fair the
underlying protocols produce that performance envelope).
Hmm, sounds like a future opportunity, I wonder if elliptical curve
cryptography could help.
SocketPermission only makes a decision whether to allow a connection or not,
that's it.
Without DNS, the policy admin would have to enter SocketPermission grants
for domain names and IP addresses (manual duplication), so it seems DNS is
there for convenience.
DNS is, and always has been, a convenience - admins back in the day
wanted something that would provide the equivalent of /etc/hosts
across large numbers of machines for low effort.
Using RemotePolicy for a djinn group, we could have an administrator node,
resolve all current domain names (and reverse lookup IP addresses) in the
djinn policy file and update all group member nodes with duplicated
SocketPermission's for IP address and domain name forms. Then none of the
nodes would need to perform DNS resolution. Again that requires our own
SocketPermission implementation.
Meh, I can't believe that's more performant than having each box doing
direct DNS resolution for itself....
If you only need to update your RemotePolicy occasionally and you can
resolve all addresses off line prior to performing a policy update, then
DNS isn't required in the middle of a SecurityCheck in progress...
Background pre-processed, rather than on demand, so to speak.
RemotePolicy doesn't make policy decisions, it's a method of
transferring Policy Permission grant's. So while a policy update is in
progress, security checks may continue unheeded, the switch is made at
the last moment, once all information has been transferred and cached
locally. Perhaps I should rename it? DjinnGroupPolicy? You limit the
Permission's the Djinn Group administrator can grant using
GrantPermission. Although there is a one is to one relationship between
RemotePolicy and Group. RemotePolicy isn't completely implemented.
If DNS is reduced to the absolute minimum, perhaps it could be
preprocessed locally too. Once we start performing security checks, we
need to be decisive.
I'd welcome a helping hand ;)
Merry Christmas & Cheers,
Peter.
Cheers,
Peter.
Dan Creswell wrote:
IMHO, workarounds like this are asking for trouble. You're assuming
certain rational actions (a decent toString) on behalf of some other
programmer in the presence of evidence that says they aren't rational
- i.e. they have a poor equals and/or a poor hashCode implementation.
Combine that with putting the mechanism "under the covers" and I feel
that's a nasty piece of dark magic brewing that'll give us problems
later.
An explicit workaround option is supported in typical collections via
a Comparator, yes, that means others have to write some code but it
also means the troubles they're facing with equals and hashCode are
"in your face".
Happy Christmas,
Dan.
On 23 December 2011 02:06, Peter Firmstone <j...@zeus.net.au> wrote:
There's another way around poorly written equals() and hashCode()
implementations.
In my reference collection utilities, I have strong, weak and soft
references, there are variations on these based on identity or equality.
Well, I've just thought of another that might help out when poor equals
implementations exist:
toString()?
first check both objects have the same class, then compare the results of
toString(), and use toString().hashCode() for hashCode's.
I could call this String equality, when toString isn't overridden it
prints
the reference address so this is compatible with identity based equality
also.
This would fix all those nasty equals implementations for use in
collections
without requiring any work on the developers part.
Cheers,
Peter.
Peter wrote:
SocketPermissionCollection adds SocketPermission at the head of its
internal list. This change was made in jdk 1.2.2_005 bug 4301064
related
to reverse dns lookup delays for applets.
This indicates that the tail of the last policy file parsed, is added
last
to the policy and hence at the head of that List.
It's also worth noting that the standard policy provider included with
the jvm is in force until the preferred policy provider is completely
initiated, after reading all policy files. So it's likely that the
standard
java policy is read last by our policy provider implementation.
In summary a list of SocketPermissions need to be sorted beginning from
those that cause long dns delays, to wildcard based permissions, so the
wildcard perms are added last and hence checked first by any implies
calls.
I've got two options on how to solve this:
1. Get rid of PermissionCollection based caches altogether and generate
PermissionCollection's on demand.
2 Replace the PermissionCollection cache with a List<Permission> based
cache, generate Permissioncollection's on demand. Sort the List after
creation, before publishing, replace the list on write.
Option 2 could be implemented in ConcurrentPermissions, a replacement
for
java.security.Permissions.
Option 1 would be implemented by the policy.
In addition, to allow the security manager to cache the results of
permission checks for SocketPermission, I can create a wrapper class,
where
equals and hashcode are based purely on the string representation. This
allows very rapid repeated permission checks.
Looks like I can get around the SocketPermission, CodeSource and URL
headaches, relatively unscathed.
N.B. Anyone care to try out, or seriously performance test the new
PreferredClassProvider?
Cheers,
Peter.
----- Original message -----
Actually, more significantly for me is that the default localhost
SocketPermission is checked before a more lenient SocketPermission. In
theory,
one should be able to introspect SocketPermission instances and
determine
that
one may be automatically implied by the other so can be skipped,
possibly
saving
a lookup. Chris
Peter Firmstone wrote:
A big problem with the current implementation is SocketPermission
blocks
other permission checks from proceeding.