Package org.rssowl.core.connection

Source Code of org.rssowl.core.connection.PlatformCredentialsProvider$Credentials

/*   **********************************************************************  **
**   Copyright notice                                                       **
**                                                                          **
**   (c) 2005-2009 RSSOwl Development Team                                  **
**   http://www.rssowl.org/                                                 **
**                                                                          **
**   All rights reserved                                                    **
**                                                                          **
**   This program and the accompanying materials are made available under   **
**   the terms of the Eclipse Public License v1.0 which accompanies this    **
**   distribution, and is available at:                                     **
**   http://www.rssowl.org/legal/epl-v10.html                               **
**                                                                          **
**   A copy is found in the file epl-v10.html and important notices to the  **
**   license from the team is found in the textfile LICENSE.txt distributed **
**   in this package.                                                       **
**                                                                          **
**   This copyright notice MUST APPEAR in all copies of the file!           **
**                                                                          **
**   Contributors:                                                          **
**     RSSOwl Development Team - initial API and implementation             **
**                                                                          **
**  **********************************************************************  */

package org.rssowl.core.connection;

import org.eclipse.core.net.proxy.IProxyData;
import org.eclipse.core.net.proxy.IProxyService;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Platform;
import org.eclipse.equinox.internal.security.storage.friends.InternalExchangeUtils;
import org.eclipse.equinox.security.storage.EncodingUtils;
import org.eclipse.equinox.security.storage.ISecurePreferences;
import org.eclipse.equinox.security.storage.SecurePreferencesFactory;
import org.eclipse.equinox.security.storage.StorageException;
import org.eclipse.equinox.security.storage.provider.IProviderHints;
import org.rssowl.core.Owl;
import org.rssowl.core.internal.Activator;
import org.rssowl.core.internal.InternalOwl;
import org.rssowl.core.internal.persist.pref.DefaultPreferences;
import org.rssowl.core.persist.pref.IPreferenceScope;
import org.rssowl.core.util.URIUtils;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
* The default implementation of the ICredentialsProvider retrieves
* authentication Credentials from the Equinox Security Storage.
*
* @author bpasero
*/
@SuppressWarnings("restriction")
public class PlatformCredentialsProvider implements ICredentialsProvider {

  /* Node for feed related security preferences */
  private static final String SECURE_FEED_NODE = "rssowl/feeds"; //$NON-NLS-1$

  /* File with credentials stored */
  private static final String SECURE_STORAGE_FILE = ".credentials"; //$NON-NLS-1$

  /* ID of the Win32 dependent password provider (win32) */
  private static final String WIN_PW_PROVIDER_ID = "org.eclipse.equinox.security.WindowsPasswordProvider"; //$NON-NLS-1$

  /* ID of the RSSOwl password provider (Dialog asking for Master Password) */
  private static final String RSSOWL_PW_PROVIDER_ID = "org.rssowl.ui.RSSOwlPasswordProvider"; //$NON-NLS-1$

  /* ID of the MacOS dependent password provider */
  private static final String MACOS_PW_PROVIDER_ID = "org.eclipse.equinox.security.OSXKeystoreIntegration"; //$NON-NLS-1$

  /* Unique Key to store Usernames */
  private static final String USERNAME = "org.rssowl.core.connection.auth.Username"; //$NON-NLS-1$

  /* Unique Key to store Passwords */
  private static final String PASSWORD = "org.rssowl.core.connection.auth.Password"; //$NON-NLS-1$

  /* Unique Key to store Domains */
  private static final String DOMAIN = "org.rssowl.core.connection.auth.Domain"; //$NON-NLS-1$

  /* Default Realm being used to store credentials */
  private static final String REALM = ""; //$NON-NLS-1$

  /* A cache of non-protected Links (in the form Link + Realm) */
  private final Set<String> fUnprotectedLinksCache = Collections.synchronizedSet(new HashSet<String>());

  /* Simple POJO Implementation of ICredentials */
  private static class Credentials implements ICredentials {
    private String fUsername;
    private String fPassword;
    private String fDomain;

    Credentials(String username, String password, String domain) {
      fUsername = username;
      fPassword = password;
      fDomain = domain;
    }

