Skip to content

Commit

Permalink
[JENKINS-36871] Migrate javadoc from classes to be removed
Browse files Browse the repository at this point in the history
  • Loading branch information
stephenc committed Aug 2, 2016
1 parent 4c8b49f commit 124439e
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 19 deletions.
Expand Up @@ -44,16 +44,17 @@
import org.jenkinsci.remoting.protocol.impl.ConnectionRefusalException;

/**
* Implementation of the JNLP-connect protocol.
* Implementation of the JNLP2-connect protocol.
*
* The slave sends the master the slave name it wants to register as and the
* computed HMAC of the slave name. If accepted the master will reply with a
* confirmation response.
* This is an extension of the JNLP1-connect protocol. On successful
* connection to the master the slave will receive a cookie from the master,
* which the slave stores.
*
* This was the first protocol supported by Jenkins. JNLP slaves will use this
* as a last resort when connecting to old versions of Jenkins masters.
* If the slave needs to reconnect it will send the same cookie as part of
* the new connection request. The master can use the cookie to determine if
* the incoming request is an initial connection request or a reconnection
* and take appropriate action.
*
* @author Akshay Dayal
*/
@Deprecated
public class JnlpProtocol2Handler extends LegacyJnlpProtocolHandler<LegacyJnlpConnectionState> {
Expand Down
Expand Up @@ -25,7 +25,6 @@

import hudson.remoting.Channel;
import hudson.remoting.ChannelBuilder;
import hudson.remoting.SocketChannelStream;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
Expand Down Expand Up @@ -54,16 +53,67 @@
import static org.jenkinsci.remoting.engine.Jnlp3Util.createChallengeResponse;

/**
* Implementation of the JNLP-connect protocol.
* Implementation of the JNLP3-connect protocol.
*
* The slave sends the master the slave name it wants to register as and the
* computed HMAC of the slave name. If accepted the master will reply with a
* confirmation response.
* <p>This protocol aims to provide a basic level of security for JNLP based
* slaves. Both the master and the slave securely authenticate each other and
* then setup an encrypted {@link Channel}.
*
* This was the first protocol supported by Jenkins. JNLP slaves will use this
* as a last resort when connecting to old versions of Jenkins masters.
* <p>The slave secret is never exchanged, but instead used as a shared secret
* to generate matching symmetric key {@link javax.crypto.Cipher}s by both
* sides which are used to perform a secure handshake. During the handshake
* both the slave and the master send each other challenge phrases which can
* only be decrypted with the matching cipher created with the slave secret.
* Once decrypted the SHA-256 hash of the challenge is computed and sent back
* to authenticate.
*
* @author Akshay Dayal
* <p>Once the handshake is successful another pair of symmetric key ciphers
* are created by the slave using random keys. These are then shared with the
* master. These ciphers are used to create an encrypted channel by both sides.
*
* <p>The following goes over the handshake in more detail:
* <pre>
* Client Master
* handshake ciphers = createFrom(slave name, slave secret)
*
* | |
* | initiate(slave name, encrypt(challenge), encrypt(cookie)) |
* | -------------------------------------------------------------->>> |
* | |
* | encrypt(hash(challenge)) |
* | <<<-------------------------------------------------------------- |
* | |
* | GREETING_SUCCESS |
* | -------------------------------------------------------------->>> |
* | |
* | encrypt(challenge) |
* | <<<-------------------------------------------------------------- |
* | |
* | encrypt(hash(challenge)) |
* | -------------------------------------------------------------->>> |
* | |
* | GREETING_SUCCESS |
* | <<<-------------------------------------------------------------- |
* | |
* | encrypt(cookie) |
* | <<<-------------------------------------------------------------- |
* | |
* | encrypt(AES key) + encrypt(IvSpec) |
* | -------------------------------------------------------------->>> |
* | |
*
* channel ciphers = createFrom(AES key, IvSpec)
* channel = channelBuilder.createWith(channel ciphers)
* </pre>
*
* <p>The entire process assumes the slave secret has not been leaked
* beforehand and the slave obtains it in a secure manner.
*
* <p>The key sizes are only 128bit since it cannot be assumed everyone has
* the <a href="http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html">
* Java Cryptography Extension</a> available. In the future maybe the key
* size could be made a parameter or the implementation can check to see if
* 256bit sizes are supported.
*/
@Deprecated
public class JnlpProtocol3Handler extends LegacyJnlpProtocolHandler<Jnlp3ConnectionState> {
Expand All @@ -88,17 +138,26 @@ public JnlpProtocol3Handler(@Nonnull ExecutorService threadPool, @Nullable NioCh
this.secretDatabase = secretDatabase;
}

/**
* {@inheritDoc}
*/
@Override
public String getName() {
return NAME;
}

/**
* {@inheritDoc}
*/
@Override
public Jnlp3ConnectionState createConnectionState(Socket socket, List<JnlpConnectionStateListener> listeners)
throws IOException {
return new Jnlp3ConnectionState(socket, listeners);
}

/**
* {@inheritDoc}
*/
@Override
void sendHandshake(Jnlp3ConnectionState state, Map<String, String> headers)
throws IOException {
Expand Down Expand Up @@ -176,11 +235,14 @@ void sendHandshake(Jnlp3ConnectionState state, Map<String, String> headers)
state.setChannelCiphers(channelCiphers);

cookie = handshakeCiphers.decrypt(readLine(inputStream));
Map<String,String> properties = new HashMap<String,String>();
Map<String, String> properties = new HashMap<String, String>();
properties.put(JnlpConnectionState.COOKIE_KEY, cookie);
state.fireAfterProperties(properties);
}

/**
* {@inheritDoc}
*/
@Override
void receiveHandshake(Jnlp3ConnectionState state, Map<String, String> headers) throws IOException {
PrintWriter out = state.getPrintWriter();
Expand Down Expand Up @@ -217,7 +279,8 @@ void receiveHandshake(Jnlp3ConnectionState state, Map<String, String> headers) t
Map<String, String> properties = new HashMap<String, String>();
properties.putAll((Map) request);
if (properties.get(JnlpConnectionState.COOKIE_KEY) != null) {
properties.put(JnlpConnectionState.COOKIE_KEY, handshakeCiphers.decrypt(properties.get(JnlpConnectionState.COOKIE_KEY)));
properties.put(JnlpConnectionState.COOKIE_KEY,
handshakeCiphers.decrypt(properties.get(JnlpConnectionState.COOKIE_KEY)));
}

// now validate the client
Expand Down Expand Up @@ -261,7 +324,9 @@ private String toHexString(@Nonnull byte[] bytes) {
StringBuilder buf = new StringBuilder();
for (byte bb : bytes) {
int b = bb & 0xFF;
if (b < 16) buf.append('0');
if (b < 16) {
buf.append('0');
}
buf.append(Integer.toHexString(b));
}
return buf.toString();
Expand All @@ -276,7 +341,8 @@ Channel buildChannel(Jnlp3ConnectionState state) throws IOException {
}
return channelBuilder.build(
new CipherInputStream(state.getBufferedInputStream(), state.getChannelCiphers().getDecryptCipher()),
new CipherOutputStream(state.getSocket().getOutputStream(), state.getChannelCiphers().getEncryptCipher())
new CipherOutputStream(state.getSocket().getOutputStream(),
state.getChannelCiphers().getEncryptCipher())
);
}

Expand Down

0 comments on commit 124439e

Please sign in to comment.