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