<commit_before>package org.jenkinsci.remoting.engine;

import hudson.remoting.Channel;
import hudson.remoting.SocketChannelStream;
import org.jenkinsci.remoting.nio.NioChannelHub;

import javax.annotation.Nonnull;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.Socket;
import java.nio.charset.Charset;
import java.security.SecureRandom;
import java.util.Random;
import java.util.concurrent.ExecutorService;

/**
 * Server-side handshaking logic for {@link JnlpProtocol3}.
 *
 * @author <NAME>
 */
public abstract class JnlpServer3Handshake extends JnlpServerHandshake {
    /**
     * If the client sends a connection cookie, that value is stored here.
     */
    protected String cookie;

    private HandshakeCiphers handshakeCiphers;

    private String nodeName;

    public JnlpServer3Handshake(NioChannelHub hub, ExecutorService threadPool, Socket socket) throws IOException {
        super(hub,threadPool,socket);
    }

    /**
     * Gets the node name reported from the other side.
     */
    public String getNodeName() {
        return nodeName;
    }

    /**
     * Performs the handshake and establishes a channel.
     */
    public Channel connect() throws IOException, InterruptedException {
        try {
            out.println(JnlpProtocol3.NEGOTIATE_LINE);

            // Get initiation information from slave.
            request.load(new ByteArrayInputStream(in.readUTF().getBytes(Charset.forName("UTF-8"))));
            nodeName = request.getProperty(JnlpProtocol3.SLAVE_NAME_KEY);

            this.handshakeCiphers = HandshakeCiphers.create(nodeName, getNodeSecret(nodeName));

            authenticateToSlave();

            // If there is a cookie decrypt it.
            if (getRequestProperty(JnlpProtocol3.COOKIE_KEY) != null) {
                cookie = handshakeCiphers.decrypt(getRequestProperty(JnlpProtocol3.COOKIE_KEY));
            }

            validateSlave();
        } catch (Failure f) {
            error(f.getMessage());
            return null;
        }

        // Send greeting and new cookie.
        out.println(JnlpProtocol.GREETING_SUCCESS);
        String newCookie = generateCookie();
        out.println(handshakeCiphers.encrypt(newCookie));

        // Now get the channel cipher information.
        String aesKeyString = handshakeCiphers.decrypt(in.readUTF());
        String specKeyString = handshakeCiphers.decrypt(in.readUTF());
        ChannelCiphers channelCiphers = ChannelCiphers.create(
                Jnlp3Util.keyFromString(aesKeyString),
                Jnlp3Util.keyFromString(specKeyString));

        Channel channel = createChannelBuilder(nodeName).build(
                new CipherInputStream(SocketChannelStream.in(socket),
                        channelCiphers.getDecryptCipher()),
                new CipherOutputStream(SocketChannelStream.out(socket),
                        channelCiphers.getEncryptCipher()));<commit_msg>[FIXED JENKINS-37140] Roll the dice again if we are unlucky<commit_after>package org.jenkinsci.remoting.engine;

import hudson.remoting.Channel;
import hudson.remoting.SocketChannelStream;
import org.jenkinsci.remoting.nio.NioChannelHub;

import javax.annotation.Nonnull;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.Socket;
import java.nio.charset.Charset;
import java.security.SecureRandom;
import java.util.Random;
import java.util.concurrent.ExecutorService;

/**
 * Server-side handshaking logic for {@link JnlpProtocol3}.
 *
 * @author <NAME>
 */
public abstract class JnlpServer3Handshake extends JnlpServerHandshake {
    /**
     * If the client sends a connection cookie, that value is stored here.
     */
    protected String cookie;

    private HandshakeCiphers handshakeCiphers;

    private String nodeName;

    public JnlpServer3Handshake(NioChannelHub hub, ExecutorService threadPool, Socket socket) throws IOException {
        super(hub,threadPool,socket);
    }

    /**
     * Gets the node name reported from the other side.
     */
    public String getNodeName() {
        return nodeName;
    }

    /**
     * Performs the handshake and establishes a channel.
     */
    public Channel connect() throws IOException, InterruptedException {
        try {
            out.println(JnlpProtocol3.NEGOTIATE_LINE);

            // Get initiation information from slave.
            request.load(new ByteArrayInputStream(in.readUTF().getBytes(Charset.forName("UTF-8"))));
            nodeName = request.getProperty(JnlpProtocol3.SLAVE_NAME_KEY);

            this.handshakeCiphers = HandshakeCiphers.create(nodeName, getNodeSecret(nodeName));

            authenticateToSlave();

            // If there is a cookie decrypt it.
            if (getRequestProperty(JnlpProtocol3.COOKIE_KEY) != null) {
                cookie = handshakeCiphers.decrypt(getRequestProperty(JnlpProtocol3.COOKIE_KEY));
            }

            validateSlave();
        } catch (Failure f) {
            error(f.getMessage());
            return null;
        }

        // Send greeting and new cookie.
        out.println(JnlpProtocol.GREETING_SUCCESS);
        String newCookie = null;
        String encryptedCookie = null;
        // JENKINS-37140 the protocol cannot handle encrypted cookies that contain a '\n', i.e. approx 22% of them
        // we loop up to 100 times
        for (int loopCount = 0; loopCount < 110; loopCount++) {
            if (loopCount >= 100) {
                // ok so a 0.22^100 chance happened... we'd be really unlucky if we ever get here again in the
                // age of the universe
                throw new IOException("JENKINS-37140 got really unlucky with the random number generator");
            }
            newCookie = generateCookie();
            encryptedCookie = handshakeCiphers.encrypt(newCookie);
            if (encryptedCookie.indexOf('\n') == -1) {
                break;
            }
        }
        out.println(encryptedCookie);

        // Now get the channel cipher information.
        String aesKeyString = handshakeCiphers.decrypt(in.readUTF());
        String specKeyString = handshakeCiphers.decrypt(in.readUTF());
        ChannelCiphers channelCiphers = ChannelCiphers.create(
                Jnlp3Util.keyFromString(aesKeyString),
                Jnlp3Util.keyFromString(specKeyString));

        Channel channel = createChannelBuilder(nodeName).build(
                new CipherInputStream(SocketChannelStream.in(socket),
                        channelCiphers.getDecryptCipher()),
                new CipherOutputStream(SocketChannelStream.out(socket),
                        channelCiphers.getEncryptCipher()));
{'fraction_non_alphanumeric': 0.08826112412177986, 'fraction_numerical': 0.007903981264637002, 'mean_word_length': 2.6935135135135133, 'pattern_counts': {'":': 0, '<': 6, '<?xml version=': 0, '>': 6, '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': '1919464', 'n_tokens_mistral': 1939, 'n_tokens_neox': 1838, 'n_words': 425}