/* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * under the License. */ package org.apache.karaf.util.jaas; import java.security.AccessControlContext; import java.security.AccessController; import java.security.Permission; import java.security.Principal; import java.security.PrivilegedAction; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; import java.security.ProtectionDomain; import java.util.Set; import javax.security.auth.Subject; import javax.security.auth.SubjectDomainCombiner; import org.apache.karaf.jaas.boot.principal.RolePrincipal; public class JaasHelper { private static final String ROLE_WILDCARD = "*"; public static boolean currentUserHasRole(String requestedRole) { if (ROLE_WILDCARD.equals(requestedRole)) { return true; } AccessControlContext acc = AccessController.getContext(); if (acc == null) { return false; } Subject subject = Subject.getSubject(acc); if (subject == null) { return false; } return currentUserHasRole(subject.getPrincipals(), requestedRole); } public static boolean currentUserHasRole(Set<Principal> principals, String requestedRole) { if (ROLE_WILDCARD.equals(requestedRole)) { return true; } String clazz; String role; int index = requestedRole.indexOf(':'); if (index > 0) { clazz = requestedRole.substring(0, index); role = requestedRole.substring(index + 1); } else { clazz = RolePrincipal.class.getName(); role = requestedRole; } for (Principal p : principals) { if (clazz.equals(p.getClass().getName()) && role.equals(p.getName())) { return true; } } return false; } public static void runAs(final Subject subject, final Runnable action) { if (action == null) { throw new NullPointerException(); } doAs(subject, (PrivilegedAction<Object>)(() -> { action.run(); return null; } )); } public static <T> T doAs(final Subject subject, final PrivilegedAction<T> action) { if (action == null) { throw new NullPointerException(); } // set up the new Subject-based AccessControlContext for doPrivileged final AccessControlContext currentAcc = AccessController.getContext(); final AccessControlContext newAcc = AccessController.doPrivileged (new PrivilegedAction<AccessControlContext>() { public AccessControlContext run() { if (subject == null) return new AccessControlContext(currentAcc, null); else return new AccessControlContext(currentAcc, new OsgiSubjectDomainCombiner(subject)); } }); // call doPrivileged and push this new context on the stack return AccessController.doPrivileged(action, newAcc); } public static <T> T doAs(final Subject subject, final PrivilegedExceptionAction<T> action) throws PrivilegedActionException { if (action == null) { throw new NullPointerException(); } // set up the new Subject-based AccessControlContext for doPrivileged final AccessControlContext currentAcc = AccessController.getContext(); final AccessControlContext newAcc = AccessController.doPrivileged (new PrivilegedAction<AccessControlContext>() { public AccessControlContext run() { if (subject == null) return new AccessControlContext(currentAcc, null); else return new AccessControlContext(currentAcc, new OsgiSubjectDomainCombiner(subject)); } }); // call doPrivileged and push this new context on the stack return AccessController.doPrivileged(action, newAcc); } public static class OsgiSubjectDomainCombiner extends SubjectDomainCombiner { private final Subject subject; public OsgiSubjectDomainCombiner(Subject subject) { super(subject); this.subject = subject; } public ProtectionDomain[] combine(ProtectionDomain[] currentDomains, ProtectionDomain[] assignedDomains) { int cLen = (currentDomains == null ? 0 : currentDomains.length); int aLen = (assignedDomains == null ? 0 : assignedDomains.length); ProtectionDomain[] newDomains = new ProtectionDomain[cLen + aLen]; Principal[] principals = subject.getPrincipals().toArray(new Principal[0]); for (int i = 0; i < cLen; i++) { newDomains[i] = new DelegatingProtectionDomain(currentDomains[i], principals); } for (int i = 0; i < aLen; i++) { newDomains[cLen + i] = assignedDomains[i]; } newDomains = optimize(newDomains); return newDomains; } private ProtectionDomain[] optimize(ProtectionDomain[] domains) { if (domains == null || domains.length == 0) { return null; } ProtectionDomain[] optimized = new ProtectionDomain[domains.length]; ProtectionDomain pd; int num = 0; for (int i = 0; i < domains.length; i++) { if ((pd = domains[i]) != null) { boolean found = false; for (int j = 0; j < num && !found; j++) { found = (optimized[j] == pd); } if (!found) { optimized[num++] = pd; } } } if (num > 0 && num < domains.length) { ProtectionDomain[] downSize = new ProtectionDomain[num]; System.arraycopy(optimized, 0, downSize, 0, downSize.length); optimized = downSize; } return ((num == 0 || optimized.length == 0) ? null : optimized); } } public static class DelegatingProtectionDomain extends ProtectionDomain { private final ProtectionDomain delegate; DelegatingProtectionDomain(ProtectionDomain delegate, Principal[] principals) { super(delegate.getCodeSource(), delegate.getPermissions(), delegate.getClassLoader(), principals); this.delegate = delegate; } @Override public boolean implies(Permission permission) { return delegate.implies(permission); } } }