-
Notifications
You must be signed in to change notification settings - Fork 364
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[GH-563] Implement [email protected] extension and keystroke obfuscati…
…on (wip)
- Loading branch information
Showing
8 changed files
with
206 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
74 changes: 74 additions & 0 deletions
74
sshd-common/src/main/java/org/apache/sshd/common/kex/extension/parser/PingPong.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
/* | ||
* Licensed to the Apache Software Foundation (ASF) under one | ||
* or more contributor license agreements. See the NOTICE file | ||
* distributed with this work for additional information | ||
* regarding copyright ownership. The ASF licenses this file | ||
* to you under the Apache License, Version 2.0 (the | ||
* "License"); you may not use this file except in compliance | ||
* with the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
|
||
package org.apache.sshd.common.kex.extension.parser; | ||
|
||
import java.io.IOException; | ||
import java.nio.charset.StandardCharsets; | ||
|
||
import org.apache.sshd.common.util.buffer.Buffer; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
/** | ||
* @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> | ||
* @see <A HREF="https://raw.githubusercontent.com/openssh/openssh-portable/master/PROTOCOL">OpenSSH PROTOCOL</A> | ||
*/ | ||
public class PingPong extends AbstractKexExtensionParser<Integer> { | ||
public static final String NAME = "[email protected]"; | ||
|
||
public static final PingPong INSTANCE = new PingPong(); | ||
|
||
private static final Logger LOG = LoggerFactory.getLogger(PingPong.class); | ||
|
||
public PingPong() { | ||
super(NAME); | ||
} | ||
|
||
@Override | ||
public Integer parseExtension(Buffer buffer) throws IOException { | ||
return parseExtension(buffer.array(), buffer.rpos(), buffer.available()); | ||
} | ||
|
||
@Override | ||
public Integer parseExtension(byte[] data, int off, int len) throws IOException { | ||
if (len <= 0) { | ||
if (LOG.isDebugEnabled()) { | ||
LOG.debug("Inconsistent KEX extension {} received; no data (len={})", NAME, len); | ||
} | ||
return null; | ||
} | ||
String value = new String(data, off, len, StandardCharsets.UTF_8); | ||
try { | ||
Integer result = Integer.valueOf(Integer.parseUnsignedInt(value)); | ||
LOG.info("Server announced support for {} version {}", NAME, result); | ||
return result; | ||
} catch (NumberFormatException e) { | ||
if (LOG.isDebugEnabled()) { | ||
LOG.debug("Cannot parse KEX extension {} version {}", NAME, value); | ||
} | ||
} | ||
return null; | ||
} | ||
|
||
@Override | ||
protected void encode(Integer version, Buffer buffer) throws IOException { | ||
buffer.putString(version.toString()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,22 +18,34 @@ | |
*/ | ||
package org.apache.sshd.client.channel; | ||
|
||
import java.io.EOFException; | ||
import java.io.IOException; | ||
import java.util.Collections; | ||
import java.util.Locale; | ||
import java.util.Map; | ||
import java.util.concurrent.ScheduledExecutorService; | ||
import java.util.concurrent.ScheduledFuture; | ||
import java.util.concurrent.TimeUnit; | ||
import java.util.concurrent.atomic.AtomicReference; | ||
|
||
import org.apache.sshd.common.FactoryManager; | ||
import org.apache.sshd.common.SshConstants; | ||
import org.apache.sshd.common.channel.PtyChannelConfiguration; | ||
import org.apache.sshd.common.channel.PtyChannelConfigurationHolder; | ||
import org.apache.sshd.common.channel.PtyChannelConfigurationMutator; | ||
import org.apache.sshd.common.channel.PtyMode; | ||
import org.apache.sshd.common.io.AbstractIoWriteFuture; | ||
import org.apache.sshd.common.io.IoWriteFuture; | ||
import org.apache.sshd.common.session.Session; | ||
import org.apache.sshd.common.util.GenericUtils; | ||
import org.apache.sshd.common.util.MapEntryUtils; | ||
import org.apache.sshd.common.util.buffer.Buffer; | ||
import org.apache.sshd.common.util.buffer.ByteArrayBuffer; | ||
import org.apache.sshd.core.CoreModuleProperties; | ||
|
||
import static org.apache.sshd.common.SshConstants.SSH_MSG_PING; | ||
import static org.apache.sshd.core.CoreModuleProperties.OBFUSCATE_KEYSTROKE_TIMING; | ||
|
||
/** | ||
* <P> | ||
* Serves as the base channel session for executing remote commands - including a full shell. <B>Note:</B> all the | ||
|
@@ -80,9 +92,12 @@ | |
* @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> | ||
*/ | ||
public class PtyCapableChannelSession extends ChannelSession implements PtyChannelConfigurationMutator { | ||
private static final String PING_MESSAGE = "PING!"; | ||
private boolean agentForwarding; | ||
private boolean usePty; | ||
private int obfuscate; | ||
private final PtyChannelConfiguration config; | ||
private final AtomicReference<ScheduledFuture<?>> chaffFuture = new AtomicReference<>(); | ||
|
||
public PtyCapableChannelSession(boolean usePty, PtyChannelConfigurationHolder configHolder, Map<String, ?> env) { | ||
this.usePty = usePty; | ||
|
@@ -267,8 +282,62 @@ protected void doOpenPty() throws IOException { | |
modes.putByte(PtyMode.TTY_OP_END); | ||
buffer.putBytes(modes.getCompactData()); | ||
writePacket(buffer); | ||
|
||
String obf | ||
= OBFUSCATE_KEYSTROKE_TIMING.get(getSession()).orElse(Boolean.FALSE.toString()).toLowerCase(Locale.ENGLISH); | ||
if (obf.equals("yes") || obf.equals("true")) { | ||
obfuscate = 20; | ||
} else if (obf.equals("no") || obf.equals("false")) { | ||
obfuscate = 0; | ||
} else if (obf.matches("interval:[0-9]{1,5}")) { | ||
obfuscate = Integer.parseInt(obf.substring("interval:".length())); | ||
} else { | ||
log.warn("doOpenPty({}) unrecognized value {} for property {}", this, obf, | ||
OBFUSCATE_KEYSTROKE_TIMING.getName()); | ||
} | ||
} | ||
|
||
sendEnvVariables(session); | ||
} | ||
|
||
@Override | ||
public IoWriteFuture writePacket(Buffer buffer) throws IOException { | ||
if (obfuscate > 0 && buffer.available() < 256) { | ||
log.info("Sending: "); | ||
if (mayWrite()) { | ||
Session s = getSession(); | ||
return s.writePacket(buffer); | ||
} | ||
if (log.isDebugEnabled()) { | ||
log.debug("writePacket({}) Discarding output packet because channel state={}", this, state); | ||
} | ||
return AbstractIoWriteFuture.fulfilled(toString(), new EOFException("Channel is being closed")); | ||
} else { | ||
return super.writePacket(buffer); | ||
} | ||
} | ||
|
||
protected void scheduleChaff() { | ||
FactoryManager manager = getSession().getFactoryManager(); | ||
ScheduledExecutorService service = manager.getScheduledExecutorService(); | ||
long delay = 1024 + manager.getRandomFactory().get().random(2048); | ||
ScheduledFuture<?> future = service.schedule(this::sendChaff, delay, TimeUnit.MILLISECONDS); | ||
future = this.chaffFuture.getAndSet(future); | ||
if (future != null) { | ||
future.cancel(false); | ||
} | ||
} | ||
|
||
protected void sendChaff() { | ||
try { | ||
Buffer buf = getSession().createBuffer(SSH_MSG_PING, PING_MESSAGE.length() + Integer.SIZE); | ||
buf.putString(PING_MESSAGE); | ||
getSession().writePacket(buf); | ||
} catch (IOException e) { | ||
if (log.isDebugEnabled()) { | ||
log.debug("Error sending chaff message", e); | ||
} | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,6 +27,7 @@ | |
|
||
import org.apache.sshd.common.AttributeRepository.AttributeKey; | ||
import org.apache.sshd.common.kex.KexProposalOption; | ||
import org.apache.sshd.common.kex.extension.parser.PingPong; | ||
import org.apache.sshd.common.kex.extension.parser.ServerSignatureAlgorithms; | ||
import org.apache.sshd.common.session.Session; | ||
import org.apache.sshd.common.util.GenericUtils; | ||
|
@@ -157,5 +158,7 @@ public void collectExtensions(Session session, KexPhase phase, BiConsumer<String | |
ServerSignatureAlgorithms.NAME); | ||
} | ||
} | ||
// [email protected] | ||
marshaller.accept(PingPong.NAME, "0"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters