blob: 788fbcde691a492d75cab298a10e3992548a6d77 [file] [log] [blame]
Changhoon Yoon23dee8f2015-05-18 22:19:49 +09001/*
2 * Copyright 2015 Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Changhoon Yoon541ef712015-05-23 17:18:34 +090017package org.onosproject.security;
18
Changhoon Yoone71dfa42015-12-04 21:49:25 +090019import java.security.AccessController;
20import java.security.AccessControlContext;
21import java.security.PrivilegedAction;
22import java.security.ProtectionDomain;
Changhoon Yoon23dee8f2015-05-18 22:19:49 +090023
Thomas Vachuska4c571ae2015-09-10 16:31:59 -070024import com.google.common.annotations.Beta;
Changhoon Yoone71dfa42015-12-04 21:49:25 +090025import com.google.common.cache.Cache;
26import com.google.common.cache.CacheBuilder;
27
28import java.lang.reflect.Field;
29import java.util.concurrent.ExecutionException;
30import java.util.concurrent.TimeUnit;
Thomas Vachuska4c571ae2015-09-10 16:31:59 -070031
Changhoon Yoon23dee8f2015-05-18 22:19:49 +090032/**
Changhoon Yoon541ef712015-05-23 17:18:34 +090033 * Aids SM-ONOS to perform API-level permission checking.
Changhoon Yoon23dee8f2015-05-18 22:19:49 +090034 */
Thomas Vachuska4c571ae2015-09-10 16:31:59 -070035@Beta
Changhoon Yoon23dee8f2015-05-18 22:19:49 +090036public final class AppGuard {
Changhoon Yoon23dee8f2015-05-18 22:19:49 +090037 private AppGuard() {
38 }
39
Changhoon Yoon541ef712015-05-23 17:18:34 +090040 /**
41 * Checks if the caller has the required permission only when security-mode is enabled.
Changhoon Yoone71dfa42015-12-04 21:49:25 +090042 *
Changhoon Yoon541ef712015-05-23 17:18:34 +090043 * @param permission permission to be checked
44 */
Changhoon Yoonb856b812015-08-10 03:47:19 +090045 public static void checkPermission(AppPermission.Type permission) {
Changhoon Yoone71dfa42015-12-04 21:49:25 +090046
Changhoon Yoon23dee8f2015-05-18 22:19:49 +090047 SecurityManager sm = System.getSecurityManager();
Changhoon Yoone71dfa42015-12-04 21:49:25 +090048 if (sm == null) {
49 return;
50 }
51
52 Object result = AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
53 int contextHash = 0;
54 AccessControlContext context = AccessController.getContext();
55 Field f = null;
56 try {
57 f = context.getClass().getDeclaredField("context");
58
59 f.setAccessible(true);
60 ProtectionDomain[] domain = (ProtectionDomain[]) f.get(context);
61 for (ProtectionDomain pd : domain) {
62 if (pd.getCodeSource() != null) {
63 contextHash = contextHash ^ pd.getCodeSource().getLocation().hashCode();
64 } else {
65 return null;
66 }
67 }
68 return contextHash;
69 } catch (NoSuchFieldException e) {
70 return null;
71 } catch (IllegalAccessException e) {
72 return null;
73 }
74 });
75
76 if (result == null) {
77 sm.checkPermission(new AppPermission(permission));
78 } else {
79 AppPermission perm = new AppPermission(permission);
80 int hash = ((int) result) ^ perm.hashCode();
81 PermissionCheckCache.getInstance().checkCache(hash, perm);
Changhoon Yoon23dee8f2015-05-18 22:19:49 +090082 }
Changhoon Yoon23dee8f2015-05-18 22:19:49 +090083 }
Changhoon Yoone71dfa42015-12-04 21:49:25 +090084
85
86 private static final class PermissionCheckCache {
87
88 private static final Cache<Integer, Boolean> CACHE = CacheBuilder.newBuilder()
89 .maximumSize(1000)
90 .expireAfterAccess(10, TimeUnit.MINUTES)
91 .build();
92
93 private PermissionCheckCache() {
94 }
95
96 private static class SingletonHelper {
97 private static final PermissionCheckCache INSTANCE = new PermissionCheckCache();
98 }
99
100 public static PermissionCheckCache getInstance() {
101 return SingletonHelper.INSTANCE;
102 }
103
104 public static void checkCache(int key, AppPermission perm) {
105 try {
106 CACHE.get(key, () -> {
107 System.getSecurityManager().checkPermission(perm);
108 return true;
109 });
110 } catch (ExecutionException e) {
111 System.getSecurityManager().checkPermission(perm);
112 }
113 }
114 }
115
Changhoon Yoon23dee8f2015-05-18 22:19:49 +0900116}
Changhoon Yoone71dfa42015-12-04 21:49:25 +0900117