Return-Path: Delivered-To: apmail-incubator-river-dev-archive@minotaur.apache.org Received: (qmail 87076 invoked from network); 11 Oct 2010 13:33:01 -0000 Received: from unknown (HELO mail.apache.org) (140.211.11.3) by 140.211.11.9 with SMTP; 11 Oct 2010 13:33:01 -0000 Received: (qmail 30596 invoked by uid 500); 11 Oct 2010 13:33:01 -0000 Delivered-To: apmail-incubator-river-dev-archive@incubator.apache.org Received: (qmail 30465 invoked by uid 500); 11 Oct 2010 13:32:59 -0000 Mailing-List: contact river-dev-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: river-dev@incubator.apache.org Delivered-To: mailing list river-dev@incubator.apache.org Received: (qmail 30456 invoked by uid 99); 11 Oct 2010 13:32:58 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 11 Oct 2010 13:32:58 +0000 X-ASF-Spam-Status: No, hits=0.7 required=10.0 tests=RCVD_IN_DNSWL_NONE,SPF_NEUTRAL X-Spam-Check-By: apache.org Received-SPF: neutral (nike.apache.org: local policy) Received: from [61.9.189.143] (HELO nschwmtas03p.mx.bigpond.com) (61.9.189.143) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 11 Oct 2010 13:32:49 +0000 Received: from nschwotgx03p.mx.bigpond.com ([61.9.223.241]) by nschwmtas03p.mx.bigpond.com with ESMTP id <20101011133223.UNZS13334.nschwmtas03p.mx.bigpond.com@nschwotgx03p.mx.bigpond.com> for ; Mon, 11 Oct 2010 13:32:23 +0000 Received: from [10.1.1.2] (really [61.9.223.241]) by nschwotgx03p.mx.bigpond.com with ESMTP id <20101011133222.FMTP16083.nschwotgx03p.mx.bigpond.com@[10.1.1.2]> for ; Mon, 11 Oct 2010 13:32:22 +0000 Message-ID: <4CB3108A.8050504@zeus.net.au> Date: Mon, 11 Oct 2010 23:26:34 +1000 From: Peter Firmstone User-Agent: Thunderbird 2.0.0.14 (X11/20080531) MIME-Version: 1.0 To: river-dev@incubator.apache.org Subject: Re: Towards Internet Jini Services (trust) References: <4C9DB5BF.8090307@zeus.net.au> <201010110946.18504.michal.kleczek@xpro.biz> <4CB2EFAA.6020602@zeus.net.au> <201010111335.28224.michal.kleczek@xpro.biz> In-Reply-To: <201010111335.28224.michal.kleczek@xpro.biz> Content-Type: text/plain; charset=ISO-8859-15; format=flowed Content-Transfer-Encoding: 7bit X-RPD-ScanID: Class unknown; VirusThreatLevel unknown, RefID str=0001.0A150205.4CB311E7.0025,ss=1,fgs=0 X-Virus-Checked: Checked by ClamAV on apache.org Ok, The ModuleServiceProvider adds a step: 1. A ModuleServiceProvider is deserialized (reflective proxy only) (consider it a Module Factory, could rename it to that too). 2. Deserialized ModuleServiceProvider is verified 3. A Module cache is checked using the ModuleServiceProvider as a key (weakly referenced). 4. If a Module exists in the cache, then that is used instead, goto 6. 5. If a Module doesn't exist in the cache for the Subject a new Module will be created using the ModuleServiceProvider 1. CodeSource[] is obtained for the Module using the ModuleServiceProvider 2. DownloadPermission is dynamically granted to all CodeSource in the array CodeSource[] only. 3. DownloadPermission is only required to load the jar files for the Module, via overriding SecureClassLoader.getPermissions(CodeSource cs) as per PreferredClassLoader. 4. The Module is deserialized, using the CodeSource[] URL's in a new ClassLoader instance. 5. The Module is verified. 6. The Module is granted GrantPermission(DownloadPermission) 7. The Module knows which CodeSources require DownloadPermission and grant's these dynamically on an as needed basis. 8. The Module needs a guard to check the caller has sufficient permission to use it, this would be created during module construction, we need to define a standard guard permissions for each method. 9. The Module is stored in the cache associated with the ModuleServiceProvider. 6. The Service Proxy is unmarshalled. 7. The service is verified (it has to authenticate with the same Subject as the ModuleServiceProvider). 8. The service is used. (Constraints ensure the service authenticates every method invocation). Note: The ModuleServiceProvider has the same Subject as the Service Proxy. Module needs an additional method: ClassLoader getClassLoader(Subject s); The Module needs to have a Subject parameter added to it's other methods too, the Module already know's the Codebase URL's, since this is it's responsibility, however it needs to ensure that different Subject's don't share ClassLoaders, in case multiple Subjects are using one Module with identical CodeSource, in the case where the Module Service provides for a number of Subjects. The Module Service, knows which jar files, module / package versions are in use for the requested classes. If Service Proxy's had OSGi embedded, they could be shutdown and reloaded with new Module versions, this would be synchronous with the Module Service. Ordinary services might simply be stopped and re looked up with updated jar files and annotated with a new ModuleServiceProvider instance. We can choose to limit other permission's also like SocketPermission's to particular domains. Can we cache jar files somehow based on their URL? I'm not certain if this is right, what do you think? Cheers, Peter. Michal Kleczek wrote: > Thanks for the tips on using Guard and subclassing Permission - I will update > the code. > > But I am not completely sure I follow your idea of ModuleServiceProvider. > > I'll try to explain why I think two permissions are needed. > Let's imagine a simple scenario: > > 1. A client gets a service proxy. > 2. Before actually downloading any code and deserializing the proxy the client > wants to verify a Module that it received as annotation. > 3. After the proxy is deserialized the client wants to grant the proxy a > permission to deserialize other objects that possibly will require other > Modules to be downloaded. > > So the following steps are performed: > 1. A Module is deserialized > 2. Deserialized Module is verified > 3. A service proxy is deserialized > 4. The service proxy is verified > 5. DownloadPermission is granted to the proxy ClassLoader (note that it is a > different ClassLoader than Module's ClassLoader) > > But how can we implement conditional Module verification? > We can have a locally installed verifier that just checks if currently > executing code has DownloadPermission and if that's the case consider any > Module trusted. But - of course - the client itself has DownloadPermission, so > this verifier would cause suppressing of Module verification alltogether. > The idea is to have another permission that only the client has - the verifier > would check that permission and if the calling code has it - consider Modules > untrusted. > So now the sequence is as follows: > 1. A Module is deserialized > 2. DelegatedModuleTrustVerifier checks for SuppressModuleInstallPermission. > 3. The client has it so DelegatedModuleTrustVerifier returns false > 4. The Module is verified using standard ProxyTrustVerifier > 5. A proxy is deserialized > 6. The proxy is verified > 7. The proxy is granted DownloadPermission > 8. The proxy tries to deserialize a subsequent object (annotated with another > Module) > 9. A Module is desecialized > 10. DelegatedModuleTrustVerifier checks for SuppressModuleInstallPermission. > Calling code does not have it so DelegatedModuleTrustVerifier checks for > DownloadPermission. Calling code does have DownloadPermission (see p. 7) so we > consider this Module trusted > 11. We're done :) > > Michal > > > On Monday 11 of October 2010 13:06:18 Peter Firmstone wrote: > >> I don't completely follow, why do you need the additional permission? >> >> Perhaps we could have ModuleServiceProvider that only allows a >> reflective proxy? We can authenticate a reflective proxy because >> there's no downloaded code. >> >> interface ModuleServiceProvider { >> CodeSource[] getModuleCodeSources(); >> Module getModule(); >> } >> >> Setting up the Module from the ModuleServiceProvider, we can obtain the >> CodeSource URL and Certificate's before downloading any jar files for >> the module and check if a Module ClassLoader has been registered for the >> Subject. >> >> We can then dynamically grant Permissions to that ClassLoader (using the >> Module's class) with the Subject's Principals[], so it only has the >> necessary Permission's when run as the Subject of the Service. >> >> A marshalled smart proxy could be annotated with the >> ModuleServiceProvider, which is authenticated, and has constraints set, >> prior to instantiating a ClassLoader with the URL[]'s(if it doesn't >> already exist), then deserialize the Module into it (by setting the >> context ClassLoader) and use the new Module to provision the smart >> proxy's jar archives. >> >> Have a look at Gregg Wonderly's CodebaseAccessClassLoader too. >> >> http://svn.apache.org/viewvc/incubator/river/jtsk/trunk/src/net/jini/loader >> /?pathrev=934258 >> >> Some Permission Tips: >> >> 1. For simple Permission classes, extend Permission instead of >> BasicPermission if you can, if you don't need implement your own >> PermissionCollection, the Policy will provide an implementation >> for you (I provide a multi read PermissionCollection with my >> Policy Provider for better concurrency). >> 2. Try using Guard installModule = new InstallModulePermission(); >> Then instead of calling the AccessController or SecurityManager, >> call installModule.checkGuard() instead, it gets the security >> manager for you and checks the Permission, when I've got the >> InternetSecurityManager finished, this will speed up your >> permission check for repeated checks. >> >> try { >> installModule.checkGuard(this); >> return true; >> } catch (SecurityException ex) { >> return false; >> } >> >> >> Cheers, >> >> Peter. >> >> Michal Kleczek wrote: >> >>> Of course we need something more since the client has >>> InstallModulePermission it would suppress trust verification >>> alltogether. The simple fix is to have two permissions and suppress >>> trust verification only when we only have one of them. The client has >>> both, so we are going to verify trust. >>> >>> class InstallModulePermission extends BasicPermission { >>> } >>> >>> class SuppressInstallModulePermission extends BasicPermission { >>> } >>> >>> public class DelegatedModuleTrustVerifier implements TrustVerifier { >>> >>> private static final InstallModulePermission >>> INSTALL_MODULE_PERMISSION = >>> >>> new InstallModulePermission(); >>> >>> private static final SuppressModuleTrustDelegationPermission >>> >>> SUPPRESS_MODULE_TRUST_DELEGATION_PERMISSION = >>> >>> new SuppressModuleTrustDelegationPermission(); >>> >>> @Override >>> public boolean isTrustedObject(Object o, Context cntxt) { >>> >>> if (o instanceof Module) { >>> >>> try { >>> >>> AccessController.checkPermission(SUPPRESS_MODULE_TRUST_DE >>> LEGATION_PERMISSION); return false; >>> >>> } >>> catch (SecurityException suppressEx) { >>> >>> try { >>> >>> AccessController.checkPermission(INSTALL_MODULE_PERMI >>> SSION); return true; >>> >>> } >>> catch (SecurityException installEx) { >>> >>> return false; >>> >>> } >>> >>> } >>> >>> } >>> >>> return false; >>> >>> } >>> >>> } >>> >>> >>> Michal >>> >>> On Monday 11 of October 2010 08:24:19 Michal Kleczek wrote: >>> >>>> On Monday 11 of October 2010 05:27:31 Peter Firmstone wrote: >>>> >>>>> Michal Kleczek wrote: >>>>> >>>>>> Some more thoughts. >>>>>> >>>>>> There is one scenario that is not covered here: >>>>>> >>>>>> I get an service, verify the module that loads its class using a >>>>>> ModuleAuthority that I trust. This service in turn downloads some >>>>>> other objects that it verified. There is no way I can delegate trust >>>>>> verification to the service - I must trust Modules (actually >>>>>> ModuleAuthorities) of those subsequent objects. >>>>>> >>>>>> 1. I have to have a way to allow or disallow module trust delegation >>>>>> (looks like a case for dynamic permission grants) >>>>>> >>>>> Currently PreferredClassLoader uses DownloadPermission to prevent or >>>>> allow a CodeSource class loading, because the CodeSource hasn't yet >>>>> been loaded, we cannot dynamically grant DownloadPermission to a >>>>> CodeSource, using DynamicPolicy. >>>>> >>>> Thanks for the hint. >>>> I think Module trust delegation can be achieved in a really simple way: >>>> >>>> class InstallModulePermission extends Permission { >>>> } >>>> >>>> //this TrustVerifier is installed locally on the client >>>> //so that delegation of Module trust verification can be done >>>> //by granting a service InstallModulePermission >>>> >>>> public class InstallModulePermissionVerifier implements TrustVerifier { >>>> >>>> private static final InstallModulePermission PERM = >>>> >>>> new InstallModulePermission() >>>> >>>> public boolean isTrustedObject(Object o, Context ctx) { >>>> >>>> try { >>>> >>>> if (o instanceof Module) { >>>> >>>> AccessController.checkPermission(PERM); >>>> return true; >>>> >>>> } >>>> >>>> return false; >>>> >>>> } >>>> catch (SecurityException e) { >>>> >>>> return false; >>>> >>>> } >>>> >>>> } >>>> >>>> } >>>> >>>> What do you think? >>>> >>>> Michal >>>> > >