The first approach is to play with the permissions settings, and the workflows that modify them. The main issue is that the permissions are only checked on the object thats actually accessed, but not on all its parents. That means that e.g. if I have the local role Reader on baz in /foo/bar/baz, but I don't have it in bar, I can still access it. The same holds true for permissions.
There is ZPublisher.BaseRequest:422 (traverse), which calls __before_publishing_traverse. If this method exists, it gets called - so maybe here response.unauthorized could be called.
Lets assume it would work - what would we do in the catalog? At least in plone by default only objects that can be accessed by the user are returned from the catalog.
allowedRolesAndUsers(obj,portal,**kwargs) Return a list of roles and users with View permission. Used by PortalCatalog to filter out items you're not allowed to see.
So, this means that the object needs to know about the parents permissions. So, either its reindexed everytime the parent object changes, or the index upon being queried would have to dynamically determine the permissions. Not sure which one sounds more ugly.
Might be that actually reindexing is better. If that was the case, then one might just as well go and upon reindexing set the permissions on the object so that it fully reflects the permissions when taking its parents into account. Ugly thing is that then there are two sets of perms - the ones one modifies, and the ones that are effectively doing the job.
Once could have:
object._unix_owner = 'jhb' object._unix_group = 'users' object._unix_perms = '700'
and set the roles and perms accordingly