    public String getUsername() {
      return fUsername;
    }

    public String getPassword() {
      return fPassword;
    }

    public String getDomain() {
      return fDomain;
    }
  }

  /*
   * @see
   * org.rssowl.core.connection.ICredentialsProvider#getAuthCredentials(java
   * .net.URI, java.lang.String)
   */
  public synchronized ICredentials getAuthCredentials(URI link, String realm) throws CredentialsException {

    /* Check Cache first */
    if (checkCacheProtected(link.toString(), realm))
      return null;

    /* Retrieve Credentials */
    ICredentials authorizationInfo = getAuthorizationInfo(link, realm);

    /* Credentials Provided */
    if (authorizationInfo != null)
      return authorizationInfo;

    /* Cache as unprotected */
    addCacheProtected(link.toString(), realm);

    /* Credentials not provided */
    return null;
  }

  private ISecurePreferences getSecurePreferences() {
    if (!InternalOwl.IS_ECLIPSE) {
      IPreferenceScope prefs = Owl.getPreferenceService().getGlobalScope();
      boolean useOSPasswordProvider = prefs.getBoolean(DefaultPreferences.USE_OS_PASSWORD);

      /* Disable OS Password if Master Password shall be used */
      if (prefs.getBoolean(DefaultPreferences.USE_MASTER_PASSWORD))
        useOSPasswordProvider = false;

      /* Try storing credentials in profile folder */
      try {
        Activator activator = Activator.getDefault();

        /* Check if Bundle is Stopped */
        if (activator == null)
          return null;

        IPath stateLocation = activator.getStateLocation();
        stateLocation = stateLocation.append(SECURE_STORAGE_FILE);
        URL location = stateLocation.toFile().toURL();
        Map<String, String> options = null;

        /* Use OS dependent password provider if available */
        if (useOSPasswordProvider) {
          if (Platform.OS_WIN32.equals(Platform.getOS())) {
            options = new HashMap<String, String>();
            options.put(IProviderHints.REQUIRED_MODULE_ID, WIN_PW_PROVIDER_ID);
          } else if (Platform.OS_MACOSX.equals(Platform.getOS())) {
            options = new HashMap<String, String>();
            options.put(IProviderHints.REQUIRED_MODULE_ID, MACOS_PW_PROVIDER_ID);
          }
        }

        /* Use RSSOwl password provider */
        else {
          options = new HashMap<String, String>();
          options.put(IProviderHints.REQUIRED_MODULE_ID, RSSOWL_PW_PROVIDER_ID);
        }

        return SecurePreferencesFactory.open(location, options);
      } catch (MalformedURLException e) {
        Activator.safeLogError(e.getMessage(), e);
      } catch (IllegalStateException e1) {
        Activator.safeLogError(e1.getMessage(), e1);
      } catch (IOException e2) {
        Activator.safeLogError(e2.getMessage(), e2);
      }
    }

    /* Fallback to default location */
    return SecurePreferencesFactory.getDefault();
  }

  private ICredentials getAuthorizationInfo(URI link, String realm) throws CredentialsException {
    ISecurePreferences securePreferences = getSecurePreferences();

    /* Check if Bundle is Stopped */
    if (securePreferences == null)
      return null;

    /* Return from Equinox Security Storage */
    if (securePreferences.nodeExists(SECURE_FEED_NODE)) { // Global Feed Node
      ISecurePreferences allFeedsPreferences = securePreferences.node(SECURE_FEED_NODE);
      if (allFeedsPreferences.nodeExists(EncodingUtils.encodeSlashes(link.toString()))) { // Feed Node
        ISecurePreferences feedPreferences = allFeedsPreferences.node(EncodingUtils.encodeSlashes(link.toString()));
        if (feedPreferences.nodeExists(EncodingUtils.encodeSlashes(realm != null ? realm : REALM))) { // Realm Node
          ISecurePreferences realmPreferences = feedPreferences.node(EncodingUtils.encodeSlashes(realm != null ? realm : REALM));

          try {
            String username = realmPreferences.get(USERNAME, null);
            String password = realmPreferences.get(PASSWORD, null);
            String domain = realmPreferences.get(DOMAIN, null);

            if (username != null && password != null)
              return new Credentials(username, password, domain);
          } catch (StorageException e) {
            throw new CredentialsException(Activator.getDefault().createErrorStatus(e.getMessage(), e));
          }
        }
      }
    }

    return null;
  }

