blob: 3bef55ec5d9e61d617a09e2c7890455c3c0e0784 [file] [log] [blame]
Karl Pauls36407322008-03-07 00:37:30 +00001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19package org.apache.felix.framework.security.condpermadmin;
20
21import java.io.IOException;
Karl Pauls23287bd2010-01-10 22:11:27 +000022import java.io.InputStream;
23import java.math.BigInteger;
24import java.net.URL;
Karl Pauls36407322008-03-07 00:37:30 +000025import java.security.AccessControlContext;
Karl Pauls23287bd2010-01-10 22:11:27 +000026import java.security.InvalidKeyException;
27import java.security.NoSuchAlgorithmException;
28import java.security.NoSuchProviderException;
Karl Pauls36407322008-03-07 00:37:30 +000029import java.security.Permission;
Karl Pauls23287bd2010-01-10 22:11:27 +000030import java.security.Principal;
Karl Pauls36407322008-03-07 00:37:30 +000031import java.security.ProtectionDomain;
Karl Pauls23287bd2010-01-10 22:11:27 +000032import java.security.PublicKey;
33import java.security.SignatureException;
34import java.security.cert.X509Certificate;
35import java.util.AbstractSet;
Karl Pauls36407322008-03-07 00:37:30 +000036import java.util.ArrayList;
Karl Pauls23287bd2010-01-10 22:11:27 +000037import java.util.Collection;
38import java.util.Collections;
39import java.util.Date;
40import java.util.Dictionary;
Karl Pauls36407322008-03-07 00:37:30 +000041import java.util.Enumeration;
42import java.util.HashMap;
Karl Pauls23287bd2010-01-10 22:11:27 +000043import java.util.Hashtable;
Karl Pauls36407322008-03-07 00:37:30 +000044import java.util.Iterator;
45import java.util.List;
46import java.util.Map;
Karl Pauls23287bd2010-01-10 22:11:27 +000047import java.util.Set;
48import java.util.StringTokenizer;
Karl Pauls36407322008-03-07 00:37:30 +000049import java.util.Map.Entry;
50
Karl Pauls23287bd2010-01-10 22:11:27 +000051import org.apache.felix.framework.BundleProtectionDomain;
52import org.apache.felix.framework.security.permissionadmin.PermissionAdminImpl;
Karl Pauls36407322008-03-07 00:37:30 +000053import org.apache.felix.framework.security.util.Conditions;
54import org.apache.felix.framework.security.util.LocalPermissions;
55import org.apache.felix.framework.security.util.Permissions;
56import org.apache.felix.framework.security.util.PropertiesCache;
Karl Pauls23287bd2010-01-10 22:11:27 +000057import org.apache.felix.framework.util.manifestparser.R4Library;
Karl Paulsfbb32572010-05-30 22:16:56 +000058
59/*
Karl Pauls23287bd2010-01-10 22:11:27 +000060import org.apache.felix.moduleloader.ICapability;
Karl Paulsd093f2d2009-11-24 23:23:26 +000061import org.apache.felix.moduleloader.IContent;
Karl Pauls23287bd2010-01-10 22:11:27 +000062import org.apache.felix.moduleloader.IModule;
63import org.apache.felix.moduleloader.IRequirement;
64import org.apache.felix.moduleloader.IWire;
Karl Paulsfbb32572010-05-30 22:16:56 +000065*/
66import org.apache.felix.framework.capabilityset.Capability;
67import org.apache.felix.framework.capabilityset.Requirement;
68import org.apache.felix.framework.resolver.Content;
69import org.apache.felix.framework.resolver.Module;
70import org.apache.felix.framework.resolver.Wire;
71
Karl Pauls36407322008-03-07 00:37:30 +000072import org.osgi.framework.Bundle;
Karl Pauls23287bd2010-01-10 22:11:27 +000073import org.osgi.framework.BundleContext;
74import org.osgi.framework.BundleException;
75import org.osgi.framework.ServiceReference;
76import org.osgi.framework.Version;
Karl Pauls36407322008-03-07 00:37:30 +000077import org.osgi.service.condpermadmin.ConditionInfo;
78import org.osgi.service.condpermadmin.ConditionalPermissionAdmin;
79import org.osgi.service.condpermadmin.ConditionalPermissionInfo;
Karl Pauls23287bd2010-01-10 22:11:27 +000080import org.osgi.service.condpermadmin.ConditionalPermissionUpdate;
Karl Pauls36407322008-03-07 00:37:30 +000081import org.osgi.service.permissionadmin.PermissionInfo;
82
83/**
84 * An implementation of the ConditionalPermissionAdmin service that doesn't need
85 * to have a framework specific security manager set. It use the DomainGripper
Karl Pauls23287bd2010-01-10 22:11:27 +000086 * to know what bundleprotectiondomains are expected.
Karl Pauls36407322008-03-07 00:37:30 +000087 */
88public final class ConditionalPermissionAdminImpl implements
89 ConditionalPermissionAdmin
90{
Karl Pauls23287bd2010-01-10 22:11:27 +000091 private static class OrderedHashMap extends HashMap
92 {
93 private final List m_order = new ArrayList();
94
95 public Object put(Object key, Object value)
96 {
97 Object result = super.put(key, value);
98 if (result != value)
99 {
100 m_order.remove(key);
101 m_order.add(key);
102 }
103 return result;
104 };
105
106 public void putAll(Map map)
107 {
108 for (Iterator iter = map.entrySet().iterator(); iter.hasNext();)
109 {
110 Entry entry = (Entry) iter.next();
111 put(entry.getKey(), entry.getValue());
112 }
113 };
114
115 public Set keySet()
116 {
117 return new AbstractSet()
118 {
119 public Iterator iterator()
120 {
121 return m_order.iterator();
122 }
123
124 public int size()
125 {
126 return m_order.size();
127 }
128
129 };
130 };
131
132 public Set entrySet()
133 {
134 return new AbstractSet()
135 {
136
137 public Iterator iterator()
138 {
139 return new Iterator()
140 {
141 Iterator m_iter = m_order.iterator();
142
143 public boolean hasNext()
144 {
145 return m_iter.hasNext();
146 }
147
148 public Object next()
149 {
150 final Object key = m_iter.next();
151 return new Entry()
152 {
153
154 public Object getKey()
155 {
156 return key;
157 }
158
159 public Object getValue()
160 {
161 return get(key);
162 }
163
164 public Object setValue(Object arg0)
165 {
166 throw new IllegalStateException(
167 "Not Implemented");
168 }
169 };
170 }
171
172 public void remove()
173 {
174 throw new IllegalStateException("Not Implemented");
175 }
176
177 };
178 }
179
180 public int size()
181 {
182 return m_order.size();
183 }
184
185 };
186 };
187
188 public Collection values()
189 {
190 List result = new ArrayList();
191 for (Iterator iter = m_order.iterator(); iter.hasNext();)
192 {
193 result.add(super.get(iter.next()));
194 }
195 return result;
196 };
197
198 public Object remove(Object key)
199 {
200 Object result = super.remove(key);
201 if (result != null)
202 {
203 m_order.remove(key);
204 }
205 return result;
206 };
207
208 public void clear()
209 {
210 super.clear();
211 m_order.clear();
212 };
213 };
214
Karl Pauls36407322008-03-07 00:37:30 +0000215 private static final ConditionInfo[] EMPTY_CONDITION_INFO = new ConditionInfo[0];
216 private static final PermissionInfo[] EMPTY_PERMISSION_INFO = new PermissionInfo[0];
Karl Pauls23287bd2010-01-10 22:11:27 +0000217 private final Map m_condPermInfos = new OrderedHashMap();
Karl Pauls36407322008-03-07 00:37:30 +0000218 private final PropertiesCache m_propertiesCache;
219 private final Permissions m_permissions;
220 private final Conditions m_conditions;
221 private final LocalPermissions m_localPermissions;
Karl Pauls23287bd2010-01-10 22:11:27 +0000222 private final PermissionAdminImpl m_pai;
Karl Pauls36407322008-03-07 00:37:30 +0000223
224 public ConditionalPermissionAdminImpl(Permissions permissions,
225 Conditions condtions, LocalPermissions localPermissions,
Karl Pauls23287bd2010-01-10 22:11:27 +0000226 PropertiesCache cache, PermissionAdminImpl pai) throws IOException
Karl Pauls36407322008-03-07 00:37:30 +0000227 {
228 m_propertiesCache = cache;
229 m_permissions = permissions;
230 m_conditions = condtions;
231 m_localPermissions = localPermissions;
Karl Pauls23287bd2010-01-10 22:11:27 +0000232 Map old = new OrderedHashMap();
Karl Pauls36407322008-03-07 00:37:30 +0000233 // Now try to restore the cache.
Karl Pauls23287bd2010-01-10 22:11:27 +0000234 m_propertiesCache.read(ConditionalPermissionInfoImpl.class, old);
235 for (Iterator iter = old.entrySet().iterator(); iter.hasNext();)
Karl Pauls36407322008-03-07 00:37:30 +0000236 {
Karl Pauls23287bd2010-01-10 22:11:27 +0000237 Entry entry = (Entry) iter.next();
238 String name = (String) entry.getKey();
239 ConditionalPermissionInfoImpl cpi = ((ConditionalPermissionInfoImpl) entry
240 .getValue());
241 m_condPermInfos.put(name, new ConditionalPermissionInfoImpl(name,
242 cpi._getConditionInfos(), cpi._getPermissionInfos(), this, cpi
243 .isAllow()));
Karl Pauls36407322008-03-07 00:37:30 +0000244 }
Karl Pauls23287bd2010-01-10 22:11:27 +0000245 m_pai = pai;
Karl Pauls36407322008-03-07 00:37:30 +0000246 }
247
248 public ConditionalPermissionInfo addConditionalPermissionInfo(
249 ConditionInfo[] conditions, PermissionInfo[] permissions)
250 {
251 Object sm = System.getSecurityManager();
252 if (sm != null)
253 {
254 ((SecurityManager) sm).checkPermission(Permissions.ALL_PERMISSION);
255 }
Karl Pauls23287bd2010-01-10 22:11:27 +0000256 ConditionalPermissionInfoImpl result = new ConditionalPermissionInfoImpl(
257 notNull(conditions), notNull(permissions), this, true);
Karl Pauls36407322008-03-07 00:37:30 +0000258
259 return write(result.getName(), result);
260 }
261
262 ConditionalPermissionInfoImpl write(String name,
263 ConditionalPermissionInfoImpl cpi)
264 {
265 synchronized (m_propertiesCache)
266 {
267 Map tmp = null;
268
269 synchronized (m_condPermInfos)
270 {
Karl Pauls23287bd2010-01-10 22:11:27 +0000271 tmp = new OrderedHashMap();
272 tmp.putAll(m_condPermInfos);
Karl Pauls36407322008-03-07 00:37:30 +0000273
274 if ((name != null) && (cpi != null))
275 {
276 m_condPermInfos.put(name, cpi);
277 }
278 else if (name != null)
279 {
280 m_condPermInfos.remove(name);
281 }
282 else
283 {
284 tmp = null;
285 }
286 }
287
288 try
289 {
290 m_propertiesCache.write(m_condPermInfos);
291 }
292 catch (IOException ex)
293 {
294 synchronized (m_condPermInfos)
295 {
Karl Pauls23287bd2010-01-10 22:11:27 +0000296 if (tmp != null)
297 {
298 m_condPermInfos.clear();
299 m_condPermInfos.putAll(tmp);
300 }
Karl Pauls36407322008-03-07 00:37:30 +0000301 }
302 ex.printStackTrace();
303 throw new IllegalStateException(ex.getMessage());
304 }
305 }
306 synchronized (m_condPermInfos)
307 {
308 return (ConditionalPermissionInfoImpl) m_condPermInfos.get(name);
309 }
310 }
311
Karl Pauls23287bd2010-01-10 22:11:27 +0000312 private static class FakeBundle implements Bundle
Karl Pauls36407322008-03-07 00:37:30 +0000313 {
Karl Pauls23287bd2010-01-10 22:11:27 +0000314 private final Map m_certs;
315
316 public FakeBundle(Map certs)
317 {
318 m_certs = Collections.unmodifiableMap(certs);
319 }
320
321 public Enumeration findEntries(String arg0, String arg1, boolean arg2)
322 {
323 return null;
324 }
325
326 public BundleContext getBundleContext()
327 {
328 return null;
329 }
330
331 public long getBundleId()
332 {
333 return -1;
334 }
335
336 public URL getEntry(String arg0)
337 {
338 return null;
339 }
340
341 public Enumeration getEntryPaths(String arg0)
342 {
343 return null;
344 }
345
346 public Dictionary getHeaders()
347 {
348 return new Hashtable();
349 }
350
351 public Dictionary getHeaders(String arg0)
352 {
353 return new Hashtable();
354 }
355
356 public long getLastModified()
357 {
358 return 0;
359 }
360
361 public String getLocation()
362 {
363 return "";
364 }
365
366 public ServiceReference[] getRegisteredServices()
367 {
368 return null;
369 }
370
371 public URL getResource(String arg0)
372 {
373 return null;
374 }
375
376 public Enumeration getResources(String arg0) throws IOException
377 {
378 return null;
379 }
380
381 public ServiceReference[] getServicesInUse()
382 {
383 return null;
384 }
385
386 public Map getSignerCertificates(int arg0)
387 {
388 return m_certs;
389 }
390
391 public int getState()
392 {
393 return Bundle.UNINSTALLED;
394 }
395
396 public String getSymbolicName()
397 {
398 return null;
399 }
400
401 public Version getVersion()
402 {
403 return Version.emptyVersion;
404 }
405
406 public boolean hasPermission(Object arg0)
407 {
408 return false;
409 }
410
411 public Class loadClass(String arg0) throws ClassNotFoundException
412 {
413 return null;
414 }
415
416 public void start() throws BundleException
417 {
418 throw new IllegalStateException();
419 }
420
421 public void start(int arg0) throws BundleException
422 {
423 throw new IllegalStateException();
424 }
425
426 public void stop() throws BundleException
427 {
428 throw new IllegalStateException();
429 }
430
431 public void stop(int arg0) throws BundleException
432 {
433 throw new IllegalStateException();
434 }
435
436 public void uninstall() throws BundleException
437 {
438 throw new IllegalStateException();
439 }
440
441 public void update() throws BundleException
442 {
443 throw new IllegalStateException();
444 }
445
446 public void update(InputStream arg0) throws BundleException
447 {
448 throw new IllegalStateException();
449 }
450
451 public boolean equals(Object o)
452 {
453 return this == o;
454 }
455
456 public int hashCode()
457 {
458 return System.identityHashCode(this);
459 }
460 }
461
462 private static class FakeCert extends X509Certificate
463 {
464 private final Principal m_principal;
465
466 public FakeCert(final String principal)
467 {
468 m_principal = new Principal()
Karl Pauls36407322008-03-07 00:37:30 +0000469 {
Karl Pauls23287bd2010-01-10 22:11:27 +0000470 public String getName()
Karl Pauls36407322008-03-07 00:37:30 +0000471 {
Karl Pauls23287bd2010-01-10 22:11:27 +0000472 return principal;
Karl Pauls36407322008-03-07 00:37:30 +0000473 }
Karl Pauls23287bd2010-01-10 22:11:27 +0000474 };
475 }
476
477 public void checkValidity()
478 throws java.security.cert.CertificateExpiredException,
479 java.security.cert.CertificateNotYetValidException
480 {
481
482 }
483
484 public void checkValidity(Date date)
485 throws java.security.cert.CertificateExpiredException,
486 java.security.cert.CertificateNotYetValidException
487 {
488 }
489
490 public int getBasicConstraints()
491 {
492 return 0;
493 }
494
495 public Principal getIssuerDN()
496 {
497 return null;
498 }
499
500 public boolean[] getIssuerUniqueID()
501 {
502 return null;
503 }
504
505 public boolean[] getKeyUsage()
506 {
507 return null;
508 }
509
510 public Date getNotAfter()
511 {
512 return null;
513 }
514
515 public Date getNotBefore()
516 {
517 return null;
518 }
519
520 public BigInteger getSerialNumber()
521 {
522 return null;
523 }
524
525 public String getSigAlgName()
526 {
527 return null;
528 }
529
530 public String getSigAlgOID()
531 {
532 return null;
533 }
534
535 public byte[] getSigAlgParams()
536 {
537 return null;
538 }
539
540 public byte[] getSignature()
541 {
542 return null;
543 }
544
545 public Principal getSubjectDN()
546 {
547 return m_principal;
548 }
549
550 public boolean[] getSubjectUniqueID()
551 {
552 return null;
553 }
554
555 public byte[] getTBSCertificate()
556 throws java.security.cert.CertificateEncodingException
557 {
558 return null;
559 }
560
561 public int getVersion()
562 {
563 return 0;
564 }
565
566 public byte[] getEncoded()
567 throws java.security.cert.CertificateEncodingException
568 {
569 return null;
570 }
571
572 public PublicKey getPublicKey()
573 {
574 return null;
575 }
576
577 public String toString()
578 {
579 return m_principal.getName();
580 }
581
582 public void verify(PublicKey key)
583 throws java.security.cert.CertificateException,
584 NoSuchAlgorithmException, InvalidKeyException,
585 NoSuchProviderException, SignatureException
586 {
587
588 }
589
590 public void verify(PublicKey key, String sigProvider)
591 throws java.security.cert.CertificateException,
592 NoSuchAlgorithmException, InvalidKeyException,
593 NoSuchProviderException, SignatureException
594 {
595
596 }
597
598 public Set getCriticalExtensionOIDs()
599 {
600 return null;
601 }
602
603 public byte[] getExtensionValue(String arg0)
604 {
605 return null;
606 }
607
608 public Set getNonCriticalExtensionOIDs()
609 {
610 return null;
611 }
612
613 public boolean hasUnsupportedCriticalExtension()
614 {
615 return false;
616 }
617
618 public boolean equals(Object o)
619 {
620 return this == o;
621 }
622
623 public int hashCode()
624 {
625 return System.identityHashCode(this);
626 }
627
628 }
629
630 public AccessControlContext getAccessControlContext(final String[] signers)
631 {
632 Map certificates = new HashMap();
633 for (int i = 0; i < signers.length; i++)
634 {
635 StringTokenizer tok = new StringTokenizer(signers[i], ";");
636 List certsList = new ArrayList();
637 while (tok.hasMoreTokens())
638 {
639 certsList.add(tok.nextToken());
640 }
641 String[] certs = (String[]) certsList.toArray(new String[certsList
642 .size()]);
643
644 X509Certificate key = new FakeCert(certs[0]);
645 List certList = new ArrayList();
646 certificates.put(key, certList);
647 certList.add(key);
648 for (int j = 1; j < certs.length; j++)
649 {
650 certList.add(new FakeCert(certs[j]));
651 }
652 }
653 final Bundle fake = new FakeBundle(certificates);
654 ProtectionDomain domain = new ProtectionDomain(null, null)
655 {
656 public boolean implies(Permission permission)
657 {
658 List posts = new ArrayList();
659 Boolean result = m_pai.hasPermission("", fake, permission,
660 ConditionalPermissionAdminImpl.this, this, null);
661 if (result != null)
662 {
663 return result.booleanValue();
664 }
Karl Paulsfbb32572010-05-30 22:16:56 +0000665 if (eval(posts, new Module()
Karl Pauls23287bd2010-01-10 22:11:27 +0000666 {
667
668 public Bundle getBundle()
669 {
670 return fake;
671 }
672
Karl Paulsfbb32572010-05-30 22:16:56 +0000673 public List<Capability> getCapabilities()
Karl Pauls23287bd2010-01-10 22:11:27 +0000674 {
675 return null;
676 }
677
678 public Class getClassByDelegation(String arg0)
679 throws ClassNotFoundException
680 {
681 return null;
682 }
683
Karl Paulsfbb32572010-05-30 22:16:56 +0000684 public Content getContent()
Karl Pauls23287bd2010-01-10 22:11:27 +0000685 {
686 return null;
687 }
688
689 public int getDeclaredActivationPolicy()
690 {
691 return 0;
692 }
693
Karl Paulsfbb32572010-05-30 22:16:56 +0000694 public List<Requirement> getDynamicRequirements()
Karl Pauls23287bd2010-01-10 22:11:27 +0000695 {
696 return null;
697 }
698
699 public URL getEntry(String arg0)
700 {
701 return null;
702 }
703
704 public Map getHeaders()
705 {
706 return null;
707 }
708
709 public String getId()
710 {
711 return null;
712 }
713
714 public InputStream getInputStream(int arg0, String arg1)
715 throws IOException
716 {
717 return null;
718 }
719
Karl Paulsfbb32572010-05-30 22:16:56 +0000720 public List<R4Library> getNativeLibraries()
Karl Pauls23287bd2010-01-10 22:11:27 +0000721 {
722 return null;
723 }
724
Karl Paulsfbb32572010-05-30 22:16:56 +0000725 public List<Requirement> getRequirements()
Karl Pauls23287bd2010-01-10 22:11:27 +0000726 {
727 return null;
728 }
729
730 public URL getResourceByDelegation(String arg0)
731 {
732 return null;
733 }
734
735 public Enumeration getResourcesByDelegation(String arg0)
736 {
737 return null;
738 }
739
740 public Object getSecurityContext()
741 {
742 return null;
743 }
744
745 public String getSymbolicName()
746 {
747 return null;
748 }
749
750 public Version getVersion()
751 {
752 return null;
753 }
754
Karl Paulsfbb32572010-05-30 22:16:56 +0000755 public List<Wire> getWires()
Karl Pauls23287bd2010-01-10 22:11:27 +0000756 {
757 return null;
758 }
759
760 public boolean hasInputStream(int arg0, String arg1)
761 throws IOException
762 {
763 return false;
764 }
765
766 public boolean isExtension()
767 {
768 return false;
769 }
770
771 public boolean isResolved()
772 {
773 return false;
774 }
775
776 public void setSecurityContext(Object arg0)
777 {
778 }
Karl Paulse2913e62010-12-22 18:29:22 +0000779
780 public URL getLocalURL(int arg0, String arg1)
781 {
782 // TODO Auto-generated method stub
783 return null;
784 }
Karl Pauls23287bd2010-01-10 22:11:27 +0000785 }, permission, m_pai))
786 {
787 if (!posts.isEmpty())
788 {
789 return m_conditions.evalRecursive(posts);
790 }
791 return true;
792 }
793 return false;
794 }
795 };
796 return new AccessControlContext(new ProtectionDomain[] { domain });
Karl Pauls36407322008-03-07 00:37:30 +0000797 }
798
799 public ConditionalPermissionInfo getConditionalPermissionInfo(String name)
800 {
801 if (name == null)
802 {
803 throw new IllegalArgumentException("Name may not be null");
804 }
805 ConditionalPermissionInfoImpl result = null;
806
807 synchronized (m_condPermInfos)
808 {
809 result = (ConditionalPermissionInfoImpl) m_condPermInfos.get(name);
810 }
811
812 if (result == null)
813 {
Karl Pauls23287bd2010-01-10 22:11:27 +0000814 result = new ConditionalPermissionInfoImpl(this, name, true);
Karl Pauls36407322008-03-07 00:37:30 +0000815
816 result = write(result.getName(), result);
817 }
818
819 return result;
820 }
821
822 public Enumeration getConditionalPermissionInfos()
823 {
824 synchronized (m_condPermInfos)
825 {
Karl Paulse2913e62010-12-22 18:29:22 +0000826 return Collections.enumeration(new ArrayList(m_condPermInfos
827 .values()));
Karl Pauls36407322008-03-07 00:37:30 +0000828 }
829 }
830
831 public ConditionalPermissionInfo setConditionalPermissionInfo(String name,
832 ConditionInfo[] conditions, PermissionInfo[] permissions)
833 {
834 Object sm = System.getSecurityManager();
835 if (sm != null)
836 {
837 ((SecurityManager) sm).checkPermission(Permissions.ALL_PERMISSION);
838 }
839
840 ConditionalPermissionInfoImpl result = null;
841 conditions = notNull(conditions);
842 permissions = notNull(permissions);
843
844 if (name != null)
845 {
846 synchronized (m_condPermInfos)
847 {
Karl Pauls23287bd2010-01-10 22:11:27 +0000848 result = (ConditionalPermissionInfoImpl) m_condPermInfos
849 .get(name);
Karl Pauls36407322008-03-07 00:37:30 +0000850
851 if (result == null)
852 {
Karl Pauls23287bd2010-01-10 22:11:27 +0000853 result = new ConditionalPermissionInfoImpl(name,
854 conditions, permissions, this, true);
Karl Pauls36407322008-03-07 00:37:30 +0000855 }
856 else
857 {
858 result.setConditionsAndPermissions(conditions, permissions);
859 }
860 }
861 }
862 else
863 {
Karl Pauls23287bd2010-01-10 22:11:27 +0000864 result = new ConditionalPermissionInfoImpl(conditions, permissions,
865 this, true);
Karl Pauls36407322008-03-07 00:37:30 +0000866 }
867
868 return write(result.getName(), result);
869 }
870
871 private PermissionInfo[] notNull(PermissionInfo[] permissions)
872 {
873 if (permissions == null)
874 {
875 return ConditionalPermissionInfoImpl.PERMISSION_INFO;
876 }
877 return (PermissionInfo[]) notNull((Object[]) permissions).toArray(
878 EMPTY_PERMISSION_INFO);
879 }
880
881 private ConditionInfo[] notNull(ConditionInfo[] conditions)
882 {
883 if (conditions == null)
884 {
885 return ConditionalPermissionInfoImpl.CONDITION_INFO;
886 }
887 return (ConditionInfo[]) notNull((Object[]) conditions).toArray(
888 EMPTY_CONDITION_INFO);
889 }
890
891 private List notNull(Object[] elements)
892 {
893 List result = new ArrayList();
894
895 for (int i = 0; i < elements.length; i++)
896 {
897 if (elements[i] != null)
898 {
899 result.add(elements[i]);
900 }
901 }
902
903 return result;
904 }
905
906 // The thread local stack used to keep track of bundle protection domains we
907 // still expect to see.
908 private final ThreadLocal m_stack = new ThreadLocal();
909
910 /**
911 * This method does the actual permission check. If it is not a direct check
Karl Pauls23287bd2010-01-10 22:11:27 +0000912 * it will try to determine the other bundle domains that will follow
913 * automatically in case this is the first check in one permission check. If
914 * not then it will keep track of which domains we have already see. While
915 * it keeps track it builds up a list of postponed tuples which it will
916 * evaluate at the last domain. See the core spec 9.5.1 and following for a
917 * general description.
Karl Pauls36407322008-03-07 00:37:30 +0000918 *
Karl Pauls23287bd2010-01-10 22:11:27 +0000919 * @param felixBundle
920 * the bundle in question.
921 * @param loader
922 * the content loader of the bundle to get access to the jar to
923 * check for local permissions.
924 * @param root
925 * the bundle id.
926 * @param signers
927 * the signers (this is to support the ACC based on signers)
928 * @param pd
929 * the bundle protection domain
930 * @param permission
931 * the permission currently checked
932 * @param direct
933 * whether this is a direct check or not. direct check will not
934 * expect any further bundle domains on the stack
935 * @return true in case the permission is granted or there are postponed
936 * tuples false if not. Again, see the spec for more explanations.
Karl Pauls36407322008-03-07 00:37:30 +0000937 */
Karl Paulsfbb32572010-05-30 22:16:56 +0000938 public boolean hasPermission(Module module, Content content,
Karl Pauls23287bd2010-01-10 22:11:27 +0000939 ProtectionDomain pd, Permission permission, boolean direct, Object admin)
Karl Pauls36407322008-03-07 00:37:30 +0000940 {
941 // System.out.println(felixBundle + "-" + permission);
942 List domains = null;
943 List tuples = null;
944 Object[] entry = null;
Karl Pauls23287bd2010-01-10 22:11:27 +0000945 // first see whether this is the normal case (the special case is for
Karl Pauls36407322008-03-07 00:37:30 +0000946 // the ACC based on signers).
Karl Pauls23287bd2010-01-10 22:11:27 +0000947 // In case of a direct call we don't need to look for other pds
948 if (direct)
Karl Pauls36407322008-03-07 00:37:30 +0000949 {
Karl Pauls23287bd2010-01-10 22:11:27 +0000950 domains = new ArrayList();
951 tuples = new ArrayList();
952 domains.add(pd);
953 }
954 else
955 {
956 // Get the other pds from the stck
957 entry = (Object[]) m_stack.get();
958
959 // if there are none then get them from the gripper
960 if (entry == null)
Karl Pauls36407322008-03-07 00:37:30 +0000961 {
Karl Pauls23287bd2010-01-10 22:11:27 +0000962 entry = new Object[] { new ArrayList(DomainGripper.grab()),
963 new ArrayList() };
Karl Pauls36407322008-03-07 00:37:30 +0000964 }
965 else
966 {
Karl Pauls23287bd2010-01-10 22:11:27 +0000967 m_stack.set(null);
968 }
Karl Pauls36407322008-03-07 00:37:30 +0000969
Karl Pauls23287bd2010-01-10 22:11:27 +0000970 domains = (List) entry[0];
971 tuples = (List) entry[1];
972 if (!domains.contains(pd))
973 {
974 // We have been called directly without the direct flag
975 domains.clear();
976 domains.add(pd);
Karl Pauls36407322008-03-07 00:37:30 +0000977 }
978 }
979
980 // check the local permissions. they need to all the permission if there
981 // are any
Karl Pauls23287bd2010-01-10 22:11:27 +0000982 if (!impliesLocal(module.getBundle(), content, permission))
Karl Pauls36407322008-03-07 00:37:30 +0000983 {
984 return false;
985 }
986
987 List posts = new ArrayList();
988
Karl Pauls23287bd2010-01-10 22:11:27 +0000989 boolean result = eval(posts, module, permission, admin);
Karl Pauls36407322008-03-07 00:37:30 +0000990
991 domains.remove(pd);
992
993 // We postponed tuples
994 if (!posts.isEmpty())
995 {
996 tuples.add(posts);
997 }
998
999 // Are we at the end or this was a direct call?
1000 if (domains.isEmpty())
1001 {
1002 m_stack.set(null);
Karl Pauls23287bd2010-01-10 22:11:27 +00001003 // Now eval the postponed tupels. if the previous eval did return
1004 // false
Karl Pauls36407322008-03-07 00:37:30 +00001005 // tuples will be empty so we don't return from here.
1006 if (!tuples.isEmpty())
1007 {
1008 return m_conditions.evalRecursive(tuples);
1009 }
1010 }
1011 else
1012 {
Karl Pauls23287bd2010-01-10 22:11:27 +00001013 // this is to support recursive permission checks. In case we
1014 // trigger
Karl Pauls36407322008-03-07 00:37:30 +00001015 // a permission check while eval the stack is null until this point
1016 m_stack.set(entry);
1017 }
1018
1019 return result;
1020 }
1021
Karl Paulsfbb32572010-05-30 22:16:56 +00001022 public boolean impliesLocal(Bundle felixBundle, Content content,
Karl Pauls23287bd2010-01-10 22:11:27 +00001023 Permission permission)
1024 {
1025 return m_localPermissions.implies(content, felixBundle, permission);
1026 }
1027
Karl Pauls35c1c342008-03-19 17:39:16 +00001028 public boolean isEmpty()
1029 {
1030 synchronized (m_condPermInfos)
1031 {
1032 return m_condPermInfos.isEmpty();
1033 }
1034 }
1035
Karl Pauls36407322008-03-07 00:37:30 +00001036 // we need to find all conditions that apply and then check whether they
1037 // de note the permission in question unless the conditions are postponed
1038 // then we make sure their permissions imply the permission and add them
1039 // to the list of posts. Return true in case we pass or have posts
1040 // else falls and clear the posts first.
Karl Paulsfbb32572010-05-30 22:16:56 +00001041 private boolean eval(List posts, Module module, Permission permission,
Karl Pauls23287bd2010-01-10 22:11:27 +00001042 Object admin)
Karl Pauls36407322008-03-07 00:37:30 +00001043 {
1044 List condPermInfos = null;
1045
1046 synchronized (m_condPermInfos)
1047 {
Karl Pauls35c1c342008-03-19 17:39:16 +00001048 if (isEmpty() && (admin == null))
Karl Pauls36407322008-03-07 00:37:30 +00001049 {
1050 return true;
1051 }
1052 condPermInfos = new ArrayList(m_condPermInfos.values());
1053 }
1054
1055 // Check for implicit permissions like access to file area
Karl Pauls23287bd2010-01-10 22:11:27 +00001056 if (m_permissions.getPermissions(
1057 m_permissions.getImplicit(module.getBundle())).implies(permission,
1058 module.getBundle()))
Karl Pauls36407322008-03-07 00:37:30 +00001059 {
1060 return true;
1061 }
Karl Pauls23287bd2010-01-10 22:11:27 +00001062 List pls = new ArrayList();
Karl Pauls36407322008-03-07 00:37:30 +00001063 // now do the real thing
1064 for (Iterator iter = condPermInfos.iterator(); iter.hasNext();)
1065 {
Karl Pauls23287bd2010-01-10 22:11:27 +00001066 ConditionalPermissionInfoImpl cpi = (ConditionalPermissionInfoImpl) iter
1067 .next();
Karl Pauls36407322008-03-07 00:37:30 +00001068
1069 ConditionInfo[] conditions = cpi._getConditionInfos();
1070
1071 List currentPosts = new ArrayList();
1072
Karl Pauls23287bd2010-01-10 22:11:27 +00001073 Conditions conds = m_conditions.getConditions(module, conditions);
1074 if (!conds.isSatisfied(currentPosts, m_permissions
1075 .getPermissions(cpi._getPermissionInfos()), permission))
Karl Pauls36407322008-03-07 00:37:30 +00001076 {
1077 continue;
1078 }
1079
1080 if (!m_permissions.getPermissions(cpi._getPermissionInfos())
1081 .implies(permission, null))
1082 {
1083 continue;
1084 }
1085
1086 if (currentPosts.isEmpty())
1087 {
Karl Pauls23287bd2010-01-10 22:11:27 +00001088 pls.add(new Object[] { cpi, null });
1089 break;
1090 }
1091 pls.add(new Object[] { cpi, currentPosts, conds });
1092 }
1093 while (pls.size() > 1)
1094 {
1095 if (!((ConditionalPermissionInfoImpl) ((Object[]) pls.get(pls
1096 .size() - 1))[0]).isAllow())
1097 {
1098 pls.remove(pls.size() - 1);
1099 }
1100 else
1101 {
1102 break;
1103 }
1104 }
1105 if (pls.size() == 1)
1106 {
1107 if (((Object[]) pls.get(0))[1] != null)
1108 {
1109 posts.add(pls.get(0));
1110 }
1111 return ((ConditionalPermissionInfoImpl) ((Object[]) pls.get(0))[0])
1112 .isAllow();
1113 }
1114 for (Iterator iter = pls.iterator(); iter.hasNext();)
1115 {
1116 posts.add(iter.next());
1117 }
1118 return !posts.isEmpty();
1119 }
1120
1121 public ConditionalPermissionInfo newConditionalPermissionInfo(
1122 String encodedConditionalPermissionInfo)
1123 {
1124 return new ConditionalPermissionInfoImpl(
1125 encodedConditionalPermissionInfo);
1126 }
1127
1128 public ConditionalPermissionInfo newConditionalPermissionInfo(String name,
1129 ConditionInfo[] conditions, PermissionInfo[] permissions, String access)
1130 {
1131 return new ConditionalPermissionInfoImpl(name, conditions, permissions,
1132 ConditionalPermissionAdminImpl.this, access
1133 .equals(ConditionalPermissionInfo.ALLOW));
1134 }
1135
1136 public ConditionalPermissionUpdate newConditionalPermissionUpdate()
1137 {
1138 return new ConditionalPermissionUpdate()
1139 {
1140 List current = null;
1141 List out = null;
1142 {
1143 synchronized (m_condPermInfos)
1144 {
1145 current = new ArrayList(m_condPermInfos.values());
1146 out = new ArrayList(m_condPermInfos.values());
1147 }
1148 }
1149
1150 public boolean commit()
1151 {
1152 synchronized (m_condPermInfos)
1153 {
1154 if (current.equals(new ArrayList(m_condPermInfos.values())))
1155 {
1156 m_condPermInfos.clear();
1157 write(null, null);
1158 for (Iterator iter = out.iterator(); iter.hasNext();)
1159 {
1160 ConditionalPermissionInfoImpl cpii = (ConditionalPermissionInfoImpl) iter
1161 .next();
1162 write(cpii.getName(), cpii);
1163 }
1164 }
1165 else
1166 {
1167 return false;
1168 }
1169 }
Karl Pauls36407322008-03-07 00:37:30 +00001170 return true;
1171 }
1172
Karl Pauls23287bd2010-01-10 22:11:27 +00001173 public List getConditionalPermissionInfos()
1174 {
1175 return out;
1176 }
1177 };
1178 }
1179
1180 public boolean handlePAHandle(BundleProtectionDomain pd)
1181 {
1182 Object[] entry = (Object[]) m_stack.get();
1183
1184 if (entry == null)
1185 {
1186 entry = new Object[] { new ArrayList(DomainGripper.grab()),
1187 new ArrayList() };
Karl Pauls36407322008-03-07 00:37:30 +00001188 }
1189
Karl Pauls23287bd2010-01-10 22:11:27 +00001190 ((List) entry[0]).remove(pd);
1191 if (((List) entry[0]).isEmpty())
1192 {
1193 m_stack.set(null);
1194 if (!((List) entry[1]).isEmpty())
1195 {
1196 return m_conditions.evalRecursive(((List) entry[1]));
1197 }
1198 }
1199 else
1200 {
1201 m_stack.set(entry);
1202 }
1203
1204 return true;
1205 }
1206
1207 public void clearPD()
1208 {
1209 m_stack.set(null);
Karl Pauls36407322008-03-07 00:37:30 +00001210 }
1211}