<commit_before>package jenkins.security;

import hudson.Extension;
import hudson.remoting.Callable;
import hudson.remoting.CallableDecorator;
import hudson.remoting.ChannelBuilder;
import hudson.slaves.ComputerListener;
import hudson.slaves.SlaveComputer;

import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Rejects {@link MasterToSlave} callables.
 *
 * @author <NAME>
 * @since TODO
 */
public class CallableDirectionChecker extends CallableDecorator {
    private final SlaveComputer computer;

    public CallableDirectionChecker(SlaveComputer computer) {
        this.computer = computer;
    }

    @Override
    public <V, T extends Throwable> Callable<V, T> userRequest(Callable<V, T> op, Callable<V, T> stem) {
        Class<?> c = op.getClass();

        if (c.getName().startsWith("hudson.remoting")) // TODO probably insecure
            return stem;    // lower level services provided by remoting, such IOSyncer, RPCRequest, Ping, etc. that we allow

        boolean m2s = c.isAnnotationPresent(MasterToSlave.class);
        boolean s2m = c.isAnnotationPresent(SlaveToMaster.class);

        if (!m2s && !s2m) {
            // no annotation provided, so we don't know.
            // to err on the correctness we'd let it pass with reporting, which
            // provides auditing trail.
            LOGGER.log(Level.WARNING, "Unchecked callable from {0}: {1}", new Object[] {computer.getName(), c});

            return stem;
        }

        if (s2m)
            return stem;    // known to be safe

        // this means m2s && !s2m, meaning it's for master->slave
        throw new SecurityException(String.format("Invocation of %s is prohibited", c));
    }

    /**
     * Installs {@link CallableDirectionChecker} to every channel.
     */
    @Extension
    public static class ComputerListenerImpl extends ComputerListener {
        @Override
        public void onChannelBuilding(ChannelBuilder builder, SlaveComputer sc) {
            builder.with(new CallableDirectionChecker(sc));
        }
    }

    private static final Logger LOGGER = Logger.getLogger(CallableDirectionChecker.class.getName());
}<commit_msg>Rewriting method body to more legible flow.<commit_after>package jenkins.security;

import hudson.Extension;
import hudson.remoting.Callable;
import hudson.remoting.CallableDecorator;
import hudson.remoting.ChannelBuilder;
import hudson.slaves.ComputerListener;
import hudson.slaves.SlaveComputer;

import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Rejects {@link MasterToSlave} callables.
 *
 * @author <NAME>
 * @since TODO
 */
public class CallableDirectionChecker extends CallableDecorator {
    private final SlaveComputer computer;

    public CallableDirectionChecker(SlaveComputer computer) {
        this.computer = computer;
    }

    @Override
    public <V, T extends Throwable> Callable<V, T> userRequest(Callable<V, T> op, Callable<V, T> stem) {
        Class<?> c = op.getClass();

        if (c.getName().startsWith("hudson.remoting")) // TODO probably insecure
            return stem;    // lower level services provided by remoting, such IOSyncer, RPCRequest, Ping, etc. that we allow

        if (c.isAnnotationPresent(SlaveToMaster.class)) {
            return stem;    // known to be safe
        }

        if (c.isAnnotationPresent(MasterToSlave.class)) {
            throw new SecurityException(String.format("Invocation of %s is prohibited", c));
        } else {
            // no annotation provided, so we don't know.
            // to err on the correctness we'd let it pass with reporting, which
            // provides auditing trail.
            LOGGER.log(Level.WARNING, "Unchecked callable from {0}: {1}", new Object[] {computer.getName(), c});
            return stem;
        }
    }

    /**
     * Installs {@link CallableDirectionChecker} to every channel.
     */
    @Extension
    public static class ComputerListenerImpl extends ComputerListener {
        @Override
        public void onChannelBuilding(ChannelBuilder builder, SlaveComputer sc) {
            builder.with(new CallableDirectionChecker(sc));
        }
    }

    private static final Logger LOGGER = Logger.getLogger(CallableDirectionChecker.class.getName());
}
{'fraction_non_alphanumeric': 0.09908429208734444, 'fraction_numerical': 0.002582765907490021, 'mean_word_length': 2.977591036414566, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 16, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1372526', 'n_tokens_mistral': 1222, 'n_tokens_neox': 1181, 'n_words': 338}