Skip to content

Commit

Permalink
GH-618: Fix reading an OpenSshCertificate from a Buffer
Browse files Browse the repository at this point in the history
Buffer.getBytesConsumed() is broken. It'll return wrong data for buffers
created on a slice of an array not starting at zero. Using it in
OpenSSHCertPublicKeyParser will return data before the raw certificate
in the buffer if that raw certificate is not the first thing in the
buffer.

Fix this by adding a Buffer.getBytesConsumed(int from) method, and use
that in OpenSSHCertPublicKeyParser.

Bug: #618
  • Loading branch information
tomaswolf committed Oct 7, 2024
1 parent 4748eae commit dfa9b06
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 5 deletions.
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@

## Bug Fixes

* [GH-618](https://github.com/apache/mina-sshd/issues/618) Fix reading an `OpenSshCertificate` from a `Buffer`

## New Features

## Potential compatibility issues
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,11 @@ protected Buffer() {
*/
public abstract byte[] getBytesConsumed();

/**
* @return The bytes consumed since the given position
*/
public abstract byte[] getBytesConsumed(int from);

/**
* @param pos A position in the <U>raw</U> underlying data bytes
* @return The byte at the specified position without changing the current {@link #rpos() read position}.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,14 @@ public byte[] getBytesConsumed() {
return consumed;
}

@Override
public byte[] getBytesConsumed(int from) {
if (from >= rpos) {
return new byte[0];
}
return Arrays.copyOfRange(data, from, rpos);
}

@Override
public byte rawByte(int pos) {
return data[pos];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public OpenSSHCertPublicKeyParser() {
public OpenSshCertificate getRawPublicKey(String keyType, Buffer buffer) throws GeneralSecurityException {
OpenSshCertificateImpl certificate = new OpenSshCertificateImpl();
certificate.setKeyType(keyType);
final int pos = buffer.rpos();

certificate.setNonce(buffer.getBytes());

Expand Down Expand Up @@ -84,7 +85,10 @@ public OpenSshCertificate getRawPublicKey(String keyType, Buffer buffer) throws
throw new InvalidKeyException("Could not parse public CA key with ID: " + certificate.getId(), ex);
}

certificate.setMessage(buffer.getBytesConsumed());
Buffer tmp = new ByteArrayBuffer();
tmp.putString(keyType);
tmp.putRawBytes(buffer.getBytesConsumed(pos));
certificate.setMessage(tmp.getCompactData());
certificate.setSignature(buffer.getBytes());

if (buffer.rpos() != buffer.wpos()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,14 @@
import org.apache.sshd.common.config.keys.PublicKeyEntry;
import org.apache.sshd.common.signature.Signature;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.buffer.Buffer;
import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
import org.apache.sshd.common.util.io.IoUtils;
import org.apache.sshd.util.test.BaseTestSupport;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

@Tag("NoIoTestCase") // see https://github.com/junit-team/junit/wiki/Parameterized-tests
public class OpenSSHCertificateParserTest extends BaseTestSupport {

Expand Down Expand Up @@ -108,6 +106,13 @@ public void parseCertificate(TestParams params) throws Exception {
typedCert.getExtensions());
assertEquals(params.sigAlgorithm, typedCert.getSignatureAlgorithm());
verifySignature(typedCert);
Buffer buffer = new ByteArrayBuffer();
buffer.putPublicKey(typedCert);
PublicKey readFromBuffer = buffer.getPublicKey();
assertTrue(readFromBuffer instanceof OpenSshCertificate,
() -> "Expected an OpenSshCertificate but got " + readFromBuffer.getClass().getName());
OpenSshCertificate readBack = (OpenSshCertificate) readFromBuffer;
verifySignature(readBack);
}
}

Expand Down

0 comments on commit dfa9b06

Please sign in to comment.