001/** 002 * 003 * Copyright 2003-2007 Jive Software. 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.util.Arrays; 022import java.util.Collection; 023import java.util.Collections; 024import java.util.HashSet; 025import java.util.Set; 026 027import javax.net.SocketFactory; 028import javax.net.ssl.HostnameVerifier; 029import javax.net.ssl.SSLContext; 030import javax.net.ssl.X509TrustManager; 031import javax.security.auth.callback.CallbackHandler; 032 033import org.jivesoftware.smack.packet.Session; 034import org.jivesoftware.smack.proxy.ProxyInfo; 035import org.jivesoftware.smack.sasl.SASLMechanism; 036import org.jivesoftware.smack.sasl.core.SASLAnonymous; 037import org.jivesoftware.smack.util.CollectionUtil; 038import org.jivesoftware.smack.util.Objects; 039import org.jivesoftware.smack.util.StringUtils; 040 041import org.jxmpp.jid.DomainBareJid; 042import org.jxmpp.jid.EntityBareJid; 043import org.jxmpp.jid.impl.JidCreate; 044import org.jxmpp.jid.parts.Resourcepart; 045import org.jxmpp.stringprep.XmppStringprepException; 046 047/** 048 * Configuration to use while establishing the connection to the server. 049 * 050 * @author Gaston Dombiak 051 */ 052public abstract class ConnectionConfiguration { 053 054 static { 055 // Ensure that Smack is initialized when ConnectionConfiguration is used, or otherwise e.g. 056 // SmackConfiguration.DEBUG may not be initialized yet. 057 SmackConfiguration.getVersion(); 058 } 059 060 /** 061 * The XMPP domain of the XMPP Service. Usually servers use the same service name as the name 062 * of the server. However, there are some servers like google where host would be 063 * talk.google.com and the serviceName would be gmail.com. 064 */ 065 protected final DomainBareJid xmppServiceDomain; 066 067 protected final InetAddress hostAddress; 068 protected final String host; 069 protected final int port; 070 071 private final String keystorePath; 072 private final String keystoreType; 073 private final String pkcs11Library; 074 private final SSLContext customSSLContext; 075 076 /** 077 * Used to get information from the user 078 */ 079 private final CallbackHandler callbackHandler; 080 081 private final boolean debuggerEnabled; 082 083 // Holds the socket factory that is used to generate the socket in the connection 084 private final SocketFactory socketFactory; 085 086 private final CharSequence username; 087 private final String password; 088 private final Resourcepart resource; 089 090 /** 091 * The optional SASL authorization identity (see RFC 6120 § 6.3.8). 092 */ 093 private final EntityBareJid authzid; 094 095 /** 096 * Initial presence as of RFC 6121 § 4.2 097 * @see <a href="http://xmpp.org/rfcs/rfc6121.html#presence-initial">RFC 6121 § 4.2 Initial Presence</a> 098 */ 099 private final boolean sendPresence; 100 101 private final boolean legacySessionDisabled; 102 private final SecurityMode securityMode; 103 104 private final DnssecMode dnssecMode; 105 106 private final X509TrustManager customX509TrustManager; 107 108 /** 109 * 110 */ 111 private final String[] enabledSSLProtocols; 112 113 /** 114 * 115 */ 116 private final String[] enabledSSLCiphers; 117 118 private final HostnameVerifier hostnameVerifier; 119 120 // Holds the proxy information (such as proxyhost, proxyport, username, password etc) 121 protected final ProxyInfo proxy; 122 123 protected final boolean allowNullOrEmptyUsername; 124 125 private final Set<String> enabledSaslMechanisms; 126 127 protected ConnectionConfiguration(Builder<?,?> builder) { 128 authzid = builder.authzid; 129 username = builder.username; 130 password = builder.password; 131 callbackHandler = builder.callbackHandler; 132 133 // Resource can be null, this means that the server must provide one 134 resource = builder.resource; 135 136 xmppServiceDomain = builder.xmppServiceDomain; 137 if (xmppServiceDomain == null) { 138 throw new IllegalArgumentException("Must define the XMPP domain"); 139 } 140 hostAddress = builder.hostAddress; 141 host = builder.host; 142 port = builder.port; 143 144 proxy = builder.proxy; 145 socketFactory = builder.socketFactory; 146 147 dnssecMode = builder.dnssecMode; 148 149 customX509TrustManager = builder.customX509TrustManager; 150 151 securityMode = builder.securityMode; 152 keystoreType = builder.keystoreType; 153 keystorePath = builder.keystorePath; 154 pkcs11Library = builder.pkcs11Library; 155 customSSLContext = builder.customSSLContext; 156 enabledSSLProtocols = builder.enabledSSLProtocols; 157 enabledSSLCiphers = builder.enabledSSLCiphers; 158 hostnameVerifier = builder.hostnameVerifier; 159 sendPresence = builder.sendPresence; 160 legacySessionDisabled = builder.legacySessionDisabled; 161 debuggerEnabled = builder.debuggerEnabled; 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 true if the new connection about to be establish is going to be debugged. By 285 * default the value of {@link SmackConfiguration#DEBUG} is used. 286 * 287 * @return true if the new connection about to be establish is going to be debugged. 288 */ 289 public boolean isDebuggerEnabled() { 290 return debuggerEnabled; 291 } 292 293 /** 294 * Returns true if a {@link Session} will be requested on login if the server 295 * supports it. Although this was mandatory on RFC 3921, RFC 6120/6121 don't 296 * even mention this part of the protocol. 297 * 298 * @return true if a session has to be requested when logging in. 299 * @deprecated Smack processes the 'optional' element of the session stream feature. 300 * @see Builder#setLegacySessionDisabled(boolean) 301 */ 302 @Deprecated 303 public boolean isLegacySessionDisabled() { 304 return legacySessionDisabled; 305 } 306 307 /** 308 * Returns a CallbackHandler to obtain information, such as the password or 309 * principal information during the SASL authentication. A CallbackHandler 310 * will be used <b>ONLY</b> if no password was specified during the login while 311 * using SASL authentication. 312 * 313 * @return a CallbackHandler to obtain information, such as the password or 314 * principal information during the SASL authentication. 315 */ 316 public CallbackHandler getCallbackHandler() { 317 return callbackHandler; 318 } 319 320 /** 321 * Returns the socket factory used to create new xmppConnection sockets. 322 * This is useful when connecting through SOCKS5 proxies. 323 * 324 * @return socketFactory used to create new sockets. 325 */ 326 public SocketFactory getSocketFactory() { 327 return this.socketFactory; 328 } 329 330 /** 331 * Get the configured proxy information (if any). 332 * 333 * @return the configured proxy information or <code>null</code>. 334 */ 335 public ProxyInfo getProxyInfo() { 336 return proxy; 337 } 338 339 /** 340 * An enumeration for TLS security modes that are available when making a connection 341 * to the XMPP server. 342 */ 343 public static enum SecurityMode { 344 345 /** 346 * Security via TLS encryption is required in order to connect. If the server 347 * does not offer TLS or if the TLS negotiation fails, the connection to the server 348 * will fail. 349 */ 350 required, 351 352 /** 353 * Security via TLS encryption is used whenever it's available. This is the 354 * default setting. 355 * <p> 356 * <b>Do not use this setting</b> unless you can't use {@link #required}. An attacker could easily perform a 357 * Man-in-the-middle attack and prevent TLS from being used, leaving you with an unencrypted (and 358 * unauthenticated) connection. 359 * </p> 360 */ 361 ifpossible, 362 363 /** 364 * Security via TLS encryption is disabled and only un-encrypted connections will 365 * be used. If only TLS encryption is available from the server, the connection 366 * will fail. 367 */ 368 disabled 369 } 370 371 /** 372 * Determines the requested DNSSEC security mode. 373 * <b>Note that Smack's support for DNSSEC/DANE is experimental!</b> 374 * <p> 375 * The default '{@link #disabled}' means that neither DNSSEC nor DANE verification will be performed. When 376 * '{@link #needsDnssec}' is used, then the connection will not be established if the resource records used to connect 377 * to the XMPP service are not authenticated by DNSSEC. Additionally, if '{@link #needsDnssecAndDane}' is used, then 378 * the XMPP service's TLS certificate is verified using DANE. 379 * 380 */ 381 public enum DnssecMode { 382 383 /** 384 * Do not perform any DNSSEC authentication or DANE verification. 385 */ 386 disabled, 387 388 /** 389 * <b>Experimental!</b> 390 * Require all DNS information to be authenticated by DNSSEC. 391 */ 392 needsDnssec, 393 394 /** 395 * <b>Experimental!</b> 396 * Require all DNS information to be authenticated by DNSSEC and require the XMPP service's TLS certificate to be verified using DANE. 397 */ 398 needsDnssecAndDane, 399 400 } 401 402 /** 403 * Returns the username to use when trying to reconnect to the server. 404 * 405 * @return the username to use when trying to reconnect to the server. 406 */ 407 public CharSequence getUsername() { 408 return this.username; 409 } 410 411 /** 412 * Returns the password to use when trying to reconnect to the server. 413 * 414 * @return the password to use when trying to reconnect to the server. 415 */ 416 public String getPassword() { 417 return this.password; 418 } 419 420 /** 421 * Returns the resource to use when trying to reconnect to the server. 422 * 423 * @return the resource to use when trying to reconnect to the server. 424 */ 425 public Resourcepart getResource() { 426 return resource; 427 } 428 429 /** 430 * Returns the optional XMPP address to be requested as the SASL authorization identity. 431 * 432 * @return the authorization identifier. 433 * @see <a href="http://tools.ietf.org/html/rfc6120#section-6.3.8">RFC 6120 § 6.3.8. Authorization Identity</a> 434 * @since 4.2 435 */ 436 public EntityBareJid getAuthzid() { 437 return authzid; 438 } 439 440 /** 441 * Returns true if an available presence should be sent when logging in while reconnecting. 442 * 443 * @return true if an available presence should be sent when logging in while reconnecting 444 */ 445 public boolean isSendPresence() { 446 return sendPresence; 447 } 448 449 /** 450 * Returns true if the connection is going to use stream compression. Stream compression 451 * will be requested after TLS was established (if TLS was enabled) and only if the server 452 * offered stream compression. With stream compression network traffic can be reduced 453 * up to 90%. By default compression is disabled. 454 * 455 * @return true if the connection is going to use stream compression. 456 */ 457 public boolean isCompressionEnabled() { 458 // Compression for non-TCP connections is always disabled 459 return false; 460 } 461 462 /** 463 * Check if the given SASL mechansism is enabled in this connection configuration. 464 * 465 * @param saslMechanism 466 * @return true if the given SASL mechanism is enabled, false otherwise. 467 */ 468 public boolean isEnabledSaslMechanism(String saslMechanism) { 469 // If enabledSaslMechanisms is not set, then all mechanisms which are not blacklisted are enabled per default. 470 if (enabledSaslMechanisms == null) { 471 return !SASLAuthentication.getBlacklistedSASLMechanisms().contains(saslMechanism); 472 } 473 return enabledSaslMechanisms.contains(saslMechanism); 474 } 475 476 /** 477 * Return the explicitly enabled SASL mechanisms. May return <code>null</code> if no SASL mechanisms where 478 * explicitly enabled, i.e. all SALS mechanisms supported and announced by the service will be considered. 479 * 480 * @return the enabled SASL mechanisms or <code>null</code>. 481 */ 482 public Set<String> getEnabledSaslMechanisms() { 483 if (enabledSaslMechanisms == null) { 484 return null; 485 } 486 return Collections.unmodifiableSet(enabledSaslMechanisms); 487 } 488 489 /** 490 * A builder for XMPP connection configurations. 491 * <p> 492 * This is an abstract class that uses the builder design pattern and the "getThis() trick" to recover the type of 493 * the builder in a class hierarchies with a self-referential generic supertype. Otherwise chaining of build 494 * instructions from the superclasses followed by build instructions of a sublcass would not be possible, because 495 * the superclass build instructions would return the builder of the superclass and not the one of the subclass. You 496 * can read more about it a Angelika Langer's Generics FAQ, especially the entry <a 497 * href="http://www.angelikalanger.com/GenericsFAQ/FAQSections/ProgrammingIdioms.html#FAQ206">What is the 498 * "getThis()" trick?</a>. 499 * </p> 500 * 501 * @param <B> the builder type parameter. 502 * @param <C> the resulting connection configuration type parameter. 503 */ 504 public static abstract class Builder<B extends Builder<B, C>, C extends ConnectionConfiguration> { 505 private SecurityMode securityMode = SecurityMode.ifpossible; 506 private DnssecMode dnssecMode = DnssecMode.disabled; 507 private String keystorePath = System.getProperty("javax.net.ssl.keyStore"); 508 private String keystoreType = "jks"; 509 private String pkcs11Library = "pkcs11.config"; 510 private SSLContext customSSLContext; 511 private String[] enabledSSLProtocols; 512 private String[] enabledSSLCiphers; 513 private HostnameVerifier hostnameVerifier; 514 private EntityBareJid authzid; 515 private CharSequence username; 516 private String password; 517 private Resourcepart resource; 518 private boolean sendPresence = true; 519 private boolean legacySessionDisabled = false; 520 private ProxyInfo proxy; 521 private CallbackHandler callbackHandler; 522 private boolean debuggerEnabled = SmackConfiguration.DEBUG; 523 private SocketFactory socketFactory; 524 private DomainBareJid xmppServiceDomain; 525 private InetAddress hostAddress; 526 private String host; 527 private int port = 5222; 528 private boolean allowEmptyOrNullUsername = false; 529 private boolean saslMechanismsSealed; 530 private Set<String> enabledSaslMechanisms; 531 private X509TrustManager customX509TrustManager; 532 533 protected Builder() { 534 } 535 536 /** 537 * Set the XMPP entities username and password. 538 * <p> 539 * The username is usually the localpart of the clients JID. But some SASL mechanisms or services may require a different 540 * format (e.g. the full JID) as used authorization identity. 541 * </p> 542 * 543 * @param username the username or authorization identity 544 * @param password the password or token used to authenticate 545 * @return a reference to this builder. 546 */ 547 public B setUsernameAndPassword(CharSequence username, String password) { 548 this.username = username; 549 this.password = password; 550 return getThis(); 551 } 552 553 /** 554 * Set the XMPP domain. The XMPP domain is what follows after the '@' sign in XMPP addresses (JIDs). 555 * 556 * @param serviceName the service name 557 * @return a reference to this builder. 558 * @deprecated use {@link #setXmppDomain(DomainBareJid)} instead. 559 */ 560 @Deprecated 561 public B setServiceName(DomainBareJid serviceName) { 562 return setXmppDomain(serviceName); 563 } 564 565 /** 566 * Set the XMPP domain. The XMPP domain is what follows after the '@' sign in XMPP addresses (JIDs). 567 * 568 * @param xmppDomain the XMPP domain. 569 * @return a reference to this builder. 570 */ 571 public B setXmppDomain(DomainBareJid xmppDomain) { 572 this.xmppServiceDomain = xmppDomain; 573 return getThis(); 574 } 575 576 /** 577 * Set the XMPP domain. The XMPP domain is what follows after the '@' sign in XMPP addresses (JIDs). 578 * 579 * @param xmppServiceDomain the XMPP domain. 580 * @return a reference to this builder. 581 * @throws XmppStringprepException if the given string is not a domain bare JID. 582 */ 583 public B setXmppDomain(String xmppServiceDomain) throws XmppStringprepException { 584 this.xmppServiceDomain = JidCreate.domainBareFrom(xmppServiceDomain); 585 return getThis(); 586 } 587 588 /** 589 * Set the resource we are requesting from the server. 590 * <p> 591 * If <code>resource</code> is <code>null</code>, the default, then the server will automatically create a 592 * resource for the client. Note that XMPP clients only suggest this resource to the server. XMPP servers are 593 * allowed to ignore the client suggested resource and instead assign a completely different 594 * resource (see RFC 6120 § 7.7.1). 595 * </p> 596 * 597 * @param resource the resource to use. 598 * @return a reference to this builder. 599 * @see <a href="https://tools.ietf.org/html/rfc6120#section-7.7.1">RFC 6120 § 7.7.1</a> 600 */ 601 public B setResource(Resourcepart resource) { 602 this.resource = resource; 603 return getThis(); 604 } 605 606 /** 607 * Set the resource we are requesting from the server. 608 * 609 * @param resource the non-null CharSequence to use a resource. 610 * @return a reference ot this builder. 611 * @throws XmppStringprepException if the CharSequence is not a valid resourcepart. 612 * @see #setResource(Resourcepart) 613 */ 614 public B setResource(CharSequence resource) throws XmppStringprepException { 615 Objects.requireNonNull(resource, "resource must not be null"); 616 return setResource(Resourcepart.from(resource.toString())); 617 } 618 619 /** 620 * Set the Internet address of the host providing the XMPP service. If set, then this will overwrite anything 621 * set via {@link #setHost(String)}. 622 * 623 * @param address the Internet address of the host providing the XMPP service. 624 * @return a reference to this builder. 625 * @since 4.2 626 */ 627 public B setHostAddress(InetAddress address) { 628 this.hostAddress = address; 629 return getThis(); 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(String 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 unsiged 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 a {@link Session} will be requested on login if the server supports 778 * it. Although this was mandatory on RFC 3921, RFC 6120/6121 don't even 779 * mention this part of the protocol. 780 * <p> 781 * Deprecation notice: This setting is no longer required in most cases because Smack processes the 'optional' 782 * element eventually found in the session stream feature. See also <a 783 * href="https://tools.ietf.org/html/draft-cridland-xmpp-session-01">Here Lies Extensible Messaging and Presence 784 * Protocol (XMPP) Session Establishment</a> 785 * </p> 786 * 787 * @param legacySessionDisabled if a session has to be requested when logging in. 788 * @return a reference to this builder. 789 * @deprecated Smack processes the 'optional' element of the session stream feature. 790 */ 791 @Deprecated 792 public B setLegacySessionDisabled(boolean legacySessionDisabled) { 793 this.legacySessionDisabled = legacySessionDisabled; 794 return getThis(); 795 } 796 797 /** 798 * Sets if an initial available presence will be sent to the server. By default 799 * an available presence will be sent to the server indicating that this presence 800 * is not online and available to receive messages. If you want to log in without 801 * being 'noticed' then pass a <tt>false</tt> value. 802 * 803 * @param sendPresence true if an initial available presence will be sent while logging in. 804 * @return a reference to this builder. 805 */ 806 public B setSendPresence(boolean sendPresence) { 807 this.sendPresence = sendPresence; 808 return getThis(); 809 } 810 811 /** 812 * Sets if the new connection about to be establish is going to be debugged. By 813 * default the value of {@link SmackConfiguration#DEBUG} is used. 814 * 815 * @param debuggerEnabled if the new connection about to be establish is going to be debugged. 816 * @return a reference to this builder. 817 */ 818 public B setDebuggerEnabled(boolean debuggerEnabled) { 819 this.debuggerEnabled = debuggerEnabled; 820 return getThis(); 821 } 822 823 /** 824 * Sets the socket factory used to create new xmppConnection sockets. 825 * This is useful when connecting through SOCKS5 proxies. 826 * 827 * @param socketFactory used to create new sockets. 828 * @return a reference to this builder. 829 */ 830 public B setSocketFactory(SocketFactory socketFactory) { 831 this.socketFactory = socketFactory; 832 return getThis(); 833 } 834 835 /** 836 * Set the information about the Proxy used for the connection. 837 * 838 * @param proxyInfo the Proxy information. 839 * @return a reference to this builder. 840 */ 841 public B setProxyInfo(ProxyInfo proxyInfo) { 842 this.proxy = proxyInfo; 843 return getThis(); 844 } 845 846 /** 847 * Allow <code>null</code> or the empty String as username. 848 * 849 * Some SASL mechanisms (e.g. SASL External) may also signal the username (as "authorization identity"), in 850 * which case Smack should not throw an IllegalArgumentException when the username is not set. 851 * 852 * @return a reference to this builder. 853 */ 854 public B allowEmptyOrNullUsernames() { 855 allowEmptyOrNullUsername = true; 856 return getThis(); 857 } 858 859 /** 860 * Perform anonymous authentication using SASL ANONYMOUS. Your XMPP service must support this authentication 861 * mechanism. This method also calls {@link #addEnabledSaslMechanism(String)} with "ANONYMOUS" as argument. 862 * 863 * @return a reference to this builder. 864 */ 865 public B performSaslAnonymousAuthentication() { 866 if (!SASLAuthentication.isSaslMechanismRegistered(SASLAnonymous.NAME)) { 867 throw new IllegalArgumentException("SASL " + SASLAnonymous.NAME + " is not registered"); 868 } 869 throwIfEnabledSaslMechanismsSet(); 870 871 allowEmptyOrNullUsernames(); 872 addEnabledSaslMechanism(SASLAnonymous.NAME); 873 saslMechanismsSealed = true; 874 return getThis(); 875 } 876 877 /** 878 * Perform authentication using SASL EXTERNAL. Your XMPP service must support this 879 * authentication mechanism. This method also calls {@link #addEnabledSaslMechanism(String)} with "EXTERNAL" as 880 * argument. It also calls {@link #allowEmptyOrNullUsernames()} and {@link #setSecurityMode(ConnectionConfiguration.SecurityMode)} to 881 * {@link SecurityMode#required}. 882 * 883 * @return a reference to this builder. 884 */ 885 public B performSaslExternalAuthentication(SSLContext sslContext) { 886 if (!SASLAuthentication.isSaslMechanismRegistered(SASLMechanism.EXTERNAL)) { 887 throw new IllegalArgumentException("SASL " + SASLMechanism.EXTERNAL + " is not registered"); 888 } 889 setCustomSSLContext(sslContext); 890 throwIfEnabledSaslMechanismsSet(); 891 892 allowEmptyOrNullUsernames(); 893 setSecurityMode(SecurityMode.required); 894 addEnabledSaslMechanism(SASLMechanism.EXTERNAL); 895 saslMechanismsSealed = true; 896 return getThis(); 897 } 898 899 private void throwIfEnabledSaslMechanismsSet() { 900 if (enabledSaslMechanisms != null) { 901 throw new IllegalStateException("Enabled SASL mechanisms found"); 902 } 903 } 904 905 /** 906 * Add the given mechanism to the enabled ones. See {@link #addEnabledSaslMechanism(Collection)} for a discussion about enabled SASL mechanisms. 907 * 908 * @param saslMechanism the name of the mechanism to enable. 909 * @return a reference to this builder. 910 */ 911 public B addEnabledSaslMechanism(String saslMechanism) { 912 return addEnabledSaslMechanism(Arrays.asList(StringUtils.requireNotNullOrEmpty(saslMechanism, 913 "saslMechanism must not be null or empty"))); 914 } 915 916 /** 917 * Enable the given SASL mechanisms. If you never add a mechanism to the set of enabled ones, <b>all mechanisms 918 * known to Smack</b> will be enabled. Only explicitly enable particular SASL mechanisms if you want to limit 919 * the used mechanisms to the enabled ones. 920 * 921 * @param saslMechanisms a collection of names of mechanisms to enable. 922 * @return a reference to this builder. 923 */ 924 public B addEnabledSaslMechanism(Collection<String> saslMechanisms) { 925 if (saslMechanismsSealed) { 926 throw new IllegalStateException("The enabled SASL mechanisms are sealed, you can not add new ones"); 927 } 928 CollectionUtil.requireNotEmpty(saslMechanisms, "saslMechanisms"); 929 Set<String> blacklistedMechanisms = SASLAuthentication.getBlacklistedSASLMechanisms(); 930 for (String mechanism : saslMechanisms) { 931 if (!SASLAuthentication.isSaslMechanismRegistered(mechanism)) { 932 throw new IllegalArgumentException("SASL " + mechanism + " is not avaiable. Consider registering it with Smack"); 933 } 934 if (blacklistedMechanisms.contains(mechanism)) { 935 throw new IllegalArgumentException("SALS " + mechanism + " is blacklisted."); 936 } 937 } 938 if (enabledSaslMechanisms == null) { 939 enabledSaslMechanisms = new HashSet<>(saslMechanisms.size()); 940 } 941 enabledSaslMechanisms.addAll(saslMechanisms); 942 return getThis(); 943 } 944 945 /** 946 * Set the XMPP address to be used as authorization identity. 947 * <p> 948 * In XMPP, authorization identities are bare jids. In general, callers should allow the server to select the 949 * authorization identifier automatically, and not call this. Note that setting the authzid does not set the XMPP 950 * service domain, which should typically match. 951 * Calling this will also SASL CRAM, since this mechanism does not support authzid. 952 * </p> 953 * 954 * @param authzid The BareJid to be requested as the authorization identifier. 955 * @return a reference to this builder. 956 * @see <a href="http://tools.ietf.org/html/rfc6120#section-6.3.8">RFC 6120 § 6.3.8. Authorization Identity</a> 957 * @since 4.2 958 */ 959 public B setAuthzid(EntityBareJid authzid) { 960 this.authzid = authzid; 961 return getThis(); 962 } 963 964 public abstract C build(); 965 966 protected abstract B getThis(); 967 } 968}