Skip to content

Commit 9ef3d78

Browse files
committed
Merge branch 'master' into 3.0.0
2 parents d087c40 + d63179e commit 9ef3d78

13 files changed

Lines changed: 371 additions & 15 deletions

File tree

sshd-common/src/main/java/org/apache/sshd/common/config/keys/KeyUtils.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1039,6 +1039,7 @@ public static boolean compareSkEcdsaKeys(SkEcdsaPublicKey k1, SkEcdsaPublicKey k
10391039
}
10401040
return Objects.equals(k1.getAppName(), k2.getAppName())
10411041
&& Objects.equals(k1.isNoTouchRequired(), k2.isNoTouchRequired())
1042+
&& Objects.equals(k1.isVerifyRequired(), k2.isVerifyRequired())
10421043
&& compareECKeys(k1.getDelegatePublicKey(), k2.getDelegatePublicKey());
10431044
}
10441045

@@ -1050,6 +1051,7 @@ public static boolean compareSkEd25519Keys(SkED25519PublicKey k1, SkED25519Publi
10501051
}
10511052
return Objects.equals(k1.getAppName(), k2.getAppName())
10521053
&& Objects.equals(k1.isNoTouchRequired(), k2.isNoTouchRequired())
1054+
&& Objects.equals(k1.isVerifyRequired(), k2.isVerifyRequired())
10531055
&& SecurityUtils.compareEDDSAPPublicKeys(k1.getDelegatePublicKey(), k2.getDelegatePublicKey());
10541056
}
10551057

sshd-common/src/main/java/org/apache/sshd/common/config/keys/impl/SkECDSAPublicKeyEntryDecoder.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ public class SkECDSAPublicKeyEntryDecoder extends AbstractPublicKeyEntryDecoder<
4848
public static final SkECDSAPublicKeyEntryDecoder INSTANCE = new SkECDSAPublicKeyEntryDecoder();
4949

5050
private static final String NO_TOUCH_REQUIRED_HEADER = "no-touch-required";
51+
private static final String VERIFY_REQUIRED_HEADER = "verify-required";
5152

5253
public SkECDSAPublicKeyEntryDecoder() {
5354
super(SkEcdsaPublicKey.class, PrivateKey.class, Collections.singleton(KEY_TYPE));
@@ -62,9 +63,10 @@ public SkEcdsaPublicKey decodePublicKey(
6263
}
6364

6465
boolean noTouchRequired = parseBooleanHeader(headers, NO_TOUCH_REQUIRED_HEADER, false);
66+
boolean verifyRequired = parseBooleanHeader(headers, VERIFY_REQUIRED_HEADER, false);
6567
ECPublicKey ecPublicKey = ECDSAPublicKeyEntryDecoder.INSTANCE.decodePublicKey(ECCurves.nistp256, keyData);
6668
String appName = KeyEntryResolver.decodeString(keyData, MAX_APP_NAME_LENGTH);
67-
return new SkEcdsaPublicKey(appName, noTouchRequired, ecPublicKey);
69+
return new SkEcdsaPublicKey(appName, noTouchRequired, verifyRequired, ecPublicKey);
6870
}
6971

7072
@Override

sshd-common/src/main/java/org/apache/sshd/common/config/keys/impl/SkED25519PublicKeyEntryDecoder.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ public class SkED25519PublicKeyEntryDecoder extends AbstractPublicKeyEntryDecode
5151
public static final SkED25519PublicKeyEntryDecoder INSTANCE = new SkED25519PublicKeyEntryDecoder();
5252

5353
private static final String NO_TOUCH_REQUIRED_HEADER = "no-touch-required";
54+
private static final String VERIFY_REQUIRED_HEADER = "verify-required";
5455

5556
public SkED25519PublicKeyEntryDecoder() {
5657
super(SkED25519PublicKey.class, PrivateKey.class, Collections.singleton(KEY_TYPE));
@@ -65,10 +66,11 @@ public SkED25519PublicKey decodePublicKey(
6566
}
6667

6768
boolean noTouchRequired = parseBooleanHeader(headers, NO_TOUCH_REQUIRED_HEADER, false);
69+
boolean verifyRequired = parseBooleanHeader(headers, VERIFY_REQUIRED_HEADER, false);
6870
PublicKey pk = SecurityUtils.getEDDSAPublicKeyEntryDecoder().decodePublicKey(session, KeyPairProvider.SSH_ED25519,
6971
keyData, headers);
7072
String appName = KeyEntryResolver.decodeString(keyData, MAX_APP_NAME_LENGTH);
71-
return new SkED25519PublicKey(appName, noTouchRequired, pk);
73+
return new SkED25519PublicKey(appName, noTouchRequired, verifyRequired, pk);
7274
}
7375