  /*
   * @see
   * org.rssowl.core.connection.auth.ICredentialsProvider#getProxyCredentials
   * (java.net.URI)
   */
  public IProxyCredentials getProxyCredentials(URI link) {
    Activator activator = Activator.getDefault();

    /* Check if Bundle is Stopped */
    if (activator == null)
      return null;

    IProxyService proxyService = activator.getProxyService();

    /* Check if Proxy is enabled */
    if (!proxyService.isProxiesEnabled())
      return null;

    String host = URIUtils.safeGetHost(link);
    boolean isSSL = "https".equals(link.getScheme()); //$NON-NLS-1$

    /* Retrieve Proxy Data */
    final IProxyData proxyData = proxyService.getProxyDataForHost(host, isSSL ? IProxyData.HTTPS_PROXY_TYPE : IProxyData.HTTP_PROXY_TYPE);
    if (proxyData != null) {
      return new IProxyCredentials() {
        public String getHost() {
          return proxyData.getHost();
        }

        public int getPort() {
          return proxyData.getPort();
        }

        public String getDomain() {
          return null;
        }

        public String getPassword() {
          return proxyData.getPassword();
        }

        public String getUsername() {
          return proxyData.getUserId();
        }
      };
    }

    /* Feed does not require Proxy or Credentials not supplied */
    return null;
  }

  /*
   * @see
   * org.rssowl.core.connection.ICredentialsProvider#setAuthCredentials(org.
   * rssowl.core.connection.ICredentials, java.net.URI, java.lang.String)
   */
  public void setAuthCredentials(ICredentials credentials, URI link, String realm) throws CredentialsException {
    ISecurePreferences securePreferences = getSecurePreferences();

    /* Check if Bundle is Stopped */
    if (securePreferences == null)
      return;

    /* Store in Equinox Security Storage */
    ISecurePreferences allFeedsPreferences = securePreferences.node(SECURE_FEED_NODE);
    ISecurePreferences feedPreferences = allFeedsPreferences.node(EncodingUtils.encodeSlashes(link.toString()));
    ISecurePreferences realmPreference = feedPreferences.node(EncodingUtils.encodeSlashes(realm != null ? realm : REALM));

    IPreferenceScope globalScope = Owl.getPreferenceService().getGlobalScope();

    /* OS Password is only supported on Windows and Mac */
    boolean useOSPassword = globalScope.getBoolean(DefaultPreferences.USE_OS_PASSWORD);
    if (!Platform.OS_WIN32.equals(Platform.getOS()) && !Platform.OS_MACOSX.equals(Platform.getOS()))
      useOSPassword = false;

    boolean encryptPW = useOSPassword || globalScope.getBoolean(DefaultPreferences.USE_MASTER_PASSWORD);
    try {
      if (credentials.getUsername() != null)
        realmPreference.put(USERNAME, credentials.getUsername(), encryptPW);

      if (credentials.getPassword() != null)
        realmPreference.put(PASSWORD, credentials.getPassword(), encryptPW);

      if (credentials.getDomain() != null)
        realmPreference.put(DOMAIN, credentials.getDomain(), encryptPW);

      realmPreference.flush(); // Flush to disk early
    } catch (StorageException e) {
      throw new CredentialsException(Activator.getDefault().createErrorStatus(e.getMessage(), e));
    } catch (IOException e) {
      throw new CredentialsException(Activator.getDefault().createErrorStatus(e.getMessage(), e));
    }

    /* Uncache */
    removeCacheProtected(link.toString(), realm);
  }

