Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright (c) 2001-2023 Mathew A. Nelson and Robocode contributors
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://robocode.sourceforge.io/license/epl-v10.html
*/
package net.sf.robocode.host.security;
import net.sf.robocode.core.Container;
import net.sf.robocode.host.IHostedThread;
import net.sf.robocode.host.IThreadManager;
import net.sf.robocode.host.io.RobotFileSystemManager;
import net.sf.robocode.io.Logger;
import net.sf.robocode.repository.IRepositoryManager;
import java.io.File;
import java.io.FilePermission;
import java.io.IOException;
import java.security.*;
import java.util.*;
/**
* @author Mathew A. Nelson (original)
* @author Flemming N. Larsen (contributor)
* @author Robert D. Maupin (contributor)
* @author Pavel Savara (contributor)
*/
public class RobocodeSecurityPolicy extends Policy {
private static final boolean isFileReadSecurityOff = System.getProperty("OVERRIDEFILEREADSECURITY", "false").equals(
"true");
private static final boolean isExperimental = System.getProperty("EXPERIMENTAL", "false").equals("true");
private final Set allowedPackages = new HashSet<>();
private final Policy parentPolicy;
private Set untrustedCodeUrls;
private final IThreadManager threadManager;
public RobocodeSecurityPolicy(IThreadManager threadManager) {
this.parentPolicy = Policy.getPolicy();
PermissionCollection allPermissions = new Permissions();
allPermissions.add(new AllPermission());
this.threadManager = threadManager;
allowedPackages.add("robocode.util");
allowedPackages.add("robocode.robotinterfaces");
allowedPackages.add("robocode.robotpaint");
allowedPackages.add("robocode.robocodeGL");
if (isExperimental) {
allowedPackages.add("robocode.robotinterfaces.peer");
}
initUrls();
Policy.setPolicy(this);
}
@Override
public PermissionCollection getPermissions(ProtectionDomain domain) {
return getPermissions(domain.getCodeSource());
}
@Override
public PermissionCollection getPermissions(final CodeSource codeSource) {
final String source = codeSource.getLocation().toString();
if (untrustedCodeUrls.contains(source)) {
return new Permissions();
}
return AccessController.doPrivileged((PrivilegedAction) () -> parentPolicy.getPermissions(codeSource));
}
@Override
public boolean implies(ProtectionDomain domain, final Permission permission) {
final String source = domain.getCodeSource().getLocation().toString();
if (!untrustedCodeUrls.contains(source)) {
return true;
}
return AccessController.doPrivileged((PrivilegedAction) () -> impliesRobot(permission));
}
private boolean impliesRobot(Permission perm) {
// For development purposes, allow read any file if override is set.
final String actions = perm.getActions();
final String name = perm.getName();
if (perm instanceof FilePermission && actions.equals("read") && isFileReadSecurityOff) {
return true;
}
// Allow reading of properties.
if (perm instanceof PropertyPermission && actions.equals("read")) {
return true;
}
if (perm instanceof RobocodePermission) {
if (name.equals("System.out") || name.equals("System.err") || name.equals("System.in")) {
return true;
}
}
// Ok, we need to figure out who our robot is.
Thread c = Thread.currentThread();
IHostedThread robotProxy = threadManager.getLoadedOrLoadingRobotProxy(c);
if (robotProxy == null) {
Logger.logError("Preventing unknown thread " + Thread.currentThread().getName() + " from access: " + perm);
return false;
}
// Attempt to stop the window from displaying
if (perm instanceof java.awt.AWTPermission) {
final String message = "Preventing " + robotProxy.getStatics().getName() + " from access: " + perm;
robotProxy.punishSecurityViolation(message);
// this is hack, because security exception is not enough
throw new ThreadDeath();
}
// FilePermission access request.
if (perm instanceof FilePermission) {
FilePermission filePermission = (FilePermission) perm;
// Get the fileSystemManager
RobotFileSystemManager fileSystemManager = robotProxy.getRobotFileSystemManager();
// Robot wants access to read something
if (filePermission.getActions().equals("read")) {
return impliesRobotFileRead(robotProxy, fileSystemManager, filePermission);
} // Robot wants access to write something
else if (filePermission.getActions().equals("write")) {
return impliesRobotFileWrite(robotProxy, fileSystemManager, filePermission);
} // Robot wants access to write something
else if (filePermission.getActions().equals("delete")) {
return impliesRobotFileDelete(robotProxy, fileSystemManager, filePermission);
}
}
// check package access
if (perm instanceof RuntimePermission) {
if (name.startsWith("accessClassInPackage.")) {
return impliesRobotPackageAccess(robotProxy, name.substring(21));
} else if (name.equals("accessDeclaredMembers")) {
return true;
}
}
// Permission denied.
final String message = "Preventing " + robotProxy.getStatics().getName() + " from access: " + perm;
robotProxy.punishSecurityViolation(message);
return false;
}
private boolean impliesRobotPackageAccess(IHostedThread robotProxy, String packageName) {
if (packageName.startsWith("robocode.control") || packageName.startsWith("net.sf.robocode")) {
if (allowedPackages.contains(packageName)) {
return true;
}
final String message = "Preventing " + Thread.currentThread().getName()
+ " from access to the internal Robocode package: " + packageName;
robotProxy.punishSecurityViolation(message);
return false;
}
return true;
}
private boolean impliesRobotFileDelete(IHostedThread robotProxy, RobotFileSystemManager fileSystemManager, FilePermission filePermission) {
// If there is no writable directory, deny access
if (fileSystemManager.getWritableDirectory() == null) {
final String message = "Preventing " + robotProxy.getStatics().getName() + " from access: " + filePermission
+ ". Robots that are not in a package may not delete any files.";
robotProxy.punishSecurityViolation(message);
return false;
}
// If this is a writable file, permit access
if (fileSystemManager.isWritable(filePermission.getName())) {
return true;
} // else it's not writable, deny access.
// We are deleting our data directory.
if (fileSystemManager.getWritableDirectory().toString().equals(filePermission.getName())) {
return true;
}
// Not a writable directory.
final String message = "Preventing " + robotProxy.getStatics().getName() + " from access: " + filePermission
+ ". You may only delete files in your own data directory: " + fileSystemManager.getWritableDirectory();
robotProxy.punishSecurityViolation(message);
return false;
}
private boolean impliesRobotFileWrite(IHostedThread robotProxy, RobotFileSystemManager fileSystemManager, FilePermission filePermission) {
// There isn't one. Deny access.
if (!threadManager.checkRobotFileStream()) {
final String message = "Preventing " + robotProxy.getStatics().getName() + " from access: " + filePermission
+ ". You must use a RobocodeOutputStream.";
robotProxy.punishSecurityViolation(message);
return false;
}
// If there is no writable directory, deny access
if (fileSystemManager.getWritableDirectory() == null) {
final String message = "Preventing " + robotProxy.getStatics().getName() + " from access: " + filePermission
+ ". Robots that are not in a package may not write any files.";
robotProxy.punishSecurityViolation(message);
return false;
}
// If this is a writable file, permit access
if (fileSystemManager.isWritable(filePermission.getName())) {
return true;
} // else it's not writable, deny access.
// We are creating the directory.
if (fileSystemManager.getWritableDirectory().toString().equals(filePermission.getName())) {
return true;
}
// Not a writable directory.
final String message = "Preventing " + robotProxy.getStatics().getName() + " from access: " + filePermission
+ ". You may only write files in your own data directory: " + fileSystemManager.getWritableDirectory();
robotProxy.punishSecurityViolation(message);
return false;
}
private boolean impliesRobotFileRead(IHostedThread robotProxy, RobotFileSystemManager fileSystemManager, FilePermission filePermission) {
// If there is no readable directory, deny access.
if (fileSystemManager.getReadableDirectory() == null) {
final String message = "Preventing " + robotProxy.getStatics().getName() + " from access: " + filePermission
+ ". Robots that are not in a package may not read any files.";
robotProxy.punishSecurityViolation(message);
return false;
}
// If this is a writtable file, return.
if (fileSystemManager.isWritable(filePermission.getName())) {
return true;
}
// If this is a readable file, return.
if (fileSystemManager.isReadable(filePermission.getName())) {
return true;
}
// Else disable robot
final String message = "Preventing " + robotProxy.getStatics().getName() + " from access: " + filePermission
+ ". You may only read files in your own root package directory.";
robotProxy.punishSecurityViolation(message);
return false;
}
@Override
public void refresh() {
initUrls();
parentPolicy.refresh();
}
private void initUrls() {
untrustedCodeUrls = new HashSet<>();
untrustedCodeUrls.add(RobotClassLoader.UNTRUSTED_URL);
String classPath = System.getProperty("robocode.class.path");
StringTokenizer tokenizer = new StringTokenizer(classPath, File.pathSeparator);
// TODO load URLs from new repository roots, don't forget about all robot .jar files
// TODO or check it directly against repository ?
try {
final List robots = new ArrayList<>();
IRepositoryManager repositoryManager = Container.getComponent(IRepositoryManager.class);
if (repositoryManager != null) {
robots.add(repositoryManager.getRobotsDirectory().toURI().toString());
for (File devel : repositoryManager.getDevelDirectories()) {
robots.add(devel.toURI().toString());
}
}
while (tokenizer.hasMoreTokens()) {
String u = new File(tokenizer.nextToken()).getCanonicalFile().toURI().toString();
if (robots.contains(u)) {
untrustedCodeUrls.add(u);
}
}
} catch (IOException e) {
Logger.logError(e);
}
}
}