1
0
Fork 0
mirror of https://github.com/vanitasvitae/Smack.git synced 2024-12-01 16:32:08 +01:00

Compare commits

...

10 commits

Author SHA1 Message Date
Florian Schmaus
4dd3800d82 Remove Bouncycastle as direct dependency
By not directly depending on Bouncycastle (BC), we avoid conflicts between
different bouncycastle versions. It is also part of the developers job
to take care that all required security primitives are available. If
they are provide by BC or some other security provider should not be
up to Smack to decide.

We now only add BC as test dependency to satisfy this requirement when
the unit tests are executed.
2020-03-13 16:58:45 +01:00
Florian Schmaus
4beaae7d6a disco: avoid boxing to Integer when not necessary 2020-03-13 16:41:27 +01:00
Florian Schmaus
39a833166a Add workaround for truststores in JKS format when using Java >= 9 2020-03-13 16:40:46 +01:00
Florian Schmaus
863d0bf403 Fix NPE in ServiceDiscoveryManager 2020-03-09 14:41:52 +01:00
Florian Schmaus
00dd77b346 Try to guess the default truststore and path
Tested with OpenJDK 8 and 11. The 'JKS' fallback is for OpenJDK 11.
2020-03-09 13:39:19 +01:00
Florian Schmaus
6440f322fe Ensure a X509TrustManager is set 2020-03-09 10:12:43 +01:00
Florian Schmaus
9a081e621d gradle: use compileClasspath instead of compileOnly
In the previous commit 46ddf071b ("gradle: add Android jar to
smack-android-extensions compile classpath") we already added the
Android jar using compileClasspath to smack-android-extensions. Now
use the same configuration for smack-android, since compileOnly is
deprecated.
2020-03-07 20:13:05 +01:00
Florian Schmaus
7b002ea214 gradle: add Android jar to smack-android-extensions compile classpath 2020-03-07 20:13:05 +01:00
Florian Schmaus
f7eaa3cc9e gradle: smack-omemo(-signal) add description, remove plugins
As those plugins are already configured by the projects root
build.gradle file, there is no need to apply them again.
2020-03-07 20:13:05 +01:00
Florian Schmaus
650deda752 gradle: remove unnecessary repositories{} from smack-openpgp/build.gradle
The MavenCentral repository is already configured by the projects root
build.gradle file. No need to do it again in the subproject.
2020-03-07 20:12:18 +01:00
19 changed files with 168 additions and 44 deletions

View file

@ -6,4 +6,7 @@ Extra Smack extensions for Android."""
dependencies {
compile project(':smack-android')
compile project(':smack-extensions')
// Add the Android jar to the Eclipse .classpath.
compileClasspath files(androidBootClasspath)
}

View file

@ -24,5 +24,5 @@ dependencies {
}
// Add the Android jar to the Eclipse .classpath.
compileOnly files(androidBootClasspath)
compileClasspath files(androidBootClasspath)
}

View file

@ -24,6 +24,7 @@ dependencies {
testCompile "org.assertj:assertj-core:3.11.1"
testCompile "org.xmlunit:xmlunit-assertj:$xmlUnitVersion"
testCompile 'com.jamesmurty.utils:java-xmlbuilder:1.2'
testCompile 'org.bouncycastle:bcprov-jdk15on:1.64'
}
class CreateFileTask extends DefaultTask {

View file

@ -135,6 +135,7 @@ import org.jivesoftware.smack.util.PacketParserUtils;
import org.jivesoftware.smack.util.ParserUtils;
import org.jivesoftware.smack.util.Predicate;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smack.util.TLSUtils;
import org.jivesoftware.smack.util.dns.HostAddress;
import org.jivesoftware.smack.util.dns.SmackDaneProvider;
import org.jivesoftware.smack.util.dns.SmackDaneVerifier;
@ -2303,7 +2304,28 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
ks = null;
}
} else {
ks.load(null, null);
InputStream stream = TLSUtils.getDefaultTruststoreStreamIfPossible();
try {
// Note that PKCS12 keystores need a password one some Java platforms. Hence we try the famous
// 'changeit' here. See https://bugs.openjdk.java.net/browse/JDK-8194702
char[] password = "changeit".toCharArray();
try {
ks.load(stream, password);
} finally {
stream.close();
}
} catch (IOException e) {
LOGGER.log(Level.FINE, "KeyStore load() threw, attempting 'jks' fallback", e);
ks = KeyStore.getInstance("jks");
// Open the stream again, so that we read it from the beginning.
stream = TLSUtils.getDefaultTruststoreStreamIfPossible();
try {
ks.load(stream, null);
} finally {
stream.close();
}
}
}
}
@ -2340,16 +2362,16 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
context = SSLContext.getInstance("TLS");
final SecureRandom secureRandom = new java.security.SecureRandom();
X509TrustManager customTrustManager = config.getCustomX509TrustManager();
X509TrustManager trustManager = config.getCustomX509TrustManager();
if (trustManager == null) {
trustManager = TLSUtils.getDefaultX509TrustManager(ks);
}
if (daneVerifier != null) {
// User requested DANE verification.
daneVerifier.init(context, kms, customTrustManager, secureRandom);
daneVerifier.init(context, kms, trustManager, secureRandom);
} else {
TrustManager[] customTrustManagers = null;
if (customTrustManager != null) {
customTrustManagers = new TrustManager[] { customTrustManager };
}
TrustManager[] customTrustManagers = new TrustManager[] { trustManager };
context.init(kms, customTrustManagers, secureRandom);
}
}

View file

@ -162,6 +162,14 @@ public abstract class StanzaBuilder<B extends StanzaBuilder<B>> implements Stanz
return getThis();
}
public final B addOptExtensions(Collection<? extends ExtensionElement> extensionElements) {
if (extensionElements == null) {
return getThis();
}
return addExtensions(extensionElements);
}
public final B addExtensions(Collection<? extends ExtensionElement> extensionElements) {
for (ExtensionElement extensionElement : extensionElements) {
addExtension(extensionElement);

View file

@ -1,6 +1,6 @@
/**
*
* Copyright 2014-2016 Florian Schmaus
* Copyright 2014-2020 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,7 +16,15 @@
*/
package org.jivesoftware.smack.util;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
@ -27,6 +35,8 @@ import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
@ -34,6 +44,7 @@ import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import org.jivesoftware.smack.ConnectionConfiguration;
@ -42,6 +53,8 @@ import org.jivesoftware.smack.SmackException.SecurityNotPossibleException;
public class TLSUtils {
private static final Logger LOGGER = Logger.getLogger(TLSUtils.class.getName());
public static final String SSL = "SSL";
public static final String TLS = "TLS";
public static final String PROTO_SSL3 = SSL + "v3";
@ -240,4 +253,86 @@ public class TLSUtils {
return new X509Certificate[0];
}
}
public static X509TrustManager getDefaultX509TrustManager(KeyStore keyStore) {
String defaultAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory trustManagerFactory;
try {
trustManagerFactory = TrustManagerFactory.getInstance(defaultAlgorithm);
trustManagerFactory.init(keyStore);
} catch (NoSuchAlgorithmException | KeyStoreException e) {
throw new AssertionError(e);
}
for (TrustManager trustManager : trustManagerFactory.getTrustManagers()) {
if (trustManager instanceof X509TrustManager) {
return (X509TrustManager) trustManager;
}
}
throw new AssertionError("No trust manager for the default algorithm " + defaultAlgorithm + " found");
}
private static final File DEFAULT_TRUSTSTORE_PATH;
static {
String javaHome = System.getProperty("java.home");
String defaultTruststorePath = javaHome + File.separator + "lib" + File.separator + "security" + File.separator + "cacerts";
DEFAULT_TRUSTSTORE_PATH = new File(defaultTruststorePath);
}
public static FileInputStream getDefaultTruststoreStreamIfPossible() {
try {
return new FileInputStream(DEFAULT_TRUSTSTORE_PATH);
} catch (FileNotFoundException e) {
LOGGER.log(Level.WARNING, "Could not open default truststore at " + DEFAULT_TRUSTSTORE_PATH, e);
return null;
}
}
enum DefaultTrustStoreType {
jks,
unknown,
no_default,
}
private static final int JKS_MAGIC = 0xfeedfeed;
private static final int JKS_VERSION_1 = 1;
private static final int JKS_VERSION_2 = 2;
public static DefaultTrustStoreType getDefaultTruststoreType() throws IOException {
try (InputStream inputStream = getDefaultTruststoreStreamIfPossible()) {
if (inputStream == null) {
return DefaultTrustStoreType.no_default;
}
DataInputStream dis = new DataInputStream(inputStream);
int magic = dis.readInt();
int version = dis.readInt();
if (magic == JKS_MAGIC && (version == JKS_VERSION_1 || version == JKS_VERSION_2)) {
return DefaultTrustStoreType.jks;
}
}
return DefaultTrustStoreType.unknown;
}
/**
* Tries to determine if the default truststore type is of type jks and sets the javax.net.ssl.trustStoreType system
* property to 'JKS' if so. This is meant as workaround in situations where the default truststore type is (still)
* 'jks' but we run on a newer JRE/JDK which uses PKCS#12 as type. See for example <a href="https://bugs.gentoo.org/712290">Gentoo bug #712290</a>.
*/
public static void setDefaultTrustStoreTypeToJksIfRequired() {
DefaultTrustStoreType defaultTrustStoreType;
try {
defaultTrustStoreType = getDefaultTruststoreType();
} catch (IOException e) {
LOGGER.log(Level.WARNING, "Could not set keystore type to jks if required", e);
return;
}
if (defaultTrustStoreType == DefaultTrustStoreType.jks) {
System.setProperty("javax.net.ssl.trustStoreType", "JKS");
}
}
}

View file

@ -1,6 +1,6 @@
/**
*
* Copyright © 2014-2019 Florian Schmaus
* Copyright © 2014-2020 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,11 +16,14 @@
*/
package org.jivesoftware.smack.test.util;
import java.security.Security;
import java.util.Base64;
import org.jivesoftware.smack.SmackConfiguration;
import org.jivesoftware.smack.util.stringencoder.Base64.Encoder;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
/**
* The SmackTestSuite takes care of initializing Smack for the unit tests. For example the Base64
* encoder is configured.
@ -52,5 +55,7 @@ public class SmackTestSuite {
}
});
Security.addProvider(new BouncyCastleProvider());
}
}

View file

@ -10,6 +10,5 @@ dependencies {
testCompile project(path: ":smack-core", configuration: "testRuntime")
testCompile project(path: ":smack-extensions", configuration: "testRuntime")
compile "org.bouncycastle:bcprov-jdk15on:$bouncyCastleVersion"
compile "org.hsluv:hsluv:0.2"
}

View file

@ -1,6 +1,6 @@
/**
*
* Copyright © 2017 Paul Schaub, 2019 Florian Schmaus
* Copyright © 2017 Paul Schaub, 2019-2020 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -42,13 +42,10 @@ import java.util.WeakHashMap;
import org.jivesoftware.smack.Manager;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.util.SecurityUtil;
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
import org.jivesoftware.smackx.hashes.element.HashElement;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
/**
* Manager that can be used to determine support for hash functions. By default the Manager announces support for
* XEP-0300, as well as for the recommended set of hash algorithms. Those contain SHA256, SHA384, SHA512, SHA3-256,
@ -57,12 +54,6 @@ import org.bouncycastle.jce.provider.BouncyCastleProvider;
*/
public final class HashManager extends Manager {
static {
// Remove any BC providers and add a fresh one.
// This is done, since older Android versions ship with a crippled BC provider.
SecurityUtil.ensureProviderAtFirstPosition(BouncyCastleProvider.class);
}
public static final String PREFIX_NS_ALGO = "urn:xmpp:hash-function-text-names:";
public enum NAMESPACE {

View file

@ -18,9 +18,12 @@ package org.jivesoftware.smackx.hashes;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.security.Security;
import org.jivesoftware.smack.test.util.SmackTestSuite;
import org.jivesoftware.smack.util.StringUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.junit.jupiter.api.Test;
/**
@ -30,6 +33,10 @@ import org.junit.jupiter.api.Test;
*/
public class HashTest extends SmackTestSuite {
static {
Security.addProvider(new BouncyCastleProvider());
}
private static final String testString = "Hello World!";
private static final String md5sum = "ed076287532e86365e841e92bfc50d8c";
private static final String sha1sum = "2ef7bde608ce5404e97d5f042f95f89f1c232871";

View file

@ -1,6 +1,6 @@
/**
*
* Copyright 2018 Florian Schmaus.
* Copyright 2018-2020 Florian Schmaus.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -47,7 +47,7 @@ public abstract class DiscoInfoLookupShortcutMechanism implements Comparable<Dis
@Override
public final int compareTo(DiscoInfoLookupShortcutMechanism other) {
Integer ourPriority = getPriority();
int ourPriority = getPriority();
return Integer.compare(ourPriority, other.getPriority());
}
}

View file

@ -178,7 +178,7 @@ public final class ServiceDiscoveryManager extends Manager {
// Add node identities
responseBuilder.addIdentities(nodeInformationProvider.getNodeIdentities());
// Add packet extensions
responseBuilder.addExtensions(nodeInformationProvider.getNodePacketExtensions());
responseBuilder.addOptExtensions(nodeInformationProvider.getNodePacketExtensions());
} else {
// Return <item-not-found/> error since specified node was not found
responseBuilder.ofType(IQ.Type.error);

View file

@ -1,6 +1,6 @@
/**
*
* Copyright 2015-2019 Florian Schmaus
* Copyright 2015-2020 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -56,6 +56,7 @@ import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smack.util.TLSUtils;
import org.jivesoftware.smackx.debugger.EnhancedDebuggerWindow;
import org.jivesoftware.smackx.iqregister.AccountManager;
@ -71,6 +72,10 @@ import org.reflections.scanners.TypeAnnotationsScanner;
public class SmackIntegrationTestFramework<DC extends AbstractXMPPConnection> {
static {
TLSUtils.setDefaultTrustStoreTypeToJksIfRequired();
}
private static final Logger LOGGER = Logger.getLogger(SmackIntegrationTestFramework.class.getName());
public static boolean SINTTEST_UNIT_TEST = false;

View file

@ -1,5 +1,6 @@
apply plugin: 'checkstyle'
apply plugin: 'maven'
description="""
Smack API for XEP-0384: OMEMO Encryption using libsignal
"""
dependencies {
compile project(":smack-im")

View file

@ -1,9 +1,11 @@
description="""
Smack API for XEP-0384: OMEMO Encryption
"""
dependencies {
compile project(":smack-im")
compile project(":smack-extensions")
compile project(":smack-experimental")
compile "org.bouncycastle:bcprov-jdk15on:$bouncyCastleVersion"
testCompile project(path: ":smack-core", configuration: "testRuntime")
}

View file

@ -17,9 +17,6 @@
package org.jivesoftware.smackx.omemo;
import org.jivesoftware.smack.initializer.UrlInitializer;
import org.jivesoftware.smack.util.SecurityUtil;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
/**
* Initializer class that registers omemo providers.
@ -29,12 +26,6 @@ import org.bouncycastle.jce.provider.BouncyCastleProvider;
@SuppressWarnings("unused")
public class OmemoInitializer extends UrlInitializer {
static {
// Remove any BC providers and add a fresh one.
// This is done, since older Android versions ship with a crippled BC provider.
SecurityUtil.ensureProviderAtFirstPosition(BouncyCastleProvider.class);
}
@Override
protected String getProvidersUri() {
return "classpath:org.jivesoftware.smackx.omemo/omemo.providers";

View file

@ -27,7 +27,6 @@ import static org.junit.Assert.assertNotNull;
import java.security.NoSuchAlgorithmException;
import org.jivesoftware.smack.test.util.SmackTestSuite;
import org.jivesoftware.smackx.omemo.element.OmemoElement;
import org.jivesoftware.smackx.omemo.exceptions.CryptoFailedException;
import org.jivesoftware.smackx.omemo.internal.CipherAndAuthTag;

View file

@ -1,10 +1,6 @@
description = """\
Smack API for XEP-0373: OpenPGP for XMPP."""
repositories {
mavenCentral()
}
// Note that the test dependencies (junit, ) are inferred from the
// sourceSet.test of the core subproject
dependencies {

View file

@ -10,7 +10,6 @@ allprojects {
// - https://issues.igniterealtime.org/browse/SMACK-858
jxmppVersion = '0.7.0-alpha5'
miniDnsVersion = '0.4.0-alpha3'
bouncyCastleVersion = '1.62'
smackMinAndroidSdk = 19
}
}