  /*
   * @see
   * org.rssowl.core.connection.auth.ICredentialsProvider#setProxyCredentials
   * (org.rssowl.core.connection.auth.IProxyCredentials, java.net.URI)
   */
  public void setProxyCredentials(IProxyCredentials credentials, URI link) {
    IProxyService proxyService = Activator.getDefault().getProxyService();
    proxyService.setProxiesEnabled(true);
    boolean isSSL = "https".equals(link.getScheme()); //$NON-NLS-1$

    /* Retrieve Proxy Data */
    final IProxyData proxyData = proxyService.getProxyData(isSSL ? IProxyData.HTTPS_PROXY_TYPE : IProxyData.HTTP_PROXY_TYPE);
    if (proxyData != null) { //TODO What if Data is NULL?
      proxyData.setHost(credentials.getHost());
      proxyData.setPort(credentials.getPort());
      proxyData.setUserid(credentials.getUsername());
      proxyData.setPassword(credentials.getPassword());
    }
  }

  /*
   * @see
   * org.rssowl.core.connection.ICredentialsProvider#deleteAuthCredentials(java
   * .net.URI, java.lang.String)
   */
  public synchronized void deleteAuthCredentials(URI link, String realm) throws CredentialsException {
    ISecurePreferences securePreferences = getSecurePreferences();

    /* Check if Bundle is Stopped */
    if (securePreferences == null)
      return;

    /* Remove from Equinox Security Storage */
    if (securePreferences.nodeExists(SECURE_FEED_NODE)) { // Global Feed Node
      ISecurePreferences allFeedsPreferences = securePreferences.node(SECURE_FEED_NODE);
      if (allFeedsPreferences.nodeExists(EncodingUtils.encodeSlashes(link.toString()))) { // Feed Node
        ISecurePreferences feedPreferences = allFeedsPreferences.node(EncodingUtils.encodeSlashes(link.toString()));
        if (feedPreferences.nodeExists(EncodingUtils.encodeSlashes(realm != null ? realm : REALM))) { // Realm Node
          ISecurePreferences realmPreferences = feedPreferences.node(EncodingUtils.encodeSlashes(realm != null ? realm : REALM));
          realmPreferences.clear();
          realmPreferences.removeNode();
          try {
            feedPreferences.flush();
          } catch (IOException e) {
            throw new CredentialsException(Activator.getDefault().createErrorStatus(e.getMessage(), e));
          }
        }
      }
    }

    /* Delete from Cache */
    removeCacheProtected(link.toString(), realm);
  }

  /*
   * @see
   * org.rssowl.core.connection.auth.ICredentialsProvider#deleteProxyCredentials
   * (java.net.URI)
   */
  public void deleteProxyCredentials(URI link) {
    IProxyService proxyService = Activator.getDefault().getProxyService();
    proxyService.setProxiesEnabled(false);
    //TODO System Properties are still set?
  }

  /**
   * An internal method only available for the
   * {@link PlatformCredentialsProvider} to clear all secure preferences nodes.
   * This method is called e.g. when the master password is to be changed or
   * disabled.
   */
  public void clear() {

    /* Clear cached info */
    InternalExchangeUtils.passwordProvidersReset();

    /* Remove all Nodes */
    ISecurePreferences secureRoot = getSecurePreferences();

    /* Check if Bundle is Stopped */
    if (secureRoot == null)
      return;

    String[] childrenNames = secureRoot.childrenNames();
    for (String child : childrenNames) {
      secureRoot.node(child).removeNode();
    }

    /* Flush to Disk */
    try {
      secureRoot.flush();
    } catch (IOException e) {
      Activator.getDefault().logError(e.getMessage(), e);
    }
  }

  private boolean checkCacheProtected(String link, String realm) {
    return fUnprotectedLinksCache.contains(toCacheKey(link, realm));
  }

  private void addCacheProtected(String link, String realm) {
    String cacheKey = toCacheKey(link, realm);
    if (!fUnprotectedLinksCache.contains(cacheKey))
      fUnprotectedLinksCache.add(cacheKey);
  }

  private void removeCacheProtected(String link, String realm) {
    fUnprotectedLinksCache.remove(toCacheKey(link, realm));
  }

  private String toCacheKey(String link, String realm) {
    if (realm == null)
      realm = REALM;

    return link + realm;
  }
}
TOP

Related Classes of org.rssowl.core.connection.PlatformCredentialsProvider$Credentials

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.