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 org.jivesoftware.smack.packet.Session; 021import org.jivesoftware.smack.proxy.ProxyInfo; 022import org.jivesoftware.smack.util.DNSUtil; 023import org.jivesoftware.smack.util.dns.HostAddress; 024 025import javax.net.SocketFactory; 026import javax.net.ssl.HostnameVerifier; 027import javax.net.ssl.SSLContext; 028import javax.security.auth.callback.CallbackHandler; 029 030import java.util.ArrayList; 031import java.util.Collections; 032import java.util.List; 033 034/** 035 * Configuration to use while establishing the connection to the server. It is possible to 036 * configure the path to the trustore file that keeps the trusted CA root certificates and 037 * enable or disable all or some of the checkings done while verifying server certificates.<p> 038 * 039 * It is also possible to configure if TLS, SASL, and compression are used or not. 040 * 041 * @author Gaston Dombiak 042 */ 043public class ConnectionConfiguration implements Cloneable { 044 045 /** 046 * Hostname of the XMPP server. Usually servers use the same service name as the name 047 * of the server. However, there are some servers like google where host would be 048 * talk.google.com and the serviceName would be gmail.com. 049 */ 050 private String serviceName; 051 052 protected List<HostAddress> hostAddresses; 053 054 private String keystorePath; 055 private String keystoreType; 056 private String pkcs11Library; 057 private SSLContext customSSLContext; 058 059 private boolean compressionEnabled = false; 060 061 /** 062 * Used to get information from the user 063 */ 064 private CallbackHandler callbackHandler; 065 066 private boolean debuggerEnabled = SmackConfiguration.DEBUG_ENABLED; 067 068 // Flag that indicates if a reconnection should be attempted when abruptly disconnected 069 private boolean reconnectionAllowed = true; 070 071 // Holds the socket factory that is used to generate the socket in the connection 072 private SocketFactory socketFactory; 073 074 // Holds the authentication information for future reconnections 075 private String username; 076 private String password; 077 private String resource; 078 private boolean sendPresence = true; 079 private boolean rosterLoadedAtLogin = true; 080 private boolean legacySessionDisabled = false; 081 private boolean useDnsSrvRr = true; 082 private SecurityMode securityMode = SecurityMode.enabled; 083 084 private HostnameVerifier hostnameVerifier; 085 086 /** 087 * Permanent store for the Roster, needed for roster versioning 088 */ 089 private RosterStore rosterStore; 090 091 // Holds the proxy information (such as proxyhost, proxyport, username, password etc) 092 protected ProxyInfo proxy; 093 094 /** 095 * Creates a new ConnectionConfiguration for the specified service name. 096 * A DNS SRV lookup will be performed to find out the actual host address 097 * and port to use for the connection. 098 * 099 * @param serviceName the name of the service provided by an XMPP server. 100 */ 101 public ConnectionConfiguration(String serviceName) { 102 init(serviceName, ProxyInfo.forDefaultProxy()); 103 } 104 105 /** 106 * Creates a new ConnectionConfiguration for the specified service name 107 * with specified proxy. 108 * A DNS SRV lookup will be performed to find out the actual host address 109 * and port to use for the connection. 110 * 111 * @param serviceName the name of the service provided by an XMPP server. 112 * @param proxy the proxy through which XMPP is to be connected 113 */ 114 public ConnectionConfiguration(String serviceName,ProxyInfo proxy) { 115 init(serviceName, proxy); 116 } 117 118 /** 119 * Creates a new ConnectionConfiguration using the specified host, port and 120 * service name. This is useful for manually overriding the DNS SRV lookup 121 * process that's used with the {@link #ConnectionConfiguration(String)} 122 * constructor. For example, say that an XMPP server is running at localhost 123 * in an internal network on port 5222 but is configured to think that it's 124 * "example.com" for testing purposes. This constructor is necessary to connect 125 * to the server in that case since a DNS SRV lookup for example.com would not 126 * point to the local testing server. 127 * 128 * @param host the host where the XMPP server is running. 129 * @param port the port where the XMPP is listening. 130 * @param serviceName the name of the service provided by an XMPP server. 131 */ 132 public ConnectionConfiguration(String host, int port, String serviceName) { 133 initHostAddresses(host, port); 134 init(serviceName, ProxyInfo.forDefaultProxy()); 135 } 136 137 /** 138 * Creates a new ConnectionConfiguration using the specified host, port and 139 * service name. This is useful for manually overriding the DNS SRV lookup 140 * process that's used with the {@link #ConnectionConfiguration(String)} 141 * constructor. For example, say that an XMPP server is running at localhost 142 * in an internal network on port 5222 but is configured to think that it's 143 * "example.com" for testing purposes. This constructor is necessary to connect 144 * to the server in that case since a DNS SRV lookup for example.com would not 145 * point to the local testing server. 146 * 147 * @param host the host where the XMPP server is running. 148 * @param port the port where the XMPP is listening. 149 * @param serviceName the name of the service provided by an XMPP server. 150 * @param proxy the proxy through which XMPP is to be connected 151 */ 152 public ConnectionConfiguration(String host, int port, String serviceName, ProxyInfo proxy) { 153 initHostAddresses(host, port); 154 init(serviceName, proxy); 155 } 156 157 /** 158 * Creates a new ConnectionConfiguration for a connection that will connect 159 * to the desired host and port. 160 * 161 * @param host the host where the XMPP server is running. 162 * @param port the port where the XMPP is listening. 163 */ 164 public ConnectionConfiguration(String host, int port) { 165 initHostAddresses(host, port); 166 init(host, ProxyInfo.forDefaultProxy()); 167 } 168 169 /** 170 * Creates a new ConnectionConfiguration for a connection that will connect 171 * to the desired host and port with desired proxy. 172 * 173 * @param host the host where the XMPP server is running. 174 * @param port the port where the XMPP is listening. 175 * @param proxy the proxy through which XMPP is to be connected 176 */ 177 public ConnectionConfiguration(String host, int port, ProxyInfo proxy) { 178 initHostAddresses(host, port); 179 init(host, proxy); 180 } 181 182 protected void init(String serviceName, ProxyInfo proxy) { 183 this.serviceName = serviceName; 184 this.proxy = proxy; 185 186 keystorePath = System.getProperty("javax.net.ssl.keyStore"); 187 keystoreType = "jks"; 188 pkcs11Library = "pkcs11.config"; 189 190 //Setting the SocketFactory according to proxy supplied 191 socketFactory = proxy.getSocketFactory(); 192 } 193 194 /** 195 * Sets the server name, also known as XMPP domain of the target server. 196 * 197 * @param serviceName the XMPP domain of the target server. 198 */ 199 void setServiceName(String serviceName) { 200 this.serviceName = serviceName; 201 } 202 203 /** 204 * Returns the server name of the target server. 205 * 206 * @return the server name of the target server. 207 */ 208 public String getServiceName() { 209 return serviceName; 210 } 211 212 /** 213 * Returns the TLS security mode used when making the connection. By default, 214 * the mode is {@link SecurityMode#enabled}. 215 * 216 * @return the security mode. 217 */ 218 public SecurityMode getSecurityMode() { 219 return securityMode; 220 } 221 222 /** 223 * Sets the TLS security mode used when making the connection. By default, 224 * the mode is {@link SecurityMode#enabled}. 225 * 226 * @param securityMode the security mode. 227 */ 228 public void setSecurityMode(SecurityMode securityMode) { 229 this.securityMode = securityMode; 230 } 231 232 /** 233 * Retuns the path to the keystore file. The key store file contains the 234 * certificates that may be used to authenticate the client to the server, 235 * in the event the server requests or requires it. 236 * 237 * @return the path to the keystore file. 238 */ 239 public String getKeystorePath() { 240 return keystorePath; 241 } 242 243 /** 244 * Sets the path to the keystore file. The key store file contains the 245 * certificates that may be used to authenticate the client to the server, 246 * in the event the server requests or requires it. 247 * 248 * @param keystorePath the path to the keystore file. 249 */ 250 public void setKeystorePath(String keystorePath) { 251 this.keystorePath = keystorePath; 252 } 253 254 /** 255 * Returns the keystore type, or <tt>null</tt> if it's not set. 256 * 257 * @return the keystore type. 258 */ 259 public String getKeystoreType() { 260 return keystoreType; 261 } 262 263 /** 264 * Sets the keystore type. 265 * 266 * @param keystoreType the keystore type. 267 */ 268 public void setKeystoreType(String keystoreType) { 269 this.keystoreType = keystoreType; 270 } 271 272 273 /** 274 * Returns the PKCS11 library file location, needed when the 275 * Keystore type is PKCS11. 276 * 277 * @return the path to the PKCS11 library file 278 */ 279 public String getPKCS11Library() { 280 return pkcs11Library; 281 } 282 283 /** 284 * Sets the PKCS11 library file location, needed when the 285 * Keystore type is PKCS11 286 * 287 * @param pkcs11Library the path to the PKCS11 library file 288 */ 289 public void setPKCS11Library(String pkcs11Library) { 290 this.pkcs11Library = pkcs11Library; 291 } 292 293 /** 294 * Gets the custom SSLContext previously set with {@link #setCustomSSLContext(SSLContext)} for 295 * SSL sockets. This is null by default. 296 * 297 * @return the custom SSLContext or null. 298 */ 299 public SSLContext getCustomSSLContext() { 300 return this.customSSLContext; 301 } 302 303 /** 304 * Sets a custom SSLContext for creating SSL sockets. 305 * <p> 306 * For more information on how to create a SSLContext see <a href= 307 * "http://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#X509TrustManager" 308 * >Java Secure Socket Extension (JSEE) Reference Guide: Creating Your Own X509TrustManager</a> 309 * 310 * @param context the custom SSLContext for new sockets 311 */ 312 public void setCustomSSLContext(SSLContext context) { 313 this.customSSLContext = context; 314 } 315 316 /** 317 * Set the HostnameVerifier used to verify the hostname of SSLSockets used by XMPP connections 318 * created with this ConnectionConfiguration. 319 * 320 * @param verifier 321 */ 322 public void setHostnameVerifier(HostnameVerifier verifier) { 323 hostnameVerifier = verifier; 324 } 325 326 /** 327 * Returns the configured HostnameVerifier of this ConnectionConfiguration or the Smack default 328 * HostnameVerifier configured with 329 * {@link SmackConfiguration#setDefaultHostnameVerifier(HostnameVerifier)}. 330 * 331 * @return a configured HostnameVerifier or <code>null</code> 332 */ 333 public HostnameVerifier getHostnameVerifier() { 334 if (hostnameVerifier != null) 335 return hostnameVerifier; 336 return SmackConfiguration.getDefaultHostnameVerifier(); 337 } 338 339 /** 340 * Returns true if the connection is going to use stream compression. Stream compression 341 * will be requested after TLS was established (if TLS was enabled) and only if the server 342 * offered stream compression. With stream compression network traffic can be reduced 343 * up to 90%. By default compression is disabled. 344 * 345 * @return true if the connection is going to use stream compression. 346 */ 347 public boolean isCompressionEnabled() { 348 return compressionEnabled; 349 } 350 351 /** 352 * Sets if the connection is going to use stream compression. Stream compression 353 * will be requested after TLS was established (if TLS was enabled) and only if the server 354 * offered stream compression. With stream compression network traffic can be reduced 355 * up to 90%. By default compression is disabled. 356 * 357 * @param compressionEnabled if the connection is going to use stream compression. 358 */ 359 public void setCompressionEnabled(boolean compressionEnabled) { 360 this.compressionEnabled = compressionEnabled; 361 } 362 363 /** 364 * Returns true if the new connection about to be establish is going to be debugged. By 365 * default the value of {@link SmackConfiguration#DEBUG_ENABLED} is used. 366 * 367 * @return true if the new connection about to be establish is going to be debugged. 368 */ 369 public boolean isDebuggerEnabled() { 370 return debuggerEnabled; 371 } 372 373 /** 374 * Sets if the new connection about to be establish is going to be debugged. By 375 * default the value of {@link SmackConfiguration#DEBUG_ENABLED} is used. 376 * 377 * @param debuggerEnabled if the new connection about to be establish is going to be debugged. 378 */ 379 public void setDebuggerEnabled(boolean debuggerEnabled) { 380 this.debuggerEnabled = debuggerEnabled; 381 } 382 383 /** 384 * Sets if the reconnection mechanism is allowed to be used. By default 385 * reconnection is allowed. 386 * 387 * @param isAllowed if the reconnection mechanism should be enabled for this connection. 388 */ 389 public void setReconnectionAllowed(boolean isAllowed) { 390 this.reconnectionAllowed = isAllowed; 391 } 392 393 /** 394 * Returns if the reconnection mechanism is allowed to be used. By default reconnection is 395 * allowed. You can disable the reconnection mechanism with {@link 396 * #setReconnectionAllowed(boolean)}. 397 * 398 * @return true, if the reconnection mechanism is enabled. 399 */ 400 public boolean isReconnectionAllowed() { 401 return this.reconnectionAllowed; 402 } 403 404 /** 405 * Sets the socket factory used to create new xmppConnection sockets. 406 * This is useful when connecting through SOCKS5 proxies. 407 * 408 * @param socketFactory used to create new sockets. 409 */ 410 public void setSocketFactory(SocketFactory socketFactory) { 411 this.socketFactory = socketFactory; 412 } 413 414 /** 415 * Sets if an initial available presence will be sent to the server. By default 416 * an available presence will be sent to the server indicating that this presence 417 * is not online and available to receive messages. If you want to log in without 418 * being 'noticed' then pass a <tt>false</tt> value. 419 * 420 * @param sendPresence true if an initial available presence will be sent while logging in. 421 */ 422 public void setSendPresence(boolean sendPresence) { 423 this.sendPresence = sendPresence; 424 } 425 426 /** 427 * Returns true if the roster will be loaded from the server when logging in. This 428 * is the common behaviour for clients but sometimes clients may want to differ this 429 * or just never do it if not interested in rosters. 430 * 431 * @return true if the roster will be loaded from the server when logging in. 432 */ 433 public boolean isRosterLoadedAtLogin() { 434 return rosterLoadedAtLogin; 435 } 436 437 /** 438 * Sets if the roster will be loaded from the server when logging in. This 439 * is the common behaviour for clients but sometimes clients may want to differ this 440 * or just never do it if not interested in rosters. 441 * 442 * @param rosterLoadedAtLogin if the roster will be loaded from the server when logging in. 443 */ 444 public void setRosterLoadedAtLogin(boolean rosterLoadedAtLogin) { 445 this.rosterLoadedAtLogin = rosterLoadedAtLogin; 446 } 447 448 /** 449 * Returns true if a {@link Session} will be requested on login if the server 450 * supports it. Although this was mandatory on RFC 3921, RFC 6120/6121 don't 451 * even mention this part of the protocol. 452 * 453 * @return true if a session has to be requested when logging in. 454 */ 455 public boolean isLegacySessionDisabled() { 456 return legacySessionDisabled; 457 } 458 459 /** 460 * Sets if a {@link Session} will be requested on login if the server supports 461 * it. Although this was mandatory on RFC 3921, RFC 6120/6121 don't even 462 * mention this part of the protocol. 463 * 464 * @param legacySessionDisabled if a session has to be requested when logging in. 465 */ 466 public void setLegacySessionDisabled(boolean legacySessionDisabled) { 467 this.legacySessionDisabled = legacySessionDisabled; 468 } 469 470 /** 471 * Returns a CallbackHandler to obtain information, such as the password or 472 * principal information during the SASL authentication. A CallbackHandler 473 * will be used <b>ONLY</b> if no password was specified during the login while 474 * using SASL authentication. 475 * 476 * @return a CallbackHandler to obtain information, such as the password or 477 * principal information during the SASL authentication. 478 */ 479 public CallbackHandler getCallbackHandler() { 480 return callbackHandler; 481 } 482 483 /** 484 * Sets a CallbackHandler to obtain information, such as the password or 485 * principal information during the SASL authentication. A CallbackHandler 486 * will be used <b>ONLY</b> if no password was specified during the login while 487 * using SASL authentication. 488 * 489 * @param callbackHandler to obtain information, such as the password or 490 * principal information during the SASL authentication. 491 */ 492 public void setCallbackHandler(CallbackHandler callbackHandler) { 493 this.callbackHandler = callbackHandler; 494 } 495 496 /** 497 * Returns the socket factory used to create new xmppConnection sockets. 498 * This is useful when connecting through SOCKS5 proxies. 499 * 500 * @return socketFactory used to create new sockets. 501 */ 502 public SocketFactory getSocketFactory() { 503 return this.socketFactory; 504 } 505 506 public List<HostAddress> getHostAddresses() { 507 return Collections.unmodifiableList(hostAddresses); 508 } 509 510 /** 511 * Set the permanent roster store 512 */ 513 public void setRosterStore(RosterStore store) { 514 rosterStore = store; 515 } 516 517 /** 518 * Get the permanent roster store 519 */ 520 public RosterStore getRosterStore() { 521 return rosterStore; 522 } 523 524 525 /** 526 * An enumeration for TLS security modes that are available when making a connection 527 * to the XMPP server. 528 */ 529 public static enum SecurityMode { 530 531 /** 532 * Securirty via TLS encryption is required in order to connect. If the server 533 * does not offer TLS or if the TLS negotiaton fails, the connection to the server 534 * will fail. 535 */ 536 required, 537 538 /** 539 * Security via TLS encryption is used whenever it's available. This is the 540 * default setting. 541 */ 542 enabled, 543 544 /** 545 * Security via TLS encryption is disabled and only un-encrypted connections will 546 * be used. If only TLS encryption is available from the server, the connection 547 * will fail. 548 */ 549 disabled 550 } 551 552 /** 553 * Returns the username to use when trying to reconnect to the server. 554 * 555 * @return the username to use when trying to reconnect to the server. 556 */ 557 public String getUsername() { 558 return this.username; 559 } 560 561 /** 562 * Returns the password to use when trying to reconnect to the server. 563 * 564 * @return the password to use when trying to reconnect to the server. 565 */ 566 public String getPassword() { 567 return this.password; 568 } 569 570 /** 571 * Returns the resource to use when trying to reconnect to the server. 572 * 573 * @return the resource to use when trying to reconnect to the server. 574 */ 575 public String getResource() { 576 return resource; 577 } 578 579 /** 580 * Returns true if an available presence should be sent when logging in while reconnecting. 581 * 582 * @return true if an available presence should be sent when logging in while reconnecting 583 */ 584 public boolean isSendPresence() { 585 return sendPresence; 586 } 587 588 void setLoginInfo(String username, String password, String resource) { 589 this.username = username; 590 this.password = password; 591 this.resource = resource; 592 } 593 594 void maybeResolveDns() throws Exception { 595 if (!useDnsSrvRr) return; 596 hostAddresses = DNSUtil.resolveXMPPDomain(serviceName); 597 } 598 599 private void initHostAddresses(String host, int port) { 600 hostAddresses = new ArrayList<HostAddress>(1); 601 HostAddress hostAddress; 602 hostAddress = new HostAddress(host, port); 603 hostAddresses.add(hostAddress); 604 useDnsSrvRr = false; 605 } 606}