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