package jenkins; import hudson.FilePath; import hudson.remoting.Channel; import hudson.remoting.ChannelBuilder; import jenkins.security.ChannelConfigurator; import javax.annotation.CheckForNull; import java.io.File; /** * Inspects {@link FilePath} access from remote channels. * * <p> * Returning {@code true} indicates that the access is accepted. No other {@link FilePathFilter} * will be consulted to reject the execution, and the access will go through. Returning {@link false} * indicates "I don't know". Other {@link FilePathFilter}s get to inspect the access, and they might * accept/reject access. And finally, throwing {@link SecurityException} is to reject the access. * * <p> * To insert a custom {@link FilePathFilter} into a connection, * see {@link ChannelConfigurator#onChannelBuilding(ChannelBuilder, Object)} * * @author Kohsuke Kawaguchi * @see FilePath * @since 1.THU */ public abstract class FilePathFilter { /** * Checks if the given file/directory can be read. * * On POSIX, this corresponds to the 'r' permission of the file/directory itself. */ public boolean read(File f) throws SecurityException { return false; } /** * Checks if the given file can be written. * * On POSIX, this corresponds to the 'w' permission of the file itself. */ public boolean write(File f) throws SecurityException { return false; } /** * Checks if a symlink can be created at 'f' * * On POSIX, this corresponds to the 'w' permission of the file itself. */ public boolean symlink(File f) throws SecurityException { return false; } /** * Checks if the given directory can be created. * * On POSIX, this corresponds to the 'w' permission of the parent directory. */ public boolean mkdirs(File f) throws SecurityException { return false; } /** * Checks if the given file can be created. * * On POSIX, this corresponds to the 'w' permission of the parent directory. */ public boolean create(File f) throws SecurityException { return false; } /** * Checks if the given file/directory can be deleted. * * On POSIX, this corresponds to the 'w' permission of the parent directory. */ public boolean delete(File f) throws SecurityException { return false; } /** * Checks if the metadata of the given file/directory (as opposed to the content) can be accessed. * * On POSIX, this corresponds to the 'r' permission of the parent directory. */ public boolean stat(File f) throws SecurityException { return false; } public final void installTo(ChannelBuilder cb) { installTo(cb,FilePathFilterAggregator.DEFAULT_ORDINAL); } public final void installTo(ChannelBuilder cb, double d) { synchronized (cb) { FilePathFilterAggregator filters = (FilePathFilterAggregator) cb.getProperties().get(FilePathFilterAggregator.KEY); if (filters==null) { filters = new FilePathFilterAggregator(); cb.withProperty(FilePathFilterAggregator.KEY,filters); } filters.add(this,d); } } public final void uninstallFrom(Channel ch) { synchronized (ch) { FilePathFilterAggregator filters = ch.getProperty(FilePathFilterAggregator.KEY); if (filters!=null) { filters.remove(this); } } } /** * Returns an {@link FilePathFilter} object that represents all the in-scope filters, * or null if none is needed. */ public static @CheckForNull FilePathFilter current() { Channel ch = Channel.current(); if (ch==null) return null; return ch.getProperty(FilePathFilterAggregator.KEY); } /** * Immutable instance that represents the filter that allows everything. */ public static final FilePathFilter UNRESTRICTED = new FilePathFilterAggregator() { @Override protected boolean defaultAction() throws SecurityException { return true; } @Override public void add(FilePathFilter f, double d) { // noop because we are immutable } @Override public String toString() { return "Unrestricted"; } }; }