001/** 002 * 003 * Copyright 2003-2007 Jive Software, 2017-2019 Florian Schmaus. 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018package org.jivesoftware.smack; 019 020import java.net.InetAddress; 021import java.net.UnknownHostException; 022import java.security.KeyStore; 023import java.util.Arrays; 024import java.util.Collection; 025import java.util.Collections; 026import java.util.HashSet; 027import java.util.Set; 028import java.util.logging.Level; 029import java.util.logging.Logger; 030 031import javax.net.SocketFactory; 032import javax.net.ssl.HostnameVerifier; 033import javax.net.ssl.SSLContext; 034import javax.net.ssl.X509TrustManager; 035import javax.security.auth.callback.CallbackHandler; 036 037import org.jivesoftware.smack.debugger.SmackDebuggerFactory; 038import org.jivesoftware.smack.proxy.ProxyInfo; 039import org.jivesoftware.smack.sasl.SASLMechanism; 040import org.jivesoftware.smack.sasl.core.SASLAnonymous; 041import org.jivesoftware.smack.util.CollectionUtil; 042import org.jivesoftware.smack.util.Objects; 043import org.jivesoftware.smack.util.StringUtils; 044 045import org.jxmpp.jid.DomainBareJid; 046import org.jxmpp.jid.EntityBareJid; 047import org.jxmpp.jid.impl.JidCreate; 048import org.jxmpp.jid.parts.Resourcepart; 049import org.jxmpp.stringprep.XmppStringprepException; 050import org.minidns.dnsname.DnsName; 051import org.minidns.dnsname.InvalidDnsNameException; 052import org.minidns.util.InetAddressUtil; 053 054/** 055 * Configuration to use while establishing the connection to the server. 056 * 057 * @author Gaston Dombiak 058 */ 059public abstract class ConnectionConfiguration { 060 061 static { 062 // Ensure that Smack is initialized when ConnectionConfiguration is used, or otherwise e.g. 063 // SmackConfiguration.DEBUG may not be initialized yet. 064 SmackConfiguration.getVersion(); 065 } 066 067 private static final Logger LOGGER = Logger.getLogger(ConnectionConfiguration.class.getName()); 068 069 /** 070 * The XMPP domain of the XMPP Service. Usually servers use the same service name as the name 071 * of the server. However, there are some servers like google where host would be 072 * talk.google.com and the serviceName would be gmail.com. 073 */ 074 protected final DomainBareJid xmppServiceDomain; 075 076 protected final DnsName xmppServiceDomainDnsName; 077 078 protected final InetAddress hostAddress; 079 protected final DnsName host; 080 protected final int port; 081 082 private final String keystorePath; 083 private final String keystoreType; 084 private final String pkcs11Library; 085 private final SSLContext customSSLContext; 086 087 /** 088 * Used to get information from the user 089 */ 090 private final CallbackHandler callbackHandler; 091 092 private final SmackDebuggerFactory debuggerFactory; 093 094 // Holds the socket factory that is used to generate the socket in the connection 095 private final SocketFactory socketFactory; 096 097 private final CharSequence username; 098 private final String password; 099 private final Resourcepart resource; 100 101 /** 102 * The optional SASL authorization identity (see RFC 6120 § 6.3.8). 103 */ 104 private final EntityBareJid authzid; 105 106 /** 107 * Initial presence as of RFC 6121 § 4.2 108 * @see <a href="http://xmpp.org/rfcs/rfc6121.html#presence-initial">RFC 6121 § 4.2 Initial Presence</a> 109 */ 110 private final boolean sendPresence; 111 112 private final SecurityMode securityMode; 113 114 private final DnssecMode dnssecMode; 115 116 private final X509TrustManager customX509TrustManager; 117 118 /** 119 * 120 */ 121 private final String[] enabledSSLProtocols; 122 123 /** 124 * 125 */ 126 private final String[] enabledSSLCiphers; 127 128 private final HostnameVerifier hostnameVerifier; 129 130 // Holds the proxy information (such as proxyhost, proxyport, username, password etc) 131 protected final ProxyInfo proxy; 132 133 protected final boolean allowNullOrEmptyUsername; 134 135 private final Set<String> enabledSaslMechanisms; 136 137 protected ConnectionConfiguration(Builder<?,?> builder) { 138 authzid = builder.authzid; 139 username = builder.username; 140 password = builder.password; 141 callbackHandler = builder.callbackHandler; 142 143 // Resource can be null, this means that the server must provide one 144 resource = builder.resource; 145 146 xmppServiceDomain = builder.xmppServiceDomain; 147 if (xmppServiceDomain == null) { 148 throw new IllegalArgumentException("Must define the XMPP domain"); 149 } 150 151 DnsName xmppServiceDomainDnsName; 152 try { 153 xmppServiceDomainDnsName = DnsName.from(xmppServiceDomain); 154 } catch (InvalidDnsNameException e) { 155 LOGGER.log(Level.INFO, 156 "Could not transform XMPP service domain '" + xmppServiceDomain 157 + "' to a DNS name. TLS X.509 certificate validiation may not be possible.", 158 e); 159 xmppServiceDomainDnsName = null; 160 } 161 this.xmppServiceDomainDnsName = xmppServiceDomainDnsName; 162 163 hostAddress = builder.hostAddress; 164 host = builder.host; 165 port = builder.port; 166 167 proxy = builder.proxy; 168 socketFactory = builder.socketFactory; 169 170 dnssecMode = builder.dnssecMode; 171 172 customX509TrustManager = builder.customX509TrustManager; 173 174 securityMode = builder.securityMode; 175 keystoreType = builder.keystoreType; 176 keystorePath = builder.keystorePath; 177 pkcs11Library = builder.pkcs11Library; 178 customSSLContext = builder.customSSLContext; 179 enabledSSLProtocols = builder.enabledSSLProtocols; 180 enabledSSLCiphers = builder.enabledSSLCiphers; 181 hostnameVerifier = builder.hostnameVerifier; 182 sendPresence = builder.sendPresence; 183 debuggerFactory = builder.debuggerFactory; 184 allowNullOrEmptyUsername = builder.allowEmptyOrNullUsername; 185 enabledSaslMechanisms = builder.enabledSaslMechanisms; 186 187 // If the enabledSaslmechanisms are set, then they must not be empty 188 assert (enabledSaslMechanisms != null ? !enabledSaslMechanisms.isEmpty() : true); 189 190 if (dnssecMode != DnssecMode.disabled && customSSLContext != null) { 191 throw new IllegalStateException("You can not use a custom SSL context with DNSSEC enabled"); 192 } 193 194 } 195 196 DnsName getHost() { 197 return host; 198 } 199 200 InetAddress getHostAddress() { 201 return hostAddress; 202 } 203 204 /** 205 * Returns the server name of the target server. 206 * 207 * @return the server name of the target server. 208 * @deprecated use {@link #getXMPPServiceDomain()} instead. 209 */ 210 @Deprecated 211 public DomainBareJid getServiceName() { 212 return xmppServiceDomain; 213 } 214 215 /** 216 * Returns the XMPP domain used by this configuration. 217 * 218 * @return the XMPP domain. 219 */ 220 public DomainBareJid getXMPPServiceDomain() { 221 return xmppServiceDomain; 222 } 223 224 /** 225 * Returns the XMPP service domain as DNS name if possible. Note that since not every XMPP address domainpart is a 226 * valid DNS name, this method may return <code>null</code>. 227 * 228 * @return the XMPP service domain as DNS name or <code>null</code>. 229 * @since 4.3.4 230 */ 231 public DnsName getXmppServiceDomainAsDnsNameIfPossible() { 232 return xmppServiceDomainDnsName; 233 } 234 235 /** 236 * Returns the TLS security mode used when making the connection. By default, 237 * the mode is {@link SecurityMode#ifpossible}. 238 * 239 * @return the security mode. 240 */ 241 public SecurityMode getSecurityMode() { 242 return securityMode; 243 } 244 245 public DnssecMode getDnssecMode() { 246 return dnssecMode; 247 } 248 249 public X509TrustManager getCustomX509TrustManager() { 250 return customX509TrustManager; 251 } 252 253 /** 254 * Retuns the path to the keystore file. The key store file contains the 255 * certificates that may be used to authenticate the client to the server, 256 * in the event the server requests or requires it. 257 * 258 * @return the path to the keystore file. 259 */ 260 public String getKeystorePath() { 261 return keystorePath; 262 } 263 264 /** 265 * Returns the keystore type, or <tt>null</tt> if it's not set. 266 * 267 * @return the keystore type. 268 */ 269 public String getKeystoreType() { 270 return keystoreType; 271 } 272 273 /** 274 * Returns the PKCS11 library file location, needed when the 275 * Keystore type is PKCS11. 276 * 277 * @return the path to the PKCS11 library file 278 */ 279 public String getPKCS11Library() { 280 return pkcs11Library; 281 } 282 283 /** 284 * Gets the custom SSLContext previously set with {@link ConnectionConfiguration.Builder#setCustomSSLContext(SSLContext)} for 285 * SSL sockets. This is null by default. 286 * 287 * @return the custom SSLContext or null. 288 */ 289 public SSLContext getCustomSSLContext() { 290 return this.customSSLContext; 291 } 292 293 /** 294 * Return the enabled SSL/TLS protocols. 295 * 296 * @return the enabled SSL/TLS protocols 297 */ 298 public String[] getEnabledSSLProtocols() { 299 return enabledSSLProtocols; 300 } 301 302 /** 303 * Return the enabled SSL/TLS ciphers. 304 * 305 * @return the enabled SSL/TLS ciphers 306 */ 307 public String[] getEnabledSSLCiphers() { 308 return enabledSSLCiphers; 309 } 310 311 /** 312 * Returns the configured HostnameVerifier of this ConnectionConfiguration or the Smack default 313 * HostnameVerifier configured with 314 * {@link SmackConfiguration#setDefaultHostnameVerifier(HostnameVerifier)}. 315 * 316 * @return a configured HostnameVerifier or <code>null</code> 317 */ 318 public HostnameVerifier getHostnameVerifier() { 319 if (hostnameVerifier != null) 320 return hostnameVerifier; 321 return SmackConfiguration.getDefaultHostnameVerifier(); 322 } 323 324 /** 325 * Returns the Smack debugger factory. 326 * 327 * @return the Smack debugger factory or <code>null</code> 328 */ 329 public SmackDebuggerFactory getDebuggerFactory() { 330 return debuggerFactory; 331 } 332 333 /** 334 * Returns a CallbackHandler to obtain information, such as the password or 335 * principal information during the SASL authentication. A CallbackHandler 336 * will be used <b>ONLY</b> if no password was specified during the login while 337 * using SASL authentication. 338 * 339 * @return a CallbackHandler to obtain information, such as the password or 340 * principal information during the SASL authentication. 341 */ 342 public CallbackHandler getCallbackHandler() { 343 return callbackHandler; 344 } 345 346 /** 347 * Returns the socket factory used to create new xmppConnection sockets. 348 * This is useful when connecting through SOCKS5 proxies. 349 * 350 * @return socketFactory used to create new sockets. 351 */ 352 public SocketFactory getSocketFactory() { 353 return this.socketFactory; 354 } 355 356 /** 357 * Get the configured proxy information (if any). 358 * 359 * @return the configured proxy information or <code>null</code>. 360 */ 361 public ProxyInfo getProxyInfo() { 362 return proxy; 363 } 364 365 /** 366 * An enumeration for TLS security modes that are available when making a connection 367 * to the XMPP server. 368 */ 369 public enum SecurityMode { 370 371 /** 372 * Security via TLS encryption is required in order to connect. If the server 373 * does not offer TLS or if the TLS negotiation fails, the connection to the server 374 * will fail. 375 */ 376 required, 377 378 /** 379 * Security via TLS encryption is used whenever it's available. This is the 380 * default setting. 381 * <p> 382 * <b>Do not use this setting</b> unless you can't use {@link #required}. An attacker could easily perform a 383 * Man-in-the-middle attack and prevent TLS from being used, leaving you with an unencrypted (and 384 * unauthenticated) connection. 385 * </p> 386 */ 387 ifpossible, 388 389 /** 390 * Security via TLS encryption is disabled and only un-encrypted connections will 391 * be used. If only TLS encryption is available from the server, the connection 392 * will fail. 393 */ 394 disabled 395 } 396 397 /** 398 * Determines the requested DNSSEC security mode. 399 * <b>Note that Smack's support for DNSSEC/DANE is experimental!</b> 400 * <p> 401 * The default '{@link #disabled}' means that neither DNSSEC nor DANE verification will be performed. When 402 * '{@link #needsDnssec}' is used, then the connection will not be established if the resource records used to connect 403 * to the XMPP service are not authenticated by DNSSEC. Additionally, if '{@link #needsDnssecAndDane}' is used, then 404 * the XMPP service's TLS certificate is verified using DANE. 405 * 406 */ 407 public enum DnssecMode { 408 409 /** 410 * Do not perform any DNSSEC authentication or DANE verification. 411 */ 412 disabled, 413 414 /** 415 * <b>Experimental!</b> 416 * Require all DNS information to be authenticated by DNSSEC. 417 */ 418 needsDnssec, 419 420 /** 421 * <b>Experimental!</b> 422 * Require all DNS information to be authenticated by DNSSEC and require the XMPP service's TLS certificate to be verified using DANE. 423 */ 424 needsDnssecAndDane, 425 426 } 427 428 /** 429 * Returns the username to use when trying to reconnect to the server. 430 * 431 * @return the username to use when trying to reconnect to the server. 432 */ 433 public CharSequence getUsername() { 434 return this.username; 435 } 436 437 /** 438 * Returns the password to use when trying to reconnect to the server. 439 * 440 * @return the password to use when trying to reconnect to the server. 441 */ 442 public String getPassword() { 443 return this.password; 444 } 445 446 /** 447 * Returns the resource to use when trying to reconnect to the server. 448 * 449 * @return the resource to use when trying to reconnect to the server. 450 */ 451 public Resourcepart getResource() { 452 return resource; 453 } 454 455 /** 456 * Returns the optional XMPP address to be requested as the SASL authorization identity. 457 * 458 * @return the authorization identifier. 459 * @see <a href="http://tools.ietf.org/html/rfc6120#section-6.3.8">RFC 6120 § 6.3.8. Authorization Identity</a> 460 * @since 4.2 461 */ 462 public EntityBareJid getAuthzid() { 463 return authzid; 464 } 465 466 /** 467 * Returns true if an available presence should be sent when logging in while reconnecting. 468 * 469 * @return true if an available presence should be sent when logging in while reconnecting 470 */ 471 public boolean isSendPresence() { 472 return sendPresence; 473 } 474 475 /** 476 * Returns true if the connection is going to use stream compression. Stream compression 477 * will be requested after TLS was established (if TLS was enabled) and only if the server 478 * offered stream compression. With stream compression network traffic can be reduced 479 * up to 90%. By default compression is disabled. 480 * 481 * @return true if the connection is going to use stream compression. 482 */ 483 public boolean isCompressionEnabled() { 484 // Compression for non-TCP connections is always disabled 485 return false; 486 } 487 488 /** 489 * Check if the given SASL mechansism is enabled in this connection configuration. 490 * 491 * @param saslMechanism 492 * @return true if the given SASL mechanism is enabled, false otherwise. 493 */ 494 public boolean isEnabledSaslMechanism(String saslMechanism) { 495 // If enabledSaslMechanisms is not set, then all mechanisms which are not blacklisted are enabled per default. 496 if (enabledSaslMechanisms == null) { 497 return !SASLAuthentication.getBlacklistedSASLMechanisms().contains(saslMechanism); 498 } 499 return enabledSaslMechanisms.contains(saslMechanism); 500 } 501 502 /** 503 * Return the explicitly enabled SASL mechanisms. May return <code>null</code> if no SASL mechanisms where 504 * explicitly enabled, i.e. all SALS mechanisms supported and announced by the service will be considered. 505 * 506 * @return the enabled SASL mechanisms or <code>null</code>. 507 */ 508 public Set<String> getEnabledSaslMechanisms() { 509 if (enabledSaslMechanisms == null) { 510 return null; 511 } 512 return Collections.unmodifiableSet(enabledSaslMechanisms); 513 } 514 515 /** 516 * A builder for XMPP connection configurations. 517 * <p> 518 * This is an abstract class that uses the builder design pattern and the "getThis() trick" to recover the type of 519 * the builder in a class hierarchies with a self-referential generic supertype. Otherwise chaining of build 520 * instructions from the superclasses followed by build instructions of a subclass would not be possible, because 521 * the superclass build instructions would return the builder of the superclass and not the one of the subclass. You 522 * can read more about it a Angelika Langer's Generics FAQ, especially the entry <a 523 * href="http://www.angelikalanger.com/GenericsFAQ/FAQSections/ProgrammingIdioms.html#FAQ206">What is the 524 * "getThis()" trick?</a>. 525 * </p> 526 * 527 * @param <B> the builder type parameter. 528 * @param <C> the resulting connection configuration type parameter. 529 */ 530 public abstract static class Builder<B extends Builder<B, C>, C extends ConnectionConfiguration> { 531 private SecurityMode securityMode = SecurityMode.ifpossible; 532 private DnssecMode dnssecMode = DnssecMode.disabled; 533 private String keystorePath = System.getProperty("javax.net.ssl.keyStore"); 534 private String keystoreType = KeyStore.getDefaultType(); 535 private String pkcs11Library = "pkcs11.config"; 536 private SSLContext customSSLContext; 537 private String[] enabledSSLProtocols; 538 private String[] enabledSSLCiphers; 539 private HostnameVerifier hostnameVerifier; 540 private EntityBareJid authzid; 541 private CharSequence username; 542 private String password; 543 private Resourcepart resource; 544 private boolean sendPresence = true; 545 private ProxyInfo proxy; 546 private CallbackHandler callbackHandler; 547 private SmackDebuggerFactory debuggerFactory; 548 private SocketFactory socketFactory; 549 private DomainBareJid xmppServiceDomain; 550 private InetAddress hostAddress; 551 private DnsName host; 552 private int port = 5222; 553 private boolean allowEmptyOrNullUsername = false; 554 private boolean saslMechanismsSealed; 555 private Set<String> enabledSaslMechanisms; 556 private X509TrustManager customX509TrustManager; 557 558 protected Builder() { 559 if (SmackConfiguration.DEBUG) { 560 enableDefaultDebugger(); 561 } 562 } 563 564 /** 565 * Set the XMPP entities username and password. 566 * <p> 567 * The username is usually the localpart of the clients JID. But some SASL mechanisms or services may require a different 568 * format (e.g. the full JID) as used authorization identity. 569 * </p> 570 * 571 * @param username the username or authorization identity 572 * @param password the password or token used to authenticate 573 * @return a reference to this builder. 574 */ 575 public B setUsernameAndPassword(CharSequence username, String password) { 576 this.username = username; 577 this.password = password; 578 return getThis(); 579 } 580 581 /** 582 * Set the XMPP domain. The XMPP domain is what follows after the '@' sign in XMPP addresses (JIDs). 583 * 584 * @param serviceName the service name 585 * @return a reference to this builder. 586 * @deprecated use {@link #setXmppDomain(DomainBareJid)} instead. 587 */ 588 @Deprecated 589 public B setServiceName(DomainBareJid serviceName) { 590 return setXmppDomain(serviceName); 591 } 592 593 /** 594 * Set the XMPP domain. The XMPP domain is what follows after the '@' sign in XMPP addresses (JIDs). 595 * 596 * @param xmppDomain the XMPP domain. 597 * @return a reference to this builder. 598 */ 599 public B setXmppDomain(DomainBareJid xmppDomain) { 600 this.xmppServiceDomain = xmppDomain; 601 return getThis(); 602 } 603 604 /** 605 * Set the XMPP domain. The XMPP domain is what follows after the '@' sign in XMPP addresses (JIDs). 606 * 607 * @param xmppServiceDomain the XMPP domain. 608 * @return a reference to this builder. 609 * @throws XmppStringprepException if the given string is not a domain bare JID. 610 */ 611 public B setXmppDomain(String xmppServiceDomain) throws XmppStringprepException { 612 this.xmppServiceDomain = JidCreate.domainBareFrom(xmppServiceDomain); 613 return getThis(); 614 } 615 616 /** 617 * Set the resource we are requesting from the server. 618 * <p> 619 * If <code>resource</code> is <code>null</code>, the default, then the server will automatically create a 620 * resource for the client. Note that XMPP clients only suggest this resource to the server. XMPP servers are 621 * allowed to ignore the client suggested resource and instead assign a completely different 622 * resource (see RFC 6120 § 7.7.1). 623 * </p> 624 * 625 * @param resource the resource to use. 626 * @return a reference to this builder. 627 * @see <a href="https://tools.ietf.org/html/rfc6120#section-7.7.1">RFC 6120 § 7.7.1</a> 628 */ 629 public B setResource(Resourcepart resource) { 630 this.resource = resource; 631 return getThis(); 632 } 633 634 /** 635 * Set the resource we are requesting from the server. 636 * 637 * @param resource the non-null CharSequence to use a resource. 638 * @return a reference ot this builder. 639 * @throws XmppStringprepException if the CharSequence is not a valid resourcepart. 640 * @see #setResource(Resourcepart) 641 */ 642 public B setResource(CharSequence resource) throws XmppStringprepException { 643 Objects.requireNonNull(resource, "resource must not be null"); 644 return setResource(Resourcepart.from(resource.toString())); 645 } 646 647 /** 648 * Set the Internet address of the host providing the XMPP service. If set, then this will overwrite anything 649 * set via {@link #setHost(String)}. 650 * 651 * @param address the Internet address of the host providing the XMPP service. 652 * @return a reference to this builder. 653 * @since 4.2 654 */ 655 public B setHostAddress(InetAddress address) { 656 this.hostAddress = address; 657 return getThis(); 658 } 659 660 /** 661 * Set the name of the host providing the XMPP service. Note that this method does only allow DNS names and not 662 * IP addresses. Use {@link #setHostAddress(InetAddress)} if you want to explicitly set the Internet address of 663 * the host providing the XMPP service. 664 * 665 * @param host the DNS name of the host providing the XMPP service. 666 * @return a reference to this builder. 667 */ 668 public B setHost(String host) { 669 DnsName hostDnsName = DnsName.from(host); 670 return setHost(hostDnsName); 671 } 672 673 /** 674 * Set the name of the host providing the XMPP service. Note that this method does only allow DNS names and not 675 * IP addresses. Use {@link #setHostAddress(InetAddress)} if you want to explicitly set the Internet address of 676 * the host providing the XMPP service. 677 * 678 * @param host the DNS name of the host providing the XMPP service. 679 * @return a reference to this builder. 680 */ 681 public B setHost(DnsName host) { 682 this.host = host; 683 return getThis(); 684 } 685 686 /** 687 * Set the host to connect to by either its fully qualified domain name (FQDN) or its IP. 688 * 689 * @param fqdnOrIp a CharSequence either representing the FQDN or the IP of the host. 690 * @return a reference to this builder. 691 * @see #setHost(DnsName) 692 * @see #setHostAddress(InetAddress) 693 * @since 4.3.2 694 */ 695 public B setHostAddressByNameOrIp(CharSequence fqdnOrIp) { 696 String fqdnOrIpString = fqdnOrIp.toString(); 697 if (InetAddressUtil.isIpAddress(fqdnOrIp)) { 698 InetAddress hostInetAddress; 699 try { 700 hostInetAddress = InetAddress.getByName(fqdnOrIpString); 701 } 702 catch (UnknownHostException e) { 703 // Should never happen. 704 throw new AssertionError(e); 705 } 706 setHostAddress(hostInetAddress); 707 } else { 708 setHost(fqdnOrIpString); 709 } 710 return getThis(); 711 } 712 713 public B setPort(int port) { 714 if (port < 0 || port > 65535) { 715 throw new IllegalArgumentException( 716 "Port must be a 16-bit unsigned integer (i.e. between 0-65535. Port was: " + port); 717 } 718 this.port = port; 719 return getThis(); 720 } 721 722 /** 723 * Sets a CallbackHandler to obtain information, such as the password or 724 * principal information during the SASL authentication. A CallbackHandler 725 * will be used <b>ONLY</b> if no password was specified during the login while 726 * using SASL authentication. 727 * 728 * @param callbackHandler to obtain information, such as the password or 729 * principal information during the SASL authentication. 730 * @return a reference to this builder. 731 */ 732 public B setCallbackHandler(CallbackHandler callbackHandler) { 733 this.callbackHandler = callbackHandler; 734 return getThis(); 735 } 736 737 public B setDnssecMode(DnssecMode dnssecMode) { 738 this.dnssecMode = Objects.requireNonNull(dnssecMode, "DNSSEC mode must not be null"); 739 return getThis(); 740 } 741 742 public B setCustomX509TrustManager(X509TrustManager x509TrustManager) { 743 this.customX509TrustManager = x509TrustManager; 744 return getThis(); 745 } 746 747 /** 748 * Sets the TLS security mode used when making the connection. By default, 749 * the mode is {@link SecurityMode#ifpossible}. 750 * 751 * @param securityMode the security mode. 752 * @return a reference to this builder. 753 */ 754 public B setSecurityMode(SecurityMode securityMode) { 755 this.securityMode = securityMode; 756 return getThis(); 757 } 758 759 /** 760 * Sets the path to the keystore file. The key store file contains the 761 * certificates that may be used to authenticate the client to the server, 762 * in the event the server requests or requires it. 763 * 764 * @param keystorePath the path to the keystore file. 765 * @return a reference to this builder. 766 */ 767 public B setKeystorePath(String keystorePath) { 768 this.keystorePath = keystorePath; 769 return getThis(); 770 } 771 772 /** 773 * Sets the keystore type. 774 * 775 * @param keystoreType the keystore type. 776 * @return a reference to this builder. 777 */ 778 public B setKeystoreType(String keystoreType) { 779 this.keystoreType = keystoreType; 780 return getThis(); 781 } 782 783 /** 784 * Sets the PKCS11 library file location, needed when the 785 * Keystore type is PKCS11. 786 * 787 * @param pkcs11Library the path to the PKCS11 library file. 788 * @return a reference to this builder. 789 */ 790 public B setPKCS11Library(String pkcs11Library) { 791 this.pkcs11Library = pkcs11Library; 792 return getThis(); 793 } 794 795 /** 796 * Sets a custom SSLContext for creating SSL sockets. 797 * <p> 798 * For more information on how to create a SSLContext see <a href= 799 * "http://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#X509TrustManager" 800 * >Java Secure Socket Extension (JSEE) Reference Guide: Creating Your Own X509TrustManager</a> 801 * 802 * @param context the custom SSLContext for new sockets. 803 * @return a reference to this builder. 804 */ 805 public B setCustomSSLContext(SSLContext context) { 806 this.customSSLContext = Objects.requireNonNull(context, "The SSLContext must not be null"); 807 return getThis(); 808 } 809 810 /** 811 * Set the enabled SSL/TLS protocols. 812 * 813 * @param enabledSSLProtocols 814 * @return a reference to this builder. 815 */ 816 public B setEnabledSSLProtocols(String[] enabledSSLProtocols) { 817 this.enabledSSLProtocols = enabledSSLProtocols; 818 return getThis(); 819 } 820 821 /** 822 * Set the enabled SSL/TLS ciphers. 823 * 824 * @param enabledSSLCiphers the enabled SSL/TLS ciphers 825 * @return a reference to this builder. 826 */ 827 public B setEnabledSSLCiphers(String[] enabledSSLCiphers) { 828 this.enabledSSLCiphers = enabledSSLCiphers; 829 return getThis(); 830 } 831 832 /** 833 * Set the HostnameVerifier used to verify the hostname of SSLSockets used by XMPP connections 834 * created with this ConnectionConfiguration. 835 * 836 * @param verifier 837 * @return a reference to this builder. 838 */ 839 public B setHostnameVerifier(HostnameVerifier verifier) { 840 hostnameVerifier = verifier; 841 return getThis(); 842 } 843 844 /** 845 * Sets if an initial available presence will be sent to the server. By default 846 * an available presence will be sent to the server indicating that this presence 847 * is not online and available to receive messages. If you want to log in without 848 * being 'noticed' then pass a <tt>false</tt> value. 849 * 850 * @param sendPresence true if an initial available presence will be sent while logging in. 851 * @return a reference to this builder. 852 */ 853 public B setSendPresence(boolean sendPresence) { 854 this.sendPresence = sendPresence; 855 return getThis(); 856 } 857 858 public B enableDefaultDebugger() { 859 this.debuggerFactory = SmackConfiguration.getDefaultSmackDebuggerFactory(); 860 assert this.debuggerFactory != null; 861 return getThis(); 862 } 863 864 /** 865 * Set the Smack debugger factory used to construct Smack debuggers. 866 * 867 * @param debuggerFactory the Smack debugger factory. 868 * @return a reference to this builder. 869 */ 870 public B setDebuggerFactory(SmackDebuggerFactory debuggerFactory) { 871 this.debuggerFactory = debuggerFactory; 872 return getThis(); 873 } 874 875 /** 876 * Sets the socket factory used to create new xmppConnection sockets. 877 * This is useful when connecting through SOCKS5 proxies. 878 * 879 * @param socketFactory used to create new sockets. 880 * @return a reference to this builder. 881 */ 882 public B setSocketFactory(SocketFactory socketFactory) { 883 this.socketFactory = socketFactory; 884 return getThis(); 885 } 886 887 /** 888 * Set the information about the Proxy used for the connection. 889 * 890 * @param proxyInfo the Proxy information. 891 * @return a reference to this builder. 892 */ 893 public B setProxyInfo(ProxyInfo proxyInfo) { 894 this.proxy = proxyInfo; 895 return getThis(); 896 } 897 898 /** 899 * Allow <code>null</code> or the empty String as username. 900 * 901 * Some SASL mechanisms (e.g. SASL External) may also signal the username (as "authorization identity"), in 902 * which case Smack should not throw an IllegalArgumentException when the username is not set. 903 * 904 * @return a reference to this builder. 905 */ 906 public B allowEmptyOrNullUsernames() { 907 allowEmptyOrNullUsername = true; 908 return getThis(); 909 } 910 911 /** 912 * Perform anonymous authentication using SASL ANONYMOUS. Your XMPP service must support this authentication 913 * mechanism. This method also calls {@link #addEnabledSaslMechanism(String)} with "ANONYMOUS" as argument. 914 * 915 * @return a reference to this builder. 916 */ 917 public B performSaslAnonymousAuthentication() { 918 if (!SASLAuthentication.isSaslMechanismRegistered(SASLAnonymous.NAME)) { 919 throw new IllegalArgumentException("SASL " + SASLAnonymous.NAME + " is not registered"); 920 } 921 throwIfEnabledSaslMechanismsSet(); 922 923 allowEmptyOrNullUsernames(); 924 addEnabledSaslMechanism(SASLAnonymous.NAME); 925 saslMechanismsSealed = true; 926 return getThis(); 927 } 928 929 /** 930 * Perform authentication using SASL EXTERNAL. Your XMPP service must support this 931 * authentication mechanism. This method also calls {@link #addEnabledSaslMechanism(String)} with "EXTERNAL" as 932 * argument. It also calls {@link #allowEmptyOrNullUsernames()} and {@link #setSecurityMode(ConnectionConfiguration.SecurityMode)} to 933 * {@link SecurityMode#required}. 934 * 935 * @param sslContext custom SSLContext to be used. 936 * @return a reference to this builder. 937 */ 938 public B performSaslExternalAuthentication(SSLContext sslContext) { 939 if (!SASLAuthentication.isSaslMechanismRegistered(SASLMechanism.EXTERNAL)) { 940 throw new IllegalArgumentException("SASL " + SASLMechanism.EXTERNAL + " is not registered"); 941 } 942 setCustomSSLContext(sslContext); 943 throwIfEnabledSaslMechanismsSet(); 944 945 allowEmptyOrNullUsernames(); 946 setSecurityMode(SecurityMode.required); 947 addEnabledSaslMechanism(SASLMechanism.EXTERNAL); 948 saslMechanismsSealed = true; 949 return getThis(); 950 } 951 952 private void throwIfEnabledSaslMechanismsSet() { 953 if (enabledSaslMechanisms != null) { 954 throw new IllegalStateException("Enabled SASL mechanisms found"); 955 } 956 } 957 958 /** 959 * Add the given mechanism to the enabled ones. See {@link #addEnabledSaslMechanism(Collection)} for a discussion about enabled SASL mechanisms. 960 * 961 * @param saslMechanism the name of the mechanism to enable. 962 * @return a reference to this builder. 963 */ 964 public B addEnabledSaslMechanism(String saslMechanism) { 965 return addEnabledSaslMechanism(Arrays.asList(StringUtils.requireNotNullOrEmpty(saslMechanism, 966 "saslMechanism must not be null or empty"))); 967 } 968 969 /** 970 * Enable the given SASL mechanisms. If you never add a mechanism to the set of enabled ones, <b>all mechanisms 971 * known to Smack</b> will be enabled. Only explicitly enable particular SASL mechanisms if you want to limit 972 * the used mechanisms to the enabled ones. 973 * 974 * @param saslMechanisms a collection of names of mechanisms to enable. 975 * @return a reference to this builder. 976 */ 977 public B addEnabledSaslMechanism(Collection<String> saslMechanisms) { 978 if (saslMechanismsSealed) { 979 throw new IllegalStateException("The enabled SASL mechanisms are sealed, you can not add new ones"); 980 } 981 CollectionUtil.requireNotEmpty(saslMechanisms, "saslMechanisms"); 982 Set<String> blacklistedMechanisms = SASLAuthentication.getBlacklistedSASLMechanisms(); 983 for (String mechanism : saslMechanisms) { 984 if (!SASLAuthentication.isSaslMechanismRegistered(mechanism)) { 985 throw new IllegalArgumentException("SASL " + mechanism + " is not available. Consider registering it with Smack"); 986 } 987 if (blacklistedMechanisms.contains(mechanism)) { 988 throw new IllegalArgumentException("SALS " + mechanism + " is blacklisted."); 989 } 990 } 991 if (enabledSaslMechanisms == null) { 992 enabledSaslMechanisms = new HashSet<>(saslMechanisms.size()); 993 } 994 enabledSaslMechanisms.addAll(saslMechanisms); 995 return getThis(); 996 } 997 998 /** 999 * Set the XMPP address to be used as authorization identity. 1000 * <p> 1001 * In XMPP, authorization identities are bare jids. In general, callers should allow the server to select the 1002 * authorization identifier automatically, and not call this. Note that setting the authzid does not set the XMPP 1003 * service domain, which should typically match. 1004 * Calling this will also SASL CRAM, since this mechanism does not support authzid. 1005 * </p> 1006 * 1007 * @param authzid The BareJid to be requested as the authorization identifier. 1008 * @return a reference to this builder. 1009 * @see <a href="http://tools.ietf.org/html/rfc6120#section-6.3.8">RFC 6120 § 6.3.8. Authorization Identity</a> 1010 * @since 4.2 1011 */ 1012 public B setAuthzid(EntityBareJid authzid) { 1013 this.authzid = authzid; 1014 return getThis(); 1015 } 1016 1017 public abstract C build(); 1018 1019 protected abstract B getThis(); 1020 } 1021 1022}