On 24 December 2011 11:04, Peter Firmstone <j...@zeus.net.au> wrote: > 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 don't think that holds necessarily if DNS lookup is good enough. > > 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. > Then you run your own DNS, and detach it from external factors.... > 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... That's just a hosts file and DNS disabled.... And you'd rsync it around or similar. You'd of course be messed around by JDK's default caching policy but... > > 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. Still a hosts file.... > > 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. >>>>>>>> >>>>>>>> >>>>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>> >>>>> >>>> >>>> >>>> >>> >>> >> >> >> > >