blob: 16f8c2b6ac9539274b701b1a01720c05275493d5 [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
Karl Paulsf6756bd2011-09-09 12:50:01 +000021import java.io.File;
Karl Pauls36407322008-03-07 00:37:30 +000022import java.io.IOException;
Karl Pauls23287bd2010-01-10 22:11:27 +000023import java.io.InputStream;
24import java.math.BigInteger;
25import java.net.URL;
Karl Pauls36407322008-03-07 00:37:30 +000026import java.security.AccessControlContext;
Karl Pauls23287bd2010-01-10 22:11:27 +000027import java.security.InvalidKeyException;
28import java.security.NoSuchAlgorithmException;
29import java.security.NoSuchProviderException;
Karl Pauls36407322008-03-07 00:37:30 +000030import java.security.Permission;
Karl Pauls23287bd2010-01-10 22:11:27 +000031import java.security.Principal;
Karl Pauls36407322008-03-07 00:37:30 +000032import java.security.ProtectionDomain;
Karl Pauls23287bd2010-01-10 22:11:27 +000033import java.security.PublicKey;
34import java.security.SignatureException;
35import java.security.cert.X509Certificate;
36import java.util.AbstractSet;
Karl Pauls36407322008-03-07 00:37:30 +000037import java.util.ArrayList;
Karl Pauls23287bd2010-01-10 22:11:27 +000038import java.util.Collection;
39import java.util.Collections;
40import java.util.Date;
41import java.util.Dictionary;
Karl Pauls36407322008-03-07 00:37:30 +000042import java.util.Enumeration;
43import java.util.HashMap;
Karl Pauls23287bd2010-01-10 22:11:27 +000044import java.util.Hashtable;
Karl Pauls36407322008-03-07 00:37:30 +000045import java.util.Iterator;
46import java.util.List;
47import java.util.Map;
Karl Pauls23287bd2010-01-10 22:11:27 +000048import java.util.Set;
49import java.util.StringTokenizer;
Karl Pauls36407322008-03-07 00:37:30 +000050import java.util.Map.Entry;
51
Karl Pauls23287bd2010-01-10 22:11:27 +000052import org.apache.felix.framework.BundleProtectionDomain;
Karl Paulsf6756bd2011-09-09 12:50:01 +000053import org.apache.felix.framework.BundleRevisionImpl;
Karl Pauls23287bd2010-01-10 22:11:27 +000054import org.apache.felix.framework.security.permissionadmin.PermissionAdminImpl;
Karl Pauls36407322008-03-07 00:37:30 +000055import org.apache.felix.framework.security.util.Conditions;
56import org.apache.felix.framework.security.util.LocalPermissions;
57import org.apache.felix.framework.security.util.Permissions;
58import org.apache.felix.framework.security.util.PropertiesCache;
Bob Pauline8047902014-12-24 01:24:58 +000059import org.apache.felix.framework.util.manifestparser.NativeLibrary;
Karl Paulsfbb32572010-05-30 22:16:56 +000060
61/*
Karl Pauls23287bd2010-01-10 22:11:27 +000062import org.apache.felix.moduleloader.ICapability;
Karl Paulsd093f2d2009-11-24 23:23:26 +000063import org.apache.felix.moduleloader.IContent;
Karl Pauls23287bd2010-01-10 22:11:27 +000064import org.apache.felix.moduleloader.IModule;
65import org.apache.felix.moduleloader.IRequirement;
66import org.apache.felix.moduleloader.IWire;
Karl Paulsfbb32572010-05-30 22:16:56 +000067*/
Karl Paulsf6756bd2011-09-09 12:50:01 +000068import org.apache.felix.framework.cache.Content;
Karl Paulsfbb32572010-05-30 22:16:56 +000069
Karl Pauls36407322008-03-07 00:37:30 +000070import org.osgi.framework.Bundle;
Karl Pauls23287bd2010-01-10 22:11:27 +000071import org.osgi.framework.BundleContext;
72import org.osgi.framework.BundleException;
73import org.osgi.framework.ServiceReference;
74import org.osgi.framework.Version;
Karl Pauls36407322008-03-07 00:37:30 +000075import org.osgi.service.condpermadmin.ConditionInfo;
76import org.osgi.service.condpermadmin.ConditionalPermissionAdmin;
77import org.osgi.service.condpermadmin.ConditionalPermissionInfo;
Karl Pauls23287bd2010-01-10 22:11:27 +000078import org.osgi.service.condpermadmin.ConditionalPermissionUpdate;
Karl Pauls36407322008-03-07 00:37:30 +000079import org.osgi.service.permissionadmin.PermissionInfo;
80
81/**
82 * An implementation of the ConditionalPermissionAdmin service that doesn't need
83 * to have a framework specific security manager set. It use the DomainGripper
Karl Pauls23287bd2010-01-10 22:11:27 +000084 * to know what bundleprotectiondomains are expected.
Karl Pauls36407322008-03-07 00:37:30 +000085 */
86public final class ConditionalPermissionAdminImpl implements
87 ConditionalPermissionAdmin
88{
Karl Pauls23287bd2010-01-10 22:11:27 +000089 private static class OrderedHashMap extends HashMap
90 {
91 private final List m_order = new ArrayList();
92
93 public Object put(Object key, Object value)
94 {
95 Object result = super.put(key, value);
96 if (result != value)
97 {
98 m_order.remove(key);
99 m_order.add(key);
100 }
101 return result;
102 };
103
104 public void putAll(Map map)
105 {
106 for (Iterator iter = map.entrySet().iterator(); iter.hasNext();)
107 {
108 Entry entry = (Entry) iter.next();
109 put(entry.getKey(), entry.getValue());
110 }
111 };
112
113 public Set keySet()
114 {
115 return new AbstractSet()
116 {
117 public Iterator iterator()
118 {
119 return m_order.iterator();
120 }
121
122 public int size()
123 {
124 return m_order.size();
125 }
126
127 };
128 };
129
130 public Set entrySet()
131 {
132 return new AbstractSet()
133 {
134
135 public Iterator iterator()
136 {
137 return new Iterator()
138 {
139 Iterator m_iter = m_order.iterator();
140
141 public boolean hasNext()
142 {
143 return m_iter.hasNext();
144 }
145
146 public Object next()
147 {
148 final Object key = m_iter.next();
149 return new Entry()
150 {
151
152 public Object getKey()
153 {
154 return key;
155 }
156
157 public Object getValue()
158 {
159 return get(key);
160 }
161
162 public Object setValue(Object arg0)
163 {
164 throw new IllegalStateException(
165 "Not Implemented");
166 }
167 };
168 }
169
170 public void remove()
171 {
172 throw new IllegalStateException("Not Implemented");
173 }
174
175 };
176 }
177
178 public int size()
179 {
180 return m_order.size();
181 }
182
183 };
184 };
185
186 public Collection values()
187 {
188 List result = new ArrayList();
189 for (Iterator iter = m_order.iterator(); iter.hasNext();)
190 {
191 result.add(super.get(iter.next()));
192 }
193 return result;
194 };
195
196 public Object remove(Object key)
197 {
198 Object result = super.remove(key);
199 if (result != null)
200 {
201 m_order.remove(key);
202 }
203 return result;
204 };
205
206 public void clear()
207 {
208 super.clear();
209 m_order.clear();
210 };
211 };
212
Karl Pauls36407322008-03-07 00:37:30 +0000213 private static final ConditionInfo[] EMPTY_CONDITION_INFO = new ConditionInfo[0];
214 private static final PermissionInfo[] EMPTY_PERMISSION_INFO = new PermissionInfo[0];
Karl Pauls23287bd2010-01-10 22:11:27 +0000215 private final Map m_condPermInfos = new OrderedHashMap();
Karl Pauls36407322008-03-07 00:37:30 +0000216 private final PropertiesCache m_propertiesCache;
217 private final Permissions m_permissions;
218 private final Conditions m_conditions;
219 private final LocalPermissions m_localPermissions;
Karl Pauls23287bd2010-01-10 22:11:27 +0000220 private final PermissionAdminImpl m_pai;
Karl Pauls36407322008-03-07 00:37:30 +0000221
222 public ConditionalPermissionAdminImpl(Permissions permissions,
223 Conditions condtions, LocalPermissions localPermissions,
Karl Pauls23287bd2010-01-10 22:11:27 +0000224 PropertiesCache cache, PermissionAdminImpl pai) throws IOException
Karl Pauls36407322008-03-07 00:37:30 +0000225 {
226 m_propertiesCache = cache;
227 m_permissions = permissions;
228 m_conditions = condtions;
229 m_localPermissions = localPermissions;
Karl Pauls23287bd2010-01-10 22:11:27 +0000230 Map old = new OrderedHashMap();
Karl Pauls36407322008-03-07 00:37:30 +0000231 // Now try to restore the cache.
Karl Pauls23287bd2010-01-10 22:11:27 +0000232 m_propertiesCache.read(ConditionalPermissionInfoImpl.class, old);
233 for (Iterator iter = old.entrySet().iterator(); iter.hasNext();)
Karl Pauls36407322008-03-07 00:37:30 +0000234 {
Karl Pauls23287bd2010-01-10 22:11:27 +0000235 Entry entry = (Entry) iter.next();
236 String name = (String) entry.getKey();
237 ConditionalPermissionInfoImpl cpi = ((ConditionalPermissionInfoImpl) entry
238 .getValue());
239 m_condPermInfos.put(name, new ConditionalPermissionInfoImpl(name,
240 cpi._getConditionInfos(), cpi._getPermissionInfos(), this, cpi
241 .isAllow()));
Karl Pauls36407322008-03-07 00:37:30 +0000242 }
Karl Pauls23287bd2010-01-10 22:11:27 +0000243 m_pai = pai;
Karl Pauls36407322008-03-07 00:37:30 +0000244 }
245
246 public ConditionalPermissionInfo addConditionalPermissionInfo(
247 ConditionInfo[] conditions, PermissionInfo[] permissions)
248 {
249 Object sm = System.getSecurityManager();
250 if (sm != null)
251 {
252 ((SecurityManager) sm).checkPermission(Permissions.ALL_PERMISSION);
253 }
Karl Pauls23287bd2010-01-10 22:11:27 +0000254 ConditionalPermissionInfoImpl result = new ConditionalPermissionInfoImpl(
255 notNull(conditions), notNull(permissions), this, true);
Karl Pauls36407322008-03-07 00:37:30 +0000256
257 return write(result.getName(), result);
258 }
259
260 ConditionalPermissionInfoImpl write(String name,
261 ConditionalPermissionInfoImpl cpi)
262 {
263 synchronized (m_propertiesCache)
264 {
265 Map tmp = null;
266
267 synchronized (m_condPermInfos)
268 {
Karl Pauls23287bd2010-01-10 22:11:27 +0000269 tmp = new OrderedHashMap();
270 tmp.putAll(m_condPermInfos);
Karl Pauls36407322008-03-07 00:37:30 +0000271
272 if ((name != null) && (cpi != null))
273 {
274 m_condPermInfos.put(name, cpi);
275 }
276 else if (name != null)
277 {
278 m_condPermInfos.remove(name);
279 }
280 else
281 {
282 tmp = null;
283 }
284 }
285
286 try
287 {
288 m_propertiesCache.write(m_condPermInfos);
289 }
290 catch (IOException ex)
291 {
292 synchronized (m_condPermInfos)
293 {
Karl Pauls23287bd2010-01-10 22:11:27 +0000294 if (tmp != null)
295 {
296 m_condPermInfos.clear();
297 m_condPermInfos.putAll(tmp);
298 }
Karl Pauls36407322008-03-07 00:37:30 +0000299 }
300 ex.printStackTrace();
301 throw new IllegalStateException(ex.getMessage());
302 }
303 }
304 synchronized (m_condPermInfos)
305 {
306 return (ConditionalPermissionInfoImpl) m_condPermInfos.get(name);
307 }
308 }
309
Karl Pauls23287bd2010-01-10 22:11:27 +0000310 private static class FakeBundle implements Bundle
Karl Pauls36407322008-03-07 00:37:30 +0000311 {
Karl Pauls23287bd2010-01-10 22:11:27 +0000312 private final Map m_certs;
313
314 public FakeBundle(Map certs)
315 {
316 m_certs = Collections.unmodifiableMap(certs);
317 }
318
319 public Enumeration findEntries(String arg0, String arg1, boolean arg2)
320 {
321 return null;
322 }
323
324 public BundleContext getBundleContext()
325 {
326 return null;
327 }
328
329 public long getBundleId()
330 {
331 return -1;
332 }
333
334 public URL getEntry(String arg0)
335 {
336 return null;
337 }
338
339 public Enumeration getEntryPaths(String arg0)
340 {
341 return null;
342 }
343
344 public Dictionary getHeaders()
345 {
346 return new Hashtable();
347 }
348
349 public Dictionary getHeaders(String arg0)
350 {
351 return new Hashtable();
352 }
353
354 public long getLastModified()
355 {
356 return 0;
357 }
358
359 public String getLocation()
360 {
361 return "";
362 }
363
364 public ServiceReference[] getRegisteredServices()
365 {
366 return null;
367 }
368
369 public URL getResource(String arg0)
370 {
371 return null;
372 }
373
374 public Enumeration getResources(String arg0) throws IOException
375 {
376 return null;
377 }
378
379 public ServiceReference[] getServicesInUse()
380 {
381 return null;
382 }
383
384 public Map getSignerCertificates(int arg0)
385 {
386 return m_certs;
387 }
388
389 public int getState()
390 {
391 return Bundle.UNINSTALLED;
392 }
393
394 public String getSymbolicName()
395 {
396 return null;
397 }
398
399 public Version getVersion()
400 {
401 return Version.emptyVersion;
402 }
403
404 public boolean hasPermission(Object arg0)
405 {
406 return false;
407 }
408
409 public Class loadClass(String arg0) throws ClassNotFoundException
410 {
411 return null;
412 }
413
414 public void start() throws BundleException
415 {
416 throw new IllegalStateException();
417 }
418
419 public void start(int arg0) throws BundleException
420 {
421 throw new IllegalStateException();
422 }
423
424 public void stop() throws BundleException
425 {
426 throw new IllegalStateException();
427 }
428
429 public void stop(int arg0) throws BundleException
430 {
431 throw new IllegalStateException();
432 }
433
434 public void uninstall() throws BundleException
435 {
436 throw new IllegalStateException();
437 }
438
439 public void update() throws BundleException
440 {
441 throw new IllegalStateException();
442 }
443
444 public void update(InputStream arg0) throws BundleException
445 {
446 throw new IllegalStateException();
447 }
448
449 public boolean equals(Object o)
450 {
451 return this == o;
452 }
453
454 public int hashCode()
455 {
456 return System.identityHashCode(this);
457 }
Karl Paulsf6756bd2011-09-09 12:50:01 +0000458
459 public int compareTo(Bundle o) {
460 // TODO Auto-generated method stub
461 return 0;
462 }
463
Karl Pauls22ee38a2013-02-12 14:33:38 +0000464 public Object adapt(Class arg0) {
Karl Paulsf6756bd2011-09-09 12:50:01 +0000465 // TODO Auto-generated method stub
466 return null;
467 }
468
469 public File getDataFile(String arg0) {
470 // TODO Auto-generated method stub
471 return null;
472 }
Karl Pauls22ee38a2013-02-12 14:33:38 +0000473
474 public int compareTo(Object t)
475 {
476 throw new UnsupportedOperationException("Not supported yet.");
477 }
Karl Pauls23287bd2010-01-10 22:11:27 +0000478 }
479
480 private static class FakeCert extends X509Certificate
481 {
482 private final Principal m_principal;
483
484 public FakeCert(final String principal)
485 {
486 m_principal = new Principal()
Karl Pauls36407322008-03-07 00:37:30 +0000487 {
Karl Pauls23287bd2010-01-10 22:11:27 +0000488 public String getName()
Karl Pauls36407322008-03-07 00:37:30 +0000489 {
Karl Pauls23287bd2010-01-10 22:11:27 +0000490 return principal;
Karl Pauls36407322008-03-07 00:37:30 +0000491 }
Karl Pauls23287bd2010-01-10 22:11:27 +0000492 };
493 }
494
495 public void checkValidity()
496 throws java.security.cert.CertificateExpiredException,
497 java.security.cert.CertificateNotYetValidException
498 {
499
500 }
501
502 public void checkValidity(Date date)
503 throws java.security.cert.CertificateExpiredException,
504 java.security.cert.CertificateNotYetValidException
505 {
506 }
507
508 public int getBasicConstraints()
509 {
510 return 0;
511 }
512
513 public Principal getIssuerDN()
514 {
515 return null;
516 }
517
518 public boolean[] getIssuerUniqueID()
519 {
520 return null;
521 }
522
523 public boolean[] getKeyUsage()
524 {
525 return null;
526 }
527
528 public Date getNotAfter()
529 {
530 return null;
531 }
532
533 public Date getNotBefore()
534 {
535 return null;
536 }
537
538 public BigInteger getSerialNumber()
539 {
540 return null;
541 }
542
543 public String getSigAlgName()
544 {
545 return null;
546 }
547
548 public String getSigAlgOID()
549 {
550 return null;
551 }
552
553 public byte[] getSigAlgParams()
554 {
555 return null;
556 }
557
558 public byte[] getSignature()
559 {
560 return null;
561 }
562
563 public Principal getSubjectDN()
564 {
565 return m_principal;
566 }
567
568 public boolean[] getSubjectUniqueID()
569 {
570 return null;
571 }
572
573 public byte[] getTBSCertificate()
574 throws java.security.cert.CertificateEncodingException
575 {
576 return null;
577 }
578
579 public int getVersion()
580 {
581 return 0;
582 }
583
584 public byte[] getEncoded()
585 throws java.security.cert.CertificateEncodingException
586 {
587 return null;
588 }
589
590 public PublicKey getPublicKey()
591 {
592 return null;
593 }
594
595 public String toString()
596 {
597 return m_principal.getName();
598 }
599
600 public void verify(PublicKey key)
601 throws java.security.cert.CertificateException,
602 NoSuchAlgorithmException, InvalidKeyException,
603 NoSuchProviderException, SignatureException
604 {
605
606 }
607
608 public void verify(PublicKey key, String sigProvider)
609 throws java.security.cert.CertificateException,
610 NoSuchAlgorithmException, InvalidKeyException,
611 NoSuchProviderException, SignatureException
612 {
613
614 }
615
616 public Set getCriticalExtensionOIDs()
617 {
618 return null;
619 }
620
621 public byte[] getExtensionValue(String arg0)
622 {
623 return null;
624 }
625
626 public Set getNonCriticalExtensionOIDs()
627 {
628 return null;
629 }
630
631 public boolean hasUnsupportedCriticalExtension()
632 {
633 return false;
634 }
635
636 public boolean equals(Object o)
637 {
638 return this == o;
639 }
640
641 public int hashCode()
642 {
643 return System.identityHashCode(this);
644 }
645
646 }
647
648 public AccessControlContext getAccessControlContext(final String[] signers)
649 {
650 Map certificates = new HashMap();
651 for (int i = 0; i < signers.length; i++)
652 {
653 StringTokenizer tok = new StringTokenizer(signers[i], ";");
654 List certsList = new ArrayList();
655 while (tok.hasMoreTokens())
656 {
657 certsList.add(tok.nextToken());
658 }
659 String[] certs = (String[]) certsList.toArray(new String[certsList
660 .size()]);
661
662 X509Certificate key = new FakeCert(certs[0]);
663 List certList = new ArrayList();
664 certificates.put(key, certList);
665 certList.add(key);
666 for (int j = 1; j < certs.length; j++)
667 {
668 certList.add(new FakeCert(certs[j]));
669 }
670 }
671 final Bundle fake = new FakeBundle(certificates);
672 ProtectionDomain domain = new ProtectionDomain(null, null)
673 {
674 public boolean implies(Permission permission)
675 {
676 List posts = new ArrayList();
677 Boolean result = m_pai.hasPermission("", fake, permission,
678 ConditionalPermissionAdminImpl.this, this, null);
679 if (result != null)
680 {
681 return result.booleanValue();
682 }
Karl Paulsf6756bd2011-09-09 12:50:01 +0000683 if (eval(posts, new BundleRevisionImpl(fake, Long.toString(fake.getBundleId())), permission, m_pai))
Karl Pauls23287bd2010-01-10 22:11:27 +0000684 {
685 if (!posts.isEmpty())
686 {
687 return m_conditions.evalRecursive(posts);
688 }
689 return true;
690 }
691 return false;
692 }
693 };
694 return new AccessControlContext(new ProtectionDomain[] { domain });
Karl Pauls36407322008-03-07 00:37:30 +0000695 }
696
697 public ConditionalPermissionInfo getConditionalPermissionInfo(String name)
698 {
699 if (name == null)
700 {
701 throw new IllegalArgumentException("Name may not be null");
702 }
703 ConditionalPermissionInfoImpl result = null;
704
705 synchronized (m_condPermInfos)
706 {
707 result = (ConditionalPermissionInfoImpl) m_condPermInfos.get(name);
708 }
709
710 if (result == null)
711 {
Karl Pauls23287bd2010-01-10 22:11:27 +0000712 result = new ConditionalPermissionInfoImpl(this, name, true);
Karl Pauls36407322008-03-07 00:37:30 +0000713
714 result = write(result.getName(), result);
715 }
716
717 return result;
718 }
719
720 public Enumeration getConditionalPermissionInfos()
721 {
722 synchronized (m_condPermInfos)
723 {
Karl Paulse2913e62010-12-22 18:29:22 +0000724 return Collections.enumeration(new ArrayList(m_condPermInfos
725 .values()));
Karl Pauls36407322008-03-07 00:37:30 +0000726 }
727 }
728
729 public ConditionalPermissionInfo setConditionalPermissionInfo(String name,
730 ConditionInfo[] conditions, PermissionInfo[] permissions)
731 {
732 Object sm = System.getSecurityManager();
733 if (sm != null)
734 {
735 ((SecurityManager) sm).checkPermission(Permissions.ALL_PERMISSION);
736 }
737
738 ConditionalPermissionInfoImpl result = null;
739 conditions = notNull(conditions);
740 permissions = notNull(permissions);
741
742 if (name != null)
743 {
744 synchronized (m_condPermInfos)
745 {
Karl Pauls23287bd2010-01-10 22:11:27 +0000746 result = (ConditionalPermissionInfoImpl) m_condPermInfos
747 .get(name);
Karl Pauls36407322008-03-07 00:37:30 +0000748
749 if (result == null)
750 {
Karl Pauls23287bd2010-01-10 22:11:27 +0000751 result = new ConditionalPermissionInfoImpl(name,
752 conditions, permissions, this, true);
Karl Pauls36407322008-03-07 00:37:30 +0000753 }
754 else
755 {
756 result.setConditionsAndPermissions(conditions, permissions);
757 }
758 }
759 }
760 else
761 {
Karl Pauls23287bd2010-01-10 22:11:27 +0000762 result = new ConditionalPermissionInfoImpl(conditions, permissions,
763 this, true);
Karl Pauls36407322008-03-07 00:37:30 +0000764 }
765
766 return write(result.getName(), result);
767 }
768
769 private PermissionInfo[] notNull(PermissionInfo[] permissions)
770 {
771 if (permissions == null)
772 {
773 return ConditionalPermissionInfoImpl.PERMISSION_INFO;
774 }
775 return (PermissionInfo[]) notNull((Object[]) permissions).toArray(
776 EMPTY_PERMISSION_INFO);
777 }
778
779 private ConditionInfo[] notNull(ConditionInfo[] conditions)
780 {
781 if (conditions == null)
782 {
783 return ConditionalPermissionInfoImpl.CONDITION_INFO;
784 }
785 return (ConditionInfo[]) notNull((Object[]) conditions).toArray(
786 EMPTY_CONDITION_INFO);
787 }
788
789 private List notNull(Object[] elements)
790 {
791 List result = new ArrayList();
792
793 for (int i = 0; i < elements.length; i++)
794 {
795 if (elements[i] != null)
796 {
797 result.add(elements[i]);
798 }
799 }
800
801 return result;
802 }
803
804 // The thread local stack used to keep track of bundle protection domains we
805 // still expect to see.
806 private final ThreadLocal m_stack = new ThreadLocal();
807
808 /**
809 * This method does the actual permission check. If it is not a direct check
Karl Pauls23287bd2010-01-10 22:11:27 +0000810 * it will try to determine the other bundle domains that will follow
811 * automatically in case this is the first check in one permission check. If
812 * not then it will keep track of which domains we have already see. While
813 * it keeps track it builds up a list of postponed tuples which it will
814 * evaluate at the last domain. See the core spec 9.5.1 and following for a
815 * general description.
Karl Pauls22ee38a2013-02-12 14:33:38 +0000816 *
Karl Pauls23287bd2010-01-10 22:11:27 +0000817 * @param felixBundle
818 * the bundle in question.
819 * @param loader
820 * the content loader of the bundle to get access to the jar to
821 * check for local permissions.
822 * @param root
823 * the bundle id.
824 * @param signers
825 * the signers (this is to support the ACC based on signers)
826 * @param pd
827 * the bundle protection domain
828 * @param permission
829 * the permission currently checked
830 * @param direct
831 * whether this is a direct check or not. direct check will not
832 * expect any further bundle domains on the stack
833 * @return true in case the permission is granted or there are postponed
834 * tuples false if not. Again, see the spec for more explanations.
Karl Pauls36407322008-03-07 00:37:30 +0000835 */
Karl Paulsf6756bd2011-09-09 12:50:01 +0000836 public boolean hasPermission(BundleRevisionImpl module, Content content,
Karl Pauls23287bd2010-01-10 22:11:27 +0000837 ProtectionDomain pd, Permission permission, boolean direct, Object admin)
Karl Pauls36407322008-03-07 00:37:30 +0000838 {
839 // System.out.println(felixBundle + "-" + permission);
840 List domains = null;
841 List tuples = null;
842 Object[] entry = null;
Karl Pauls23287bd2010-01-10 22:11:27 +0000843 // first see whether this is the normal case (the special case is for
Karl Pauls36407322008-03-07 00:37:30 +0000844 // the ACC based on signers).
Karl Pauls23287bd2010-01-10 22:11:27 +0000845 // In case of a direct call we don't need to look for other pds
846 if (direct)
Karl Pauls36407322008-03-07 00:37:30 +0000847 {
Karl Pauls23287bd2010-01-10 22:11:27 +0000848 domains = new ArrayList();
849 tuples = new ArrayList();
850 domains.add(pd);
851 }
852 else
853 {
854 // Get the other pds from the stck
855 entry = (Object[]) m_stack.get();
856
857 // if there are none then get them from the gripper
858 if (entry == null)
Karl Pauls36407322008-03-07 00:37:30 +0000859 {
Karl Pauls23287bd2010-01-10 22:11:27 +0000860 entry = new Object[] { new ArrayList(DomainGripper.grab()),
861 new ArrayList() };
Karl Pauls36407322008-03-07 00:37:30 +0000862 }
863 else
864 {
Karl Pauls23287bd2010-01-10 22:11:27 +0000865 m_stack.set(null);
866 }
Karl Pauls36407322008-03-07 00:37:30 +0000867
Karl Pauls23287bd2010-01-10 22:11:27 +0000868 domains = (List) entry[0];
869 tuples = (List) entry[1];
870 if (!domains.contains(pd))
871 {
872 // We have been called directly without the direct flag
873 domains.clear();
874 domains.add(pd);
Karl Pauls36407322008-03-07 00:37:30 +0000875 }
876 }
877
878 // check the local permissions. they need to all the permission if there
879 // are any
Karl Pauls23287bd2010-01-10 22:11:27 +0000880 if (!impliesLocal(module.getBundle(), content, permission))
Karl Pauls36407322008-03-07 00:37:30 +0000881 {
882 return false;
883 }
884
885 List posts = new ArrayList();
886
Karl Pauls23287bd2010-01-10 22:11:27 +0000887 boolean result = eval(posts, module, permission, admin);
Karl Pauls36407322008-03-07 00:37:30 +0000888
889 domains.remove(pd);
890
891 // We postponed tuples
892 if (!posts.isEmpty())
893 {
894 tuples.add(posts);
895 }
896
897 // Are we at the end or this was a direct call?
898 if (domains.isEmpty())
899 {
900 m_stack.set(null);
Karl Pauls23287bd2010-01-10 22:11:27 +0000901 // Now eval the postponed tupels. if the previous eval did return
902 // false
Karl Pauls36407322008-03-07 00:37:30 +0000903 // tuples will be empty so we don't return from here.
904 if (!tuples.isEmpty())
905 {
906 return m_conditions.evalRecursive(tuples);
907 }
908 }
909 else
910 {
Karl Pauls23287bd2010-01-10 22:11:27 +0000911 // this is to support recursive permission checks. In case we
912 // trigger
Karl Pauls36407322008-03-07 00:37:30 +0000913 // a permission check while eval the stack is null until this point
914 m_stack.set(entry);
915 }
916
917 return result;
918 }
919
Karl Paulsfbb32572010-05-30 22:16:56 +0000920 public boolean impliesLocal(Bundle felixBundle, Content content,
Karl Pauls23287bd2010-01-10 22:11:27 +0000921 Permission permission)
922 {
923 return m_localPermissions.implies(content, felixBundle, permission);
924 }
925
Karl Pauls35c1c342008-03-19 17:39:16 +0000926 public boolean isEmpty()
927 {
928 synchronized (m_condPermInfos)
929 {
930 return m_condPermInfos.isEmpty();
931 }
932 }
933
Karl Pauls36407322008-03-07 00:37:30 +0000934 // we need to find all conditions that apply and then check whether they
935 // de note the permission in question unless the conditions are postponed
936 // then we make sure their permissions imply the permission and add them
937 // to the list of posts. Return true in case we pass or have posts
938 // else falls and clear the posts first.
Karl Paulsf6756bd2011-09-09 12:50:01 +0000939 private boolean eval(List posts, BundleRevisionImpl module, Permission permission,
Karl Pauls23287bd2010-01-10 22:11:27 +0000940 Object admin)
Karl Pauls36407322008-03-07 00:37:30 +0000941 {
942 List condPermInfos = null;
943
944 synchronized (m_condPermInfos)
945 {
Karl Pauls35c1c342008-03-19 17:39:16 +0000946 if (isEmpty() && (admin == null))
Karl Pauls36407322008-03-07 00:37:30 +0000947 {
948 return true;
949 }
950 condPermInfos = new ArrayList(m_condPermInfos.values());
951 }
952
953 // Check for implicit permissions like access to file area
Karl Pauls23287bd2010-01-10 22:11:27 +0000954 if (m_permissions.getPermissions(
955 m_permissions.getImplicit(module.getBundle())).implies(permission,
956 module.getBundle()))
Karl Pauls36407322008-03-07 00:37:30 +0000957 {
958 return true;
959 }
Karl Pauls23287bd2010-01-10 22:11:27 +0000960 List pls = new ArrayList();
Karl Pauls36407322008-03-07 00:37:30 +0000961 // now do the real thing
962 for (Iterator iter = condPermInfos.iterator(); iter.hasNext();)
963 {
Karl Pauls23287bd2010-01-10 22:11:27 +0000964 ConditionalPermissionInfoImpl cpi = (ConditionalPermissionInfoImpl) iter
965 .next();
Karl Pauls36407322008-03-07 00:37:30 +0000966
967 ConditionInfo[] conditions = cpi._getConditionInfos();
968
969 List currentPosts = new ArrayList();
970
Karl Pauls23287bd2010-01-10 22:11:27 +0000971 Conditions conds = m_conditions.getConditions(module, conditions);
972 if (!conds.isSatisfied(currentPosts, m_permissions
973 .getPermissions(cpi._getPermissionInfos()), permission))
Karl Pauls36407322008-03-07 00:37:30 +0000974 {
975 continue;
976 }
977
978 if (!m_permissions.getPermissions(cpi._getPermissionInfos())
979 .implies(permission, null))
980 {
981 continue;
982 }
983
984 if (currentPosts.isEmpty())
985 {
Karl Pauls23287bd2010-01-10 22:11:27 +0000986 pls.add(new Object[] { cpi, null });
987 break;
988 }
989 pls.add(new Object[] { cpi, currentPosts, conds });
990 }
991 while (pls.size() > 1)
992 {
993 if (!((ConditionalPermissionInfoImpl) ((Object[]) pls.get(pls
994 .size() - 1))[0]).isAllow())
995 {
996 pls.remove(pls.size() - 1);
997 }
998 else
999 {
1000 break;
1001 }
1002 }
1003 if (pls.size() == 1)
1004 {
1005 if (((Object[]) pls.get(0))[1] != null)
1006 {
1007 posts.add(pls.get(0));
1008 }
1009 return ((ConditionalPermissionInfoImpl) ((Object[]) pls.get(0))[0])
1010 .isAllow();
1011 }
1012 for (Iterator iter = pls.iterator(); iter.hasNext();)
1013 {
1014 posts.add(iter.next());
1015 }
1016 return !posts.isEmpty();
1017 }
1018
1019 public ConditionalPermissionInfo newConditionalPermissionInfo(
1020 String encodedConditionalPermissionInfo)
1021 {
1022 return new ConditionalPermissionInfoImpl(
1023 encodedConditionalPermissionInfo);
1024 }
1025
1026 public ConditionalPermissionInfo newConditionalPermissionInfo(String name,
1027 ConditionInfo[] conditions, PermissionInfo[] permissions, String access)
1028 {
1029 return new ConditionalPermissionInfoImpl(name, conditions, permissions,
1030 ConditionalPermissionAdminImpl.this, access
1031 .equals(ConditionalPermissionInfo.ALLOW));
1032 }
1033
1034 public ConditionalPermissionUpdate newConditionalPermissionUpdate()
1035 {
1036 return new ConditionalPermissionUpdate()
1037 {
1038 List current = null;
1039 List out = null;
1040 {
1041 synchronized (m_condPermInfos)
1042 {
1043 current = new ArrayList(m_condPermInfos.values());
1044 out = new ArrayList(m_condPermInfos.values());
1045 }
1046 }
1047
1048 public boolean commit()
1049 {
1050 synchronized (m_condPermInfos)
1051 {
1052 if (current.equals(new ArrayList(m_condPermInfos.values())))
1053 {
1054 m_condPermInfos.clear();
1055 write(null, null);
1056 for (Iterator iter = out.iterator(); iter.hasNext();)
1057 {
1058 ConditionalPermissionInfoImpl cpii = (ConditionalPermissionInfoImpl) iter
1059 .next();
1060 write(cpii.getName(), cpii);
1061 }
1062 }
1063 else
1064 {
1065 return false;
1066 }
1067 }
Karl Pauls36407322008-03-07 00:37:30 +00001068 return true;
1069 }
1070
Karl Pauls23287bd2010-01-10 22:11:27 +00001071 public List getConditionalPermissionInfos()
1072 {
1073 return out;
1074 }
1075 };
1076 }
1077
1078 public boolean handlePAHandle(BundleProtectionDomain pd)
1079 {
1080 Object[] entry = (Object[]) m_stack.get();
1081
1082 if (entry == null)
1083 {
1084 entry = new Object[] { new ArrayList(DomainGripper.grab()),
1085 new ArrayList() };
Karl Pauls36407322008-03-07 00:37:30 +00001086 }
1087
Karl Pauls23287bd2010-01-10 22:11:27 +00001088 ((List) entry[0]).remove(pd);
1089 if (((List) entry[0]).isEmpty())
1090 {
1091 m_stack.set(null);
1092 if (!((List) entry[1]).isEmpty())
1093 {
1094 return m_conditions.evalRecursive(((List) entry[1]));
1095 }
1096 }
1097 else
1098 {
1099 m_stack.set(entry);
1100 }
1101
1102 return true;
1103 }
1104
1105 public void clearPD()
1106 {
1107 m_stack.set(null);
Karl Pauls36407322008-03-07 00:37:30 +00001108 }
1109}