Skip to content

Commit

Permalink
merge update
Browse files Browse the repository at this point in the history
  • Loading branch information
ramabit committed Oct 31, 2016
2 parents 96c05dc + 1d3c48e commit 4a02a61
Show file tree
Hide file tree
Showing 60 changed files with 2,324 additions and 247 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ before_install:
- export PATH="$(pwd)/gradle-${GRADLE_VERSION}/bin:$PATH"

install: gradle assemble --stacktrace
script: gradle check
script: gradle check --stacktrace

after_success:
- JAVAC_VERSION=$((javac -version) 2>&1)
Expand Down
75 changes: 75 additions & 0 deletions documentation/dnssec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
DNSSEC and DANE
===============

[Back](index.md)

**DNSSEC and DANE support in Smack and MiniDNS is still in its
infancy. It should be considered experimental and not ready for
production use at this time.** We would like to see more thorough
testing and review by the security community. If you can help, then
please do not hesitate to contact us.

About
-----

DNSSEC ([RFC 4033](https://tools.ietf.org/html/rfc4033) and others)
authenticates DNS answers, positive and negative ones. This means that
if a DNS response secured by DNSSEC turns out to be authentic, then
you can be sure that the domain either exists, and that the returned
resource records (RRs) are the ones the domain owner authorized, or
that the domain does not exists and that nobody tried to fake its non
existence.

The tricky part is that an application using DNSSEC can not determine
whether a domain uses DNSSEC, does not use DNSSEC or if someone
downgraded your DNS query using DNSSEC to a response without DNSSEC.

[DANE](https://tools.ietf.org/html/rfc6698) allows the verification of
a TLS certificate with information stored in the DNS system and
secured by DNSSEC. Thus DANE requires DNSSEC.

Prerequisites
-------------

From the three DNS resolver providers (MiniDNS, javax, dnsjava)
supported by Smack only [MiniDNS](https://github.com/rtreffer/minidns)
currently supports DNSSEC. MiniDNS is the default resolver when
smack-android is used. For other configurations, make sure to add
smack-resolver-minidns to your dependencies and call
`MiniDnsResolver.setup()` prior using Smack (e.g. in a `static {}`
code block).

DNSSEC API
----------

Smack's DNSSEC API is very simple: Just use
`ConnectionConfiguration.Builder..setDnssecMode(DnssecMode)` to enable
DNSSEC. `DnssecMode` can be one of

- `disabled`
- `needsDnssec`
- `needsDnssecAndDane`

The default is `disabled`.

If `needsDnssec` is used, then Smack will only connect if the DNS
results required to determine a host for the XMPP domain could be
verified using DNSSEC.

If `needsDnssecAndDane` then DANE will be used to verify the XMPP
service's TLS certificate if STARTTLS is used. Note that you may want
to configure
`ConnectionConfiguration.Builder.setSecurityMode(SecurityMode.required)`
if you use this DNSSEC mode setting.

Best practices
--------------

We recommend that applications using Smack's DNSSEC API do not ask the
user if DNSSEC is avaialble. Instead they should check for DNSSEC
suport on every connection attempt. Once DNSSEC support has been
discovered, the application should use the `needsDnssec` mode for all
future connection attempts. The same scheme can be applied when using
DANE. This approach is similar to the scheme established by
to
["HTTP Strict Transport Security" (HSTS, RFC 6797)](https://tools.ietf.org/html/rfc6797).
63 changes: 63 additions & 0 deletions documentation/extensions/blockingcommand.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
Blocking Command
================

Allows to manage communications blocking.

* Check push notifications support
* Get blocking list
* Block contact
* Unblock contact
* Unblock all


**XEP related:** [XEP-0191](http://xmpp.org/extensions/xep-0191.html)


Get an instance of Blocking Command Manager
-------------------------------------------

```
BlockingCommandManager blockingCommandManager = BlockingCommandManager.getInstanceFor(connection);
```


Check blocking command support
------------------------------

```
boolean isSupported = blockingCommandManager.isSupportedByServer();
```


Get block list
--------------

```
List<Jid> blockList = blockingCommandManager.getBlockList();
```


Block contact
-------------

```
blockingCommandManager.blockContact(jid);
```
*jid* is a `Jid`


Unblock contact
---------------

```
blockingCommandManager.unblockContact(jid);
```
*jid* is a `Jid`


Unblock all
-----------

```
blockingCommandManager.unblockAll();
```
8 changes: 4 additions & 4 deletions documentation/extensions/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ Smack Extensions and currently supported XEPs of smack-extensions
| Data Forms Layout | [XEP-0141](http://xmpp.org/extensions/xep-0141.html) | Enables an application to specify form layouts. |
| Personal Eventing Protocol | [XEP-0163](http://xmpp.org/extensions/xep-0163.html) | Using the XMPP publish-subscribe protocol to broadcast state change events associated with an XMPP account. |
| Message Delivery Receipts | [XEP-0184](http://xmpp.org/extensions/xep-0184.html) | Extension for message delivery receipts. The sender can request notification that the message has been delivered. |
| [Blocking Command](blockingcommand.md) | [XEP-0191](http://xmpp.org/extensions/xep-0191.html) | Communications blocking that is intended to be simpler than privacy lists (XEP-0016). |
| XMPP Ping | [XEP-0199](http://xmpp.org/extensions/xep-0199.html) | Sending application-level pings over XML streams.
| Entity Time | [XEP-0202](http://xmpp.org/extensions/xep-0202.html) | Allows entities to communicate their local time |
| Delayed Delivery | [XEP-0203](http://xmpp.org/extensions/xep-0203.html) | Extension for communicating the fact that an XML stanza has been delivered with a delay. |
Expand All @@ -78,16 +79,16 @@ Experimental Smack Extensions and currently supported XEPs of smack-experimental

| Name | XEP | Description |
|---------------------------------------------|----------------------------------------------------------|----------------------------------------------------------------------------------------------------------|
| Message Carbons | [XEP-0280](http://xmpp.org/extensions/xep-0280.html) | Keep all IM clients for a user engaged in a conversation, by carbon-copy outbound messages to all interested resources.
| Message Carbons | [XEP-0280](http://xmpp.org/extensions/xep-0280.html) | Keep all IM clients for a user engaged in a conversation, by carbon-copy outbound messages to all interested resources. |
| [Message Archive Management](mam.md) | [XEP-0313](http://xmpp.org/extensions/xep-0313.html) | Query and control an archive of messages stored on a server. |
| [Internet of Things - Sensor Data](iot.md) | [XEP-0323](http://xmpp.org/extensions/xep-0323.html) | Sensor data interchange over XMPP. |
| [Internet of Things - Provisioning](iot.md) | [XEP-0324](http://xmpp.org/extensions/xep-0324.html) | Provisioning, access rights and user priviliges for the Internet of Things. |
| [Internet of Things - Control](iot.md) | [XEP-0325](http://xmpp.org/extensions/xep-0325.html) | Describes how to control devices or actuators in an XMPP-based sensor netowrk. |
| [HTTP over XMPP transport](hoxt.md) | [XEP-0332](http://xmpp.org/extensions/xep-0332.html) | Allows to transport HTTP communication over XMPP peer-to-peer networks. |
| JSON Containers | [XEP-0335](http://xmpp.org/extensions/xep-0335.html) | Encapsulation of JSON data within XMPP Stanzas. |
| [Internet of Things - Discovery](iot.md) | [XEP-0347](http://xmpp.org/extensions/xep-0347.html) | Describes how Things can be installed and discovered by their owners. |
| Google GCM JSON payload | n/a | Semantically the same as XEP-0335: JSON Containers |
| Client State Indication | [XEP-0352](http://xmpp.org/extensions/xep-0352.html) | A way for the client to indicate its active/inactive state. |
| [Message Archive Management](mam.md) | [XEP-0313](http://xmpp.org/extensions/xep-0313.html) | Query and control an archive of messages stored on a server. |
| Google GCM JSON payload | n/a | Semantically the same as XEP-0335: JSON Containers |


Legacy Smack Extensions and currently supported XEPs of smack-legacy
Expand All @@ -98,5 +99,4 @@ If a XEP becomes 'Deprecated' or 'Obsolete' the code will be moved to the *smack
| Name | XEP | Description |
|---------------------------------------------|----------------------------------------------------------|----------------------------------------------------------------------------------------------------------|
| [Message Events](messageevents.md) | [XEP-0022](http://xmpp.org/extensions/xep-0022.html) | Requests and responds to message events. |

| [Roster Item Exchange](rosterexchange.md) | [XEP-0093](http://xmpp.org/extensions/xep-0093.html) | Allows roster data to be shared between users. |
1 change: 1 addition & 0 deletions documentation/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
* [Roster and Presence](roster.md)
* [Processing Incoming Stanzas](processing.md)
* [Provider Architecture](providers.md)
* [DNSSEC and DANE](dnssec.md)
* [Debugging with Smack](debugging.md)

* [Smack Extensions Manual](extensions/index.md)
Original file line number Diff line number Diff line change
Expand Up @@ -648,11 +648,10 @@ protected List<HostAddress> populateHostAddresses() {
// N.B.: Important to use config.serviceName and not AbstractXMPPConnection.serviceName
if (config.host != null) {
hostAddresses = new ArrayList<HostAddress>(1);
HostAddress hostAddress;
hostAddress = new HostAddress(config.host, config.port);
HostAddress hostAddress = DNSUtil.getDNSResolver().lookupHostAddress(config.host, failedAddresses, config.getDnssecMode());
hostAddresses.add(hostAddress);
} else {
hostAddresses = DNSUtil.resolveXMPPServiceDomain(config.getXMPPServiceDomain().toString(), failedAddresses);
hostAddresses = DNSUtil.resolveXMPPServiceDomain(config.getXMPPServiceDomain().toString(), failedAddresses, config.getDnssecMode());
}
// If we reach this, then hostAddresses *must not* be empty, i.e. there is at least one host added, either the
// config.host one or the host representing the service name by DNSUtil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,14 @@
import org.jivesoftware.smack.util.StringUtils;
import org.jxmpp.jid.DomainBareJid;
import org.jxmpp.jid.EntityBareJid;
import org.jxmpp.jid.impl.JidCreate;
import org.jxmpp.jid.parts.Resourcepart;
import org.jxmpp.stringprep.XmppStringprepException;

import javax.net.SocketFactory;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.X509TrustManager;
import javax.security.auth.callback.CallbackHandler;

/**
Expand Down Expand Up @@ -96,6 +98,10 @@ public abstract class ConnectionConfiguration {
private final boolean legacySessionDisabled;
private final SecurityMode securityMode;

private final DnssecMode dnssecMode;

private final X509TrustManager customX509TrustManager;

/**
*
*/
Expand Down Expand Up @@ -134,6 +140,10 @@ protected ConnectionConfiguration(Builder<?,?> builder) {
proxy = builder.proxy;
socketFactory = builder.socketFactory;

dnssecMode = builder.dnssecMode;

customX509TrustManager = builder.customX509TrustManager;

securityMode = builder.securityMode;
keystoreType = builder.keystoreType;
keystorePath = builder.keystorePath;
Expand All @@ -150,6 +160,11 @@ protected ConnectionConfiguration(Builder<?,?> builder) {

// If the enabledSaslmechanisms are set, then they must not be empty
assert(enabledSaslMechanisms != null ? !enabledSaslMechanisms.isEmpty() : true);

if (dnssecMode != DnssecMode.disabled && customSSLContext != null) {
throw new IllegalStateException("You can not use a custom SSL context with DNSSEC enabled");
}

}

/**
Expand Down Expand Up @@ -182,6 +197,14 @@ public SecurityMode getSecurityMode() {
return securityMode;
}

public DnssecMode getDnssecMode() {
return dnssecMode;
}

public X509TrustManager getCustomX509TrustManager() {
return customX509TrustManager;
}

/**
* Retuns the path to the keystore file. The key store file contains the
* certificates that may be used to authenticate the client to the server,
Expand Down Expand Up @@ -341,6 +364,37 @@ public static enum SecurityMode {
disabled
}

/**
* Determines the requested DNSSEC security mode.
* <b>Note that Smack's support for DNSSEC/DANE is experimental!</b>
* <p>
* The default '{@link #disabled}' means that neither DNSSEC nor DANE verification will be performed. When
* '{@link #needsDnssec}' is used, then the connection will not be established if the resource records used to connect
* to the XMPP service are not authenticated by DNSSEC. Additionally, if '{@link #needsDnssecAndDane}' is used, then
* the XMPP service's TLS certificate is verified using DANE.
*
*/
public enum DnssecMode {

/**
* Do not perform any DNSSEC authentication or DANE verification.
*/
disabled,

/**
* <b>Experimental!</b>
* Require all DNS information to be authenticated by DNSSEC.
*/
needsDnssec,

/**
* <b>Experimental!</b>
* Require all DNS information to be authenticated by DNSSEC and require the XMPP service's TLS certificate to be verified using DANE.
*/
needsDnssecAndDane,

}

/**
* Returns the username to use when trying to reconnect to the server.
*
Expand Down Expand Up @@ -436,6 +490,7 @@ public Set<String> getEnabledSaslMechanisms() {
*/
public static abstract class Builder<B extends Builder<B, C>, C extends ConnectionConfiguration> {
private SecurityMode securityMode = SecurityMode.ifpossible;
private DnssecMode dnssecMode = DnssecMode.disabled;
private String keystorePath = System.getProperty("javax.net.ssl.keyStore");
private String keystoreType = "jks";
private String pkcs11Library = "pkcs11.config";
Expand All @@ -459,6 +514,7 @@ public static abstract class Builder<B extends Builder<B, C>, C extends Connecti
private boolean allowEmptyOrNullUsername = false;
private boolean saslMechanismsSealed;
private Set<String> enabledSaslMechanisms;
private X509TrustManager customX509TrustManager;

protected Builder() {
}
Expand All @@ -481,7 +537,7 @@ public B setUsernameAndPassword(CharSequence username, String password) {
}

/**
* Set the service name of this XMPP service (i.e., the XMPP domain).
* Set the XMPP domain. The XMPP domain is what follows after the '@' sign in XMPP addresses (JIDs).
*
* @param serviceName the service name
* @return a reference to this builder.
Expand All @@ -493,13 +549,25 @@ public B setServiceName(DomainBareJid serviceName) {
}

/**
* Set the service name of this XMPP service (i.e., the XMPP domain).
* Set the XMPP domain. The XMPP domain is what follows after the '@' sign in XMPP addresses (JIDs).
*
* @param xmppDomain the XMPP domain.
* @return a reference to this builder.
*/
public B setXmppDomain(DomainBareJid xmppDomain) {
this.xmppServiceDomain = xmppDomain;
return getThis();
}

/**
* Set the XMPP domain. The XMPP domain is what follows after the '@' sign in XMPP addresses (JIDs).
*
* @param xmppServiceDomain the service name
* @param xmppServiceDomain the XMPP domain.
* @return a reference to this builder.
* @throws XmppStringprepException if the given string is not a domain bare JID.
*/
public B setXmppDomain(DomainBareJid xmppServiceDomain) {
this.xmppServiceDomain = xmppServiceDomain;
public B setXmppDomain(String xmppServiceDomain) throws XmppStringprepException {
this.xmppServiceDomain = JidCreate.domainBareFrom(xmppServiceDomain);
return getThis();
}

Expand Down Expand Up @@ -556,6 +624,16 @@ public B setCallbackHandler(CallbackHandler callbackHandler) {
return getThis();
}

public B setDnssecMode(DnssecMode dnssecMode) {
this.dnssecMode = Objects.requireNonNull(dnssecMode, "DNSSEC mode must not be null");
return getThis();
}

public B setCustomX509TrustManager(X509TrustManager x509TrustManager) {
this.customX509TrustManager = x509TrustManager;
return getThis();
}

/**
* Sets the TLS security mode used when making the connection. By default,
* the mode is {@link SecurityMode#ifpossible}.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
* @author Gaston Dombiak
*/
public class ConsoleDebugger extends AbstractDebugger {
private final SimpleDateFormat dateFormatter = new SimpleDateFormat("hh:mm:ss aaa");
private final SimpleDateFormat dateFormatter = new SimpleDateFormat("HH:mm:ss");

public ConsoleDebugger(XMPPConnection connection, Writer writer, Reader reader) {
super(connection, writer, reader);
Expand Down
Loading

0 comments on commit 4a02a61

Please sign in to comment.