7476
@Override

sshd-common/src/main/java/org/apache/sshd/common/config/keys/u2f/SecurityKeyPublicKey.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,12 @@
2323
import org.apache.sshd.common.config.keys.SshPublicKey;
2424

2525
public interface SecurityKeyPublicKey<K extends PublicKey> extends SshPublicKey {
26+
2627
String getAppName();
2728

2829
boolean isNoTouchRequired();
2930

31+
boolean isVerifyRequired();
32+
3033
K getDelegatePublicKey();
3134
}

sshd-common/src/main/java/org/apache/sshd/common/config/keys/u2f/SkED25519PublicKey.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,26 @@ public class SkED25519PublicKey implements SecurityKeyPublicKey<PublicKey> {
3434

3535
private final String appName;
3636
private final boolean noTouchRequired;
37+
private final boolean verifyRequired;
3738
private final PublicKey delegatePublicKey;
3839

40+
/**
41+
* Creates a new instance.
42+
*
43+
* @param appName application name
44+
* @param noTouchRequired whether the "no-touch-required" flag was present in authorized_keys
45+
* @param delegatePublicKey the underlying real public key
46+
* @deprecated use {@link #SkED25519PublicKey(String, boolean, boolean, PublicKey)} instead
47+
*/
48+
@Deprecated
3949
public SkED25519PublicKey(String appName, boolean noTouchRequired, PublicKey delegatePublicKey) {
50+
this(appName, noTouchRequired, false, delegatePublicKey);
51+
}
52+
53+
public SkED25519PublicKey(String appName, boolean noTouchRequired, boolean verifyRequired, PublicKey delegatePublicKey) {
4054
this.appName = appName;
4155
this.noTouchRequired = noTouchRequired;
56+
this.verifyRequired = verifyRequired;
4257
ValidateUtils.checkTrue(KeyPairProvider.SSH_ED25519.equals(KeyUtils.getKeyType(delegatePublicKey)),
4358
"Key is not an ed25519 key");
4459
this.delegatePublicKey = delegatePublicKey;
@@ -74,6 +89,11 @@ public boolean isNoTouchRequired() {
7489
return noTouchRequired;
7590
}
7691

92+
@Override
93+
public boolean isVerifyRequired() {
94+
return verifyRequired;
95+
}
96+
7797
@Override
7898
public PublicKey getDelegatePublicKey() {
7999
return delegatePublicKey;
@@ -84,6 +104,7 @@ public String toString() {
84104
return getClass().getSimpleName()
85105
+ "[appName=" + getAppName()
86106
+ ", noTouchRequired=" + isNoTouchRequired()
107+
+ ", verifyRequired=" + isVerifyRequired()
87108
+ ", delegatePublicKey=" + getDelegatePublicKey()
88109
+ "]";
89110
}

sshd-common/src/main/java/org/apache/sshd/common/config/keys/u2f/SkEcdsaPublicKey.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,26 @@ public class SkEcdsaPublicKey implements SecurityKeyPublicKey<ECPublicKey> {
3131

3232
private final String appName;
3333
private final boolean noTouchRequired;
34+
private final boolean verifyRequired;
3435
private final ECPublicKey delegatePublicKey;
3536

37+
/**
38+
* Creates a new instance.
39+
*
40+
* @param appName application name
41+
* @param noTouchRequired whether the "no-touch-required" flag was present in authorized_keys
42+
* @param delegatePublicKey the underlying real public key
43+
* @deprecated use {@link #SkEcdsaPublicKey(String, boolean, boolean, ECPublicKey)} instead
44+
*/
45+
@Deprecated
3646
public SkEcdsaPublicKey(String appName, boolean noTouchRequired, ECPublicKey delegatePublicKey) {
47+
this(appName, noTouchRequired, false, delegatePublicKey);
48+
}
49+
50+
public SkEcdsaPublicKey(String appName, boolean noTouchRequired, boolean verifyRequired, ECPublicKey delegatePublicKey) {
3751
this.appName = appName;
3852
this.noTouchRequired = noTouchRequired;
53+
this.verifyRequired = verifyRequired;
3954
this.delegatePublicKey = delegatePublicKey;
4055
}
4156

@@ -69,6 +84,11 @@ public boolean isNoTouchRequired() {
6984
return noTouchRequired;
7085
}
7186

87+
@Override
88+
public boolean isVerifyRequired() {
89+
return verifyRequired;
90+
}
91+
7292
@Override
7393
public ECPublicKey getDelegatePublicKey() {
7494
return delegatePublicKey;
@@ -79,6 +99,7 @@ public String toString() {
7999
return getClass().getSimpleName()
80100
+ "[appName=" + getAppName()
81101
+ ", noTouchRequired=" + isNoTouchRequired()
102+
+ ", verifyRequired=" + isVerifyRequired()
82103
+ ", delegatePublicKey=" + getDelegatePublicKey()
83104
+ "]";
84105
}

sshd-common/src/main/java/org/apache/sshd/common/signature/AbstractSecurityKeySignature.java

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,18 @@
2323
import java.security.MessageDigest;
2424
import java.security.PrivateKey;
2525
import java.security.PublicKey;
26+
import java.security.SignatureException;
2627

2728
import org.apache.sshd.common.config.keys.u2f.SecurityKeyPublicKey;
2829
import org.apache.sshd.common.session.SessionContext;
2930
import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
3031
import org.apache.sshd.common.util.security.SecurityUtils;
3132

3233
public abstract class AbstractSecurityKeySignature implements Signature {
33-
private static final int FLAG_USER_PRESENCE = 0x01;
34+
35+
private static final int FLAG_USER_PRESENCE = 1 << 0;
36+
37+
private static final int FLAG_VERIFIED = 1 << 2;
3438

3539
private final String keyType;
3640
private SecurityKeyPublicKey<?> publicKey;
@@ -76,14 +80,17 @@ public boolean verify(SessionContext session, byte[] sig) throws Exception {
7680
byte flags = data.getByte();
7781
long counter = data.getUInt();
7882

79-
// Return false if we don't understand the flags
80-
if ((flags & ~FLAG_USER_PRESENCE) != 0) {
81-
return false;
82-
}
8383
// Check user-presence flag is present if required by the public key
8484
if ((flags & FLAG_USER_PRESENCE) != FLAG_USER_PRESENCE && !publicKey.isNoTouchRequired()) {
8585
return false;
8686
}
87+
if ((flags & FLAG_VERIFIED) != FLAG_VERIFIED && publicKey.isVerifyRequired()) {
88+
return false;
89+
}
90+
91+
if (data.available() > 0) {
92+
throw new SignatureException("Unexpected trailing data in signature");
93+
}
8794

8895
// Re-encode signature in a format to match the delegate
8996
ByteArrayBuffer encoded = new ByteArrayBuffer();

sshd-common/src/main/java/org/apache/sshd/common/util/buffer/keys/SkECBufferPublicKeyParser.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,6 @@ public SkEcdsaPublicKey getRawPublicKey(String keyType, Buffer buffer) throws Ge
4343
// with an appname on the end
4444
ECPublicKey ecPublicKey = ECBufferPublicKeyParser.INSTANCE.getRawPublicKey(ECCurves.nistp256.getKeyType(), buffer);
4545
String appName = buffer.getString();
46-
return new SkEcdsaPublicKey(appName, false, ecPublicKey);
46+
return new SkEcdsaPublicKey(appName, false, false, ecPublicKey);
4747
}
4848
}

sshd-common/src/main/java/org/apache/sshd/common/util/buffer/keys/SkED25519BufferPublicKeyParser.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,6 @@ public SkED25519PublicKey getRawPublicKey(String keyType, Buffer buffer) throws
4343
// the end
4444
PublicKey publicKey = ED25519BufferPublicKeyParser.INSTANCE.getRawPublicKey(KeyPairProvider.SSH_ED25519, buffer);
4545
String appName = buffer.getString();
46-
return new SkED25519PublicKey(appName, false, publicKey);
46+
return new SkED25519PublicKey(appName, false, false, publicKey);
4747
}
4848
}

sshd-core/src/main/java/org/apache/sshd/server/auth/pubkey/AuthorizedKeyEntriesPublickeyAuthenticator.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,7 @@ public AuthorizedKeyEntriesPublickeyAuthenticator(Object id, ServerSession sessi
6161
} else {
6262
resolvedKeys = new HashMap<>(numEntries);
6363
for (AuthorizedKeyEntry e : entries) {
64-
Map<String, String> headers = e.getLoginOptions();
65-
PublicKey k = e.resolvePublicKey(session, headers, fallbackResolver);
64+
PublicKey k = e.resolvePublicKey(session, Collections.emptyMap(), fallbackResolver);
6665
if (k != null) {
6766
resolvedKeys.put(e, k);
6867
}

0 commit comments

Comments
 (0)