001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package java.lang;
019:
020: import java.io.File;
021: import java.io.FileDescriptor;
022: import java.io.FilePermission;
023: import java.lang.reflect.Constructor;
024: import java.lang.reflect.InvocationTargetException;
025: import java.lang.reflect.Member;
026: import java.net.InetAddress;
027: import java.net.SocketPermission;
028: import java.security.AccessControlContext;
029: import java.security.AccessController;
030: import java.security.AllPermission;
031: import java.security.Permission;
032: import java.security.Security;
033: import java.security.SecurityPermission;
034: import java.util.PropertyPermission;
035: import java.util.StringTokenizer;
036:
037: import org.apache.harmony.luni.util.PriviAction;
038:
039: /**
040: * SecurityManager is the abstract superclass of the classes which can provide
041: * security verification for a running program.
042: */
043: public class SecurityManager {
044:
045: private static final PropertyPermission READ_WRITE_ALL_PROPERTIES_PERMISSION = new PropertyPermission(
046: "*", "read,write"); //$NON-NLS-1$ //$NON-NLS-2$
047:
048: private static final String PKG_ACC_KEY = "package.access"; //$NON-NLS-1$
049:
050: private static final String PKG_DEF_KEY = "package.definition"; //$NON-NLS-1$
051:
052: /**
053: * Flag to indicate whether a security check is in progress.
054: *
055: * @deprecated Use checkPermission
056: */
057: @Deprecated
058: protected boolean inCheck;
059:
060: /**
061: * Constructs a new instance of this class.
062: */
063: public SecurityManager() {
064: SecurityManager security = System.getSecurityManager();
065: if (security != null) {
066: security
067: .checkPermission(RuntimePermission.permissionToCreateSecurityManager);
068: }
069: Class<?> type = Security.class; // initialize Security properties
070: if (type == null) {
071: throw new AssertionError();
072: }
073: }
074:
075: /**
076: * Checks whether the running program is allowed to accept socket
077: * connections.
078: *
079: * @param host
080: * the address of the host which is attempting to connect
081: * @param port
082: * the port number to check
083: */
084: public void checkAccept(String host, int port) {
085: if (host == null) {
086: throw new NullPointerException();
087: }
088: checkPermission(new SocketPermission(host + ':' + port,
089: "accept")); //$NON-NLS-1$
090: }
091:
092: /**
093: * Checks whether the running program is allowed to modify the thread.
094: *
095: * @param thread
096: * the thread we are attempting to modify
097: */
098: public void checkAccess(Thread thread) {
099: // Only worry about system threads. Dead threads have a null group.
100: ThreadGroup group = thread.getThreadGroup();
101: if ((group != null) && (group.parent == null)) {
102: checkPermission(RuntimePermission.permissionToModifyThread);
103: }
104: }
105:
106: /**
107: * Checks whether the running program is allowed to modify the thread group.
108: *
109: *
110: * @param group
111: * the thread group we are attempting to modify
112: */
113: public void checkAccess(ThreadGroup group) {
114: // Only worry about system threads.
115: if (group == null) {
116: throw new NullPointerException();
117: }
118: if (group.parent == null) {
119: checkPermission(RuntimePermission.permissionToModifyThreadGroup);
120: }
121: }
122:
123: /**
124: * Checks whether the running program is allowed to establish socket
125: * connections. A -1 port indicates the caller is trying to resolve the
126: * hostname.
127: *
128: * @param host
129: * String the address of the host to connect to.
130: * @param port
131: * int the port number to check, or -1 for resolve.
132: */
133: public void checkConnect(String host, int port) {
134: if (host == null) {
135: throw new NullPointerException();
136: }
137: if (port > 0) {
138: checkPermission(new SocketPermission(host + ':' + port,
139: "connect")); //$NON-NLS-1$
140: } else {
141: checkPermission(new SocketPermission(host, "resolve")); //$NON-NLS-1$
142: }
143: }
144:
145: /**
146: * Checks whether the given security context is allowed to establish socket
147: * connections. A -1 port indicates the caller is trying to resolve the
148: * hostname.
149: *
150: * @param host
151: * String the address of the host to connect to.
152: * @param port
153: * int the port number to check, or -1 for resolve.
154: * @param context
155: * Object the security context to use for the check.
156: */
157: public void checkConnect(String host, int port, Object context) {
158: if (port > 0) {
159: checkPermission(new SocketPermission(host + ':' + port,
160: "connect"), //$NON-NLS-1$
161: context);
162: } else {
163: checkPermission(
164: new SocketPermission(host, "resolve"), context); //$NON-NLS-1$
165: }
166: }
167:
168: /**
169: * Checks whether the running program is allowed to create a class loader.
170: */
171: public void checkCreateClassLoader() {
172: checkPermission(RuntimePermission.permissionToCreateClassLoader);
173: }
174:
175: /**
176: * Checks whether the running program is allowed to delete the file named by
177: * the argument, which should be passed in canonical form.
178: *
179: * @param file
180: * the name of the file to check
181: */
182: public void checkDelete(String file) {
183: checkPermission(new FilePermission(file, "delete")); //$NON-NLS-1$
184: }
185:
186: /**
187: * Checks whether the running program is allowed to execute the specified
188: * platform specific command.
189: *
190: * @param cmd
191: * the command line
192: */
193: public void checkExec(String cmd) {
194: checkPermission(new FilePermission(
195: new File(cmd).isAbsolute() ? cmd : "<<ALL FILES>>", "execute")); //$NON-NLS-1$ //$NON-NLS-2$
196: }
197:
198: /**
199: * Checks whether the running program is allowed to terminate itself.
200: *
201: * @param status
202: * the status to return from the exit.
203: */
204: public void checkExit(int status) {
205: checkPermission(RuntimePermission.permissionToExitVM);
206: }
207:
208: /**
209: * Checks whether the running program is allowed to load the specified
210: * native library.
211: *
212: * @param libName
213: * the name of the library to load
214: */
215: public void checkLink(String libName) {
216: if (libName == null) {
217: throw new NullPointerException();
218: }
219: checkPermission(new RuntimePermission("loadLibrary." + libName)); //$NON-NLS-1$
220: }
221:
222: /**
223: * Checks whether the running program is allowed to listen on the specified
224: * port.
225: *
226: * @param port
227: * int the port number to check
228: */
229: public void checkListen(int port) {
230: if (port == 0) {
231: checkPermission(new SocketPermission(
232: "localhost:1024-", "listen")); //$NON-NLS-1$ //$NON-NLS-2$
233: } else {
234: checkPermission(new SocketPermission(
235: "localhost:" + port, "listen")); //$NON-NLS-1$//$NON-NLS-2$
236: }
237: }
238:
239: /**
240: * Checks whether the running program is allowed to access members. The
241: * default is to allow access to public members (i.e.
242: * java.lang.reflect.PUBLIC) and to classes loaded by the same loader as the
243: * original caller (i.e. the method that called the reflect API).
244: *
245: * Due to the nature of the check, overriding implementations cannot call
246: * super.checkMemberAccess() since the stack would no longer be of the
247: * expected shape.
248: *
249: * @param cls ?
250: * @param type
251: * Either java.lang.reflect.Member.PUBLIC or DECLARED
252: */
253: public void checkMemberAccess(Class<?> cls, int type) {
254: if (cls == null) {
255: throw new NullPointerException();
256: }
257: if (type == Member.PUBLIC) {
258: return;
259: }
260: //
261: // Need to compare the classloaders.
262: // Stack shape is
263: // <user code> <- want this class
264: // Class.getDeclared*();
265: // Class.checkMemberAccess();
266: // SecurityManager.checkMemberAccess(); <- current frame
267: //
268: // Use getClassLoaderImpl() since getClassLoader()
269: // returns null for the bootstrap class loader.
270: if (ClassLoader.getStackClassLoader(3) == cls
271: .getClassLoaderImpl()) {
272: return;
273: }
274:
275: // Forward off to the permission mechanism.
276: checkPermission(new RuntimePermission("accessDeclaredMembers")); //$NON-NLS-1$
277: }
278:
279: /**
280: * Checks whether the running program is allowed to join, leave or send to a
281: * multicast address.
282: */
283: public void checkMulticast(InetAddress maddr) {
284: checkPermission(new SocketPermission(maddr.getHostAddress(),
285: "accept,connect")); //$NON-NLS-1$
286: }
287:
288: /**
289: * Checks whether the running program is allowed to join, leave or send to a
290: * multicast address.
291: *
292: * @deprecated use SecurityManager#checkMulticast(java.net.InetAddress)
293: */
294: @Deprecated
295: public void checkMulticast(InetAddress maddr, byte ttl) {
296: checkPermission(new SocketPermission(maddr.getHostAddress(),
297: "accept,connect")); //$NON-NLS-1$
298: }
299:
300: /**
301: * Checks whether the running program is allowed to access the specified
302: * package.
303: *
304: * @param packageName
305: * the name of the package to be accessed.
306: */
307: public void checkPackageAccess(String packageName) {
308: if (packageName == null) {
309: throw new NullPointerException();
310: }
311: if (checkPackageProperty(PKG_ACC_KEY, packageName)) {
312: checkPermission(new RuntimePermission(
313: "accessClassInPackage." //$NON-NLS-1$
314: + packageName));
315: }
316: }
317:
318: /**
319: * Checks whether the running program is allowed to define new classes in
320: * the specified package.
321: *
322: * @param packageName
323: * the name of the package to add a class to.
324: */
325: public void checkPackageDefinition(String packageName) {
326: if (packageName == null) {
327: throw new NullPointerException();
328: }
329: if (checkPackageProperty(PKG_DEF_KEY, packageName)) {
330: checkPermission(new RuntimePermission(
331: "defineClassInPackage." //$NON-NLS-1$
332: + packageName));
333: }
334: }
335:
336: /**
337: * Returns true if the package name is restricted by the specified security
338: * property.
339: */
340: private static boolean checkPackageProperty(final String property,
341: final String pkg) {
342: String list = AccessController.doPrivileged(PriviAction
343: .getSecurityProperty(property));
344: if (list != null) {
345: int plen = pkg.length();
346: StringTokenizer tokenizer = new StringTokenizer(list, ", "); //$NON-NLS-1$
347: while (tokenizer.hasMoreTokens()) {
348: String token = tokenizer.nextToken();
349: int tlen = token.length();
350: if (plen > tlen
351: && pkg.startsWith(token)
352: && (token.charAt(tlen - 1) == '.' || pkg
353: .charAt(tlen) == '.')) {
354: return true;
355: } else if (plen == tlen && token.startsWith(pkg)) {
356: return true;
357: } else if (plen + 1 == tlen && token.startsWith(pkg)
358: && token.charAt(tlen - 1) == '.') {
359: return true;
360: }
361: }
362: }
363:
364: return false;
365: }
366:
367: /**
368: * Checks whether the running program is allowed to access the system
369: * properties.
370: */
371: public void checkPropertiesAccess() {
372: checkPermission(READ_WRITE_ALL_PROPERTIES_PERMISSION);
373: }
374:
375: /**
376: * Checks whether the running program is allowed to access a particular
377: * system property.
378: *
379: * @param key
380: * the name of the property to be accessed.
381: */
382: public void checkPropertyAccess(String key) {
383: checkPermission(new PropertyPermission(key, "read")); //$NON-NLS-1$
384: }
385:
386: /**
387: * Checks whether the running program is allowed to read from the file whose
388: * descriptor is the argument.
389: *
390: * @param fd
391: * the file descriptor of the file to check
392: */
393: public void checkRead(FileDescriptor fd) {
394: if (fd == null) {
395: throw new NullPointerException();
396: }
397: checkPermission(RuntimePermission.permissionToReadFileDescriptor);
398: }
399:
400: /**
401: * Checks whether the running program is allowed to read from the file named
402: * by the argument, which should be passed in canonical form.
403: *
404: * @param file
405: * String the name of the file or directory to check.
406: */
407: public void checkRead(String file) {
408: checkPermission(new FilePermission(file, "read")); //$NON-NLS-1$
409: }
410:
411: /**
412: * Checks whether the given security context is allowed to read from the
413: * file named by the argument, which should be passed in canonical form.
414: *
415: * @param file
416: * String the name of the file or directory to check.
417: * @param context
418: * Object the security context to use for the check.
419: */
420: public void checkRead(String file, Object context) {
421: checkPermission(new FilePermission(file, "read"), context); //$NON-NLS-1$
422: }
423:
424: /**
425: * Checks whether the running program is allowed to perform the security
426: * operation named by the target.
427: *
428: * @param target
429: * String the name of the operation to perform.
430: */
431: public void checkSecurityAccess(String target) {
432: checkPermission(new SecurityPermission(target));
433: }
434:
435: /**
436: * Checks whether the running program is allowed to set the net object
437: * factories.
438: */
439: public void checkSetFactory() {
440: checkPermission(RuntimePermission.permissionToSetFactory);
441: }
442:
443: /**
444: * Checks whether the running program is allowed to create a top level
445: * window.
446: *
447: * @param window
448: * The non-null window for which to check access
449: */
450: public boolean checkTopLevelWindow(Object window) {
451: if (window == null) {
452: throw new NullPointerException();
453: }
454: try {
455: Class<?> awtPermission = Class
456: .forName("java.awt.AWTPermission"); //$NON-NLS-1$
457: Constructor<?> constructor = awtPermission
458: .getConstructor(String.class);
459: Object perm = constructor
460: .newInstance("showWindowWithoutWarningBanner"); //$NON-NLS-1$
461: checkPermission((Permission) perm);
462: } catch (ClassNotFoundException e) {
463: } catch (NoSuchMethodException e) {
464: } catch (InstantiationException e) {
465: } catch (IllegalAccessException e) {
466: } catch (InvocationTargetException e) {
467: } catch (SecurityException e) {
468: return false;
469: }
470: return true;
471: }
472:
473: /**
474: * Checks whether the running program is allowed to access the system
475: * clipboard.
476: */
477: public void checkSystemClipboardAccess() {
478: try {
479: Class<?> awtPermission = Class
480: .forName("java.awt.AWTPermission"); //$NON-NLS-1$
481: Constructor<?> constructor = awtPermission
482: .getConstructor(String.class);
483: Object perm = constructor.newInstance("accessClipboard"); //$NON-NLS-1$
484: checkPermission((Permission) perm);
485: return;
486: } catch (ClassNotFoundException e) {
487: } catch (NoSuchMethodException e) {
488: } catch (InstantiationException e) {
489: } catch (IllegalAccessException e) {
490: } catch (InvocationTargetException e) {
491: }
492: throw new SecurityException();
493: }
494:
495: /**
496: * Checks whether the running program is allowed to access the AWT Event
497: * queue. Since we don't support AWT, the answer is no.
498: */
499: public void checkAwtEventQueueAccess() {
500: try {
501: Class<?> awtPermission = Class
502: .forName("java.awt.AWTPermission"); //$NON-NLS-1$
503: Constructor<?> constructor = awtPermission
504: .getConstructor(String.class);
505: Object perm = constructor.newInstance("accessEventQueue"); //$NON-NLS-1$
506: checkPermission((Permission) perm);
507: return;
508: } catch (ClassNotFoundException e) {
509: } catch (NoSuchMethodException e) {
510: } catch (InstantiationException e) {
511: } catch (IllegalAccessException e) {
512: } catch (InvocationTargetException e) {
513: }
514: throw new SecurityException();
515: }
516:
517: /**
518: * Checks whether the running program is allowed to start a new print job.
519: */
520: public void checkPrintJobAccess() {
521: checkPermission(RuntimePermission.permissionToQueuePrintJob);
522: }
523:
524: /**
525: * Checks whether the running program is allowed to read from the file whose
526: * descriptor is the argument.
527: *
528: * @param fd
529: * the file descriptor of the file to check
530: */
531: public void checkWrite(FileDescriptor fd) {
532: if (fd == null) {
533: throw new NullPointerException();
534: }
535: checkPermission(RuntimePermission.permissionToWriteFileDescriptor);
536: }
537:
538: /**
539: * Checks whether the running program is allowed to write to the file named
540: * by the argument, which should be passed in canonical form.
541: *
542: * @param file
543: * the name of the file to check
544: */
545: public void checkWrite(String file) {
546: checkPermission(new FilePermission(file, "write")); //$NON-NLS-1$
547: }
548:
549: /**
550: * Answers true if the security manager is currently checking something.
551: *
552: * @return boolean true if we are are in a security check method.
553: *
554: * @deprecated Use checkPermission
555: */
556: @Deprecated
557: public boolean getInCheck() {
558: return inCheck;
559: }
560:
561: /**
562: * Answers an array containing one entry for each method in the stack. Each
563: * entry is the java.lang.Class which represents the class in which the
564: * method is defined.
565: *
566: * @return Class[] all of the classes in the stack.
567: */
568: @SuppressWarnings("unchecked")
569: protected Class[] getClassContext() {
570: return Class.getStackClasses(-1, false);
571: }
572:
573: /**
574: * Answers the class loader of the first class in the stack whose class
575: * loader is not a system class loader.
576: *
577: * @return ClassLoader the most recent non-system class loader.
578: *
579: * @deprecated Use checkPermission
580: */
581: @Deprecated
582: protected ClassLoader currentClassLoader() {
583:
584: /*
585: * First, check if AllPermission is allowed. If so, then we are
586: * effectively running in an unsafe environment, so just answer null
587: * (==> everything is a system class).
588: */
589: try {
590: checkPermission(new AllPermission());
591: return null;
592: } catch (SecurityException ex) {
593: }
594:
595: /*
596: * Now, check if there are any non-system class loaders in the stack up
597: * to the first privileged method (or the end of the stack.
598: */
599: Class<?>[] classes = Class.getStackClasses(-1, true);
600: for (int i = 0; i < classes.length; i++) {
601: ClassLoader cl = classes[i].getClassLoaderImpl();
602: if (cl != null && !cl.isSystemClassLoader()) {
603: return cl;
604: }
605: }
606: return null;
607: }
608:
609: /**
610: * Answers the index in the stack of three first class whose class loader is
611: * not a system class loader.
612: *
613: * @return int the frame index of the first method whose class was loaded by
614: * a non-system class loader.
615: *
616: * @deprecated Use checkPermission
617: */
618: @Deprecated
619: protected int classLoaderDepth() {
620: /*
621: * First, check if AllPermission is allowed. If so, then we are
622: * effectively running in an unsafe environment, so just answer -1 (==>
623: * everything is a system class).
624: */
625: try {
626: checkPermission(new AllPermission());
627: return -1;
628: } catch (SecurityException ex) {
629: }
630:
631: /*
632: * Now, check if there are any non-system class loaders in the stack up
633: * to the first privileged method (or the end of the stack.
634: */
635: Class<?>[] classes = Class.getStackClasses(-1, true);
636: for (int i = 0; i < classes.length; i++) {
637: ClassLoader cl = classes[i].getClassLoaderImpl();
638: if (cl != null && !cl.isSystemClassLoader()) {
639: return i;
640: }
641: }
642: return -1;
643: }
644:
645: /**
646: * Answers the first class in the stack which was loaded by a class loader
647: * which is not a system class loader.
648: *
649: * @return Class the most recent class loaded by a non-system class loader.
650: *
651: * @deprecated Use checkPermission
652: */
653: @Deprecated
654: protected Class<?> currentLoadedClass() {
655: /*
656: * First, check if AllPermission is allowed. If so, then we are
657: * effectively running in an unsafe environment, so just answer null
658: * (==> everything is a system class).
659: */
660: try {
661: checkPermission(new AllPermission());
662: return null;
663: } catch (SecurityException ex) {
664: }
665:
666: /*
667: * Now, check if there are any non-system class loaders in the stack up
668: * to the first privileged method (or the end of the stack.
669: */
670: Class<?>[] classes = Class.getStackClasses(-1, true);
671: for (int i = 0; i < classes.length; i++) {
672: ClassLoader cl = classes[i].getClassLoaderImpl();
673: if (cl != null && !cl.isSystemClassLoader()) {
674: return classes[i];
675: }
676: }
677: return null;
678: }
679:
680: /**
681: * Answers the index in the stack of the first method which is contained in
682: * a class called <code>name</code>. If no methods from this class are in
683: * the stack, return -1.
684: *
685: * @param name
686: * String the name of the class to look for.
687: * @return int the depth in the stack of a the first method found.
688: *
689: * @deprecated Use checkPermission
690: */
691: @Deprecated
692: protected int classDepth(String name) {
693: Class<?>[] classes = Class.getStackClasses(-1, false);
694: for (int i = 0; i < classes.length; i++) {
695: if (classes[i].getName().equals(name)) {
696: return i;
697: }
698: }
699: return -1;
700: }
701:
702: /**
703: * Answers true if there is a method on the stack from the specified class,
704: * and false otherwise.
705: *
706: * @param name
707: * String the name of the class to look for.
708: * @return boolean true if we are running a method from the specified class.
709: *
710: * @deprecated Use checkPermission
711: */
712: @Deprecated
713: protected boolean inClass(String name) {
714: return classDepth(name) != -1;
715: }
716:
717: /**
718: * Answers true if there is a method on the stack from a class which was
719: * defined by a non-system classloader.
720: *
721: * @return boolean
722: *
723: * @deprecated Use checkPermission
724: */
725: @Deprecated
726: protected boolean inClassLoader() {
727: return currentClassLoader() != null;
728: }
729:
730: /**
731: * Answers the thread group which should be used to instantiate new threads.
732: * By default, this is the same as the thread group of the thread running
733: * this method.
734: *
735: * @return ThreadGroup The thread group to create new threads in.
736: */
737: public ThreadGroup getThreadGroup() {
738: return Thread.currentThread().getThreadGroup();
739: }
740:
741: /**
742: * Answers an object which encapsulates the security state of the current
743: * point in the execution. In our case, this is an AccessControlContext.
744: */
745: public Object getSecurityContext() {
746: return AccessController.getContext();
747: }
748:
749: /**
750: * Checks whether the running program is allowed to access the resource
751: * being guarded by the given Permission argument.
752: *
753: * @param permission
754: * the permission to check
755: */
756: public void checkPermission(Permission permission) {
757: try {
758: inCheck = true;
759: AccessController.checkPermission(permission);
760: } finally {
761: inCheck = false;
762: }
763: }
764:
765: /**
766: * Checks whether the running program is allowed to access the resource
767: * being guarded by the given Permission argument.
768: *
769: * @param permission
770: * the permission to check
771: */
772: public void checkPermission(Permission permission, Object context) {
773: try {
774: inCheck = true;
775: // Must be an AccessControlContext. If we don't check
776: // this, then applications could pass in an arbitrary
777: // object which circumvents the security check.
778: if (context instanceof AccessControlContext) {
779: ((AccessControlContext) context)
780: .checkPermission(permission);
781: } else {
782: throw new SecurityException();
783: }
784: } finally {
785: inCheck = false;
786: }
787: }
788: }
|