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