All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ucar.nc2.util.net.HTTPAuthStore Maven / Gradle / Ivy

Go to download

The NetCDF-Java Library is a Java interface to NetCDF files, as well as to many other types of scientific data formats.

The newest version!
/*
 * Copyright 1998-2009 University Corporation for Atmospheric Research/Unidata
 *
 * Portions of this software were developed by the Unidata Program at the
 * University Corporation for Atmospheric Research.
 *
 * Access and use of this software shall impose the following obligations
 * and understandings on the user. The user is granted the right, without
 * any fee or cost, to use, copy, modify, alter, enhance and distribute
 * this software, and any derivative works thereof, and its supporting
 * documentation for any purpose whatsoever, provided that this entire
 * notice appears in all copies of the software, derivative works and
 * supporting documentation.  Further, UCAR requests that the user credit
 * UCAR/Unidata in any publications that result from the use of this
 * software or in any product that includes this software. The names UCAR
 * and/or Unidata, however, may not be used in any advertising or publicity
 * to endorse or promote any products or commercial entity unless specific
 * written permission is obtained from UCAR/Unidata. The user also
 * understands that UCAR/Unidata is not obligated to provide the user with
 * any support, consulting, training or assistance of any kind with regard
 * to the use, operation and performance of this software nor to provide
 * the user with any updates, revisions, new versions or "bug fixes."
 *
 * THIS SOFTWARE IS PROVIDED BY UCAR/UNIDATA "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL UCAR/UNIDATA BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 * WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package ucar.nc2.util.net;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;
import java.io.*;

import org.apache.commons.httpclient.auth.*;

import javax.crypto.*;
import javax.crypto.spec.*;


/**

HTTPAuthStore stores tuples of authorization information in a thread
safe manner.  It currently supports serial access, but can be extended
to support single writer / multiple reader semantics
using the procedures
{acquire,release}writeaccess
and
{acquire,release}readaccess

 */

//Package local scope
class HTTPAuthStore implements Serializable
{


//////////////////////////////////////////////////////////////////////////
static public org.slf4j.Logger log
                = org.slf4j.LoggerFactory.getLogger(HTTPSession.class);
//////////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////
/**

The auth store is (conceptually) a set of tuples (rows) of the form
HTTPAuthScheme(scheme) X String(url) X CredentialsProvider(creds).
The creds column specifies the kind of authorization
(e.g. basic, keystore, etc) and the info to support it.
The functional relationship is (scheme,url)=>creds.
*/

static public class Entry implements Serializable, Comparable
{
    public HTTPAuthScheme scheme;
    public String url; // possibly including user info
    public CredentialsProvider creds;

    public Entry()
    {
	    this(ANY_ENTRY);
    }

    /**
     * @param entry
     */

    public Entry(Entry entry)
    {
	if(entry == null) entry = ANY_ENTRY;
	constructor(entry.scheme,entry.url,entry.creds);
    }

    /**
     * @param scheme
     * @param uri
     * @param creds
     */

    public Entry(HTTPAuthScheme scheme, String uri, CredentialsProvider creds)
    {
	constructor(scheme, uri, creds);
    }

    /**
     * Shared constructor code
     * @param scheme
     * @param uri
     * @param creds
     */

    protected void constructor(HTTPAuthScheme scheme, String uri, CredentialsProvider creds)
    {
	if(uri == null) uri = ANY_URL;
        if(scheme == null) scheme = DEFAULT_SCHEME;
	this.scheme = scheme;
	this.url = uri;
	this.creds = creds;
    }

    public boolean valid()
    {
	return (scheme != null && url != null);
    }

    public String toString()
    {
	String creds = (this.creds == null ? "null" : this.creds.toString());
        return String.format("%s:%s{%s}",scheme, url,creds);
    }

    private void writeObject(java.io.ObjectOutputStream oos)
        throws IOException
    {
        oos.writeObject(this.scheme);
        oos.writeObject(this.url);
        // serializing the credentials provider is a bit tricky
        // since it might not support the serializable interface.
        boolean isser = (this.creds instanceof Serializable);
        oos.writeObject(isser);
        if(isser)
            oos.writeObject(this.creds);
        else {
            oos.writeObject(this.creds.getClass());
        }
    }

    private void readObject(java.io.ObjectInputStream ois)
            throws IOException, ClassNotFoundException
    {
        this.scheme = (HTTPAuthScheme)ois.readObject();
        this.url = (String)ois.readObject();
        // serializing the credentials provider is a bit tricky
        // since it might not support the serializable interface.
        boolean isser = (Boolean)ois.readObject();
        Object o = ois.readObject();
        if(isser)
            this.creds = (CredentialsProvider)o;
        else {
            try {
                this.creds = (CredentialsProvider)((Class)o).newInstance();
            } catch (Exception e) {
                throw new ClassNotFoundException("Cannot create CredentialsProvider instance",e);
            }
        }
    }

    /**
      * return 0 if e1 == e2, 1 if e1 > e2
      * and -1 if e1 < e2 using the following tests
      * null, => 0
      * !null,null => -1
      * null,!null => +1
      * e1.scheme :: e2.scheme
      * compareURI(e1.url,e2.url) => e2.url.compare(e1.url) (note reverse order)
      *
      * Assume that the first argument comes from the pattern
      * and the second comes from the AuthStore
      */

    //////////////////////////////////////////////////
    // Comparable interface

    public int compareTo(Object o1)
    {
        if(!(o1 instanceof Entry)) return +1;
        Entry e1 = this;
        Entry e2 = (Entry)o1;
        if(e1 == null && e2 == null) return 0;
        if(e1 != null && e2 == null) return +1;
        if(e1 == null && e2 != null) return -1;
        int cmp = e1.scheme.compareTo(e2.scheme);
        if(cmp != 0) return cmp;
        if(compatibleURL(e1.url,e2.url))
            return e2.url.compareTo(e1.url);
        return e1.url.compareTo(e2.url);
    }

    //////////////////////////////////////////////////
    // Comparator interface

    public boolean equals(Entry e)
    {
        return this.compareTo(e) == 0;
    }

    //////////////////////////////////////////////////
    // Additional comparison functions

    // Used in search
    static protected boolean matches(Entry e1, Entry e2)
    {
	if(e1 == null && e2 == null) return true;
	if(e1 != null && e2 == null) return false;
	if(e1 == null && e2 != null) return false;

        if(e1.scheme != ANY_SCHEME && e2.scheme != ANY_SCHEME
           && e1.scheme != e2.scheme)
            return false;

	if(!compatibleURL(e1.url,e2.url))
            return false;
        
        return true;
    }

    // Uses in insert and remove
    static public boolean identical(Entry e1, Entry e2)
    {
        return (e1.scheme == e2.scheme &&
                (e1.url == e2.url // null test
                 || e1.url.equals(e2.url)));
    }


}

//////////////////////////////////////////////////

static public final boolean          SCHEME = true;
static public final String           ANY_URL = "";
static public final HTTPAuthScheme   ANY_SCHEME = HTTPAuthScheme.ANY;
static public final HTTPAuthScheme   DEFAULT_SCHEME = HTTPAuthScheme.BASIC;

static final public Entry            ANY_ENTRY = new Entry(ANY_SCHEME,ANY_URL,null);

static private List rows;


static {
     rows = new ArrayList();

    // For back compatibility, check some system properties
    // and add appropriate entries
    // 1. ESG keystore support
    String kpath = System.getProperty("keystore");
    if(kpath != null) {
        String tpath = System.getProperty("truststore");
        String kpwd = System.getProperty("keystorepassword");
        String tpwd = System.getProperty("truststorepassword");
        kpath = kpath.trim();
        if(tpath != null) tpath = tpath.trim();
        if(kpwd != null) kpwd = kpwd.trim();
        if(tpwd != null) tpwd = tpwd.trim();
        if(kpath.length() == 0) kpath = null;
        if(tpath.length() == 0) tpath = null;
        if(kpwd.length() == 0) kpwd = null;
        if(tpwd.length() == 0) tpwd = null;

        CredentialsProvider creds = new HTTPSSLProvider(kpath,kpwd,tpath,tpwd);
        try {
            insert(new Entry(HTTPAuthScheme.SSL,ANY_URL,creds));
        }   catch (HTTPException he) {
            log.error("HTTPAuthStore: could not insert default SSL data");
        }
     }

}

/**
 * Define URI compatibility.
 */
static protected boolean compatibleURL(String u1, String u2)
{   
    if(u1 == u2) return true;
    if(u1 == null) return false;
    if(u2 == null) return false;

    if(u1.equals(u2)
       || u1.startsWith(u2)
       || u2.startsWith(u1)) return true;

    // Check piece by piece
    URI uu1;
    URI uu2;
    try {
        uu1 = new URI(u1);
    } catch (URISyntaxException use) {
        return false;
    }
    try {
        uu2 = new URI(u2);
    } catch (URISyntaxException use) {
        return false;
    }

    // For the following we want this truth table
    // s1    s2    t/f
    // ---------------
    //  null  null  match
    //  null !null  !match
    // !null  null  !match
    // !null !null  match = s1.equals(s2)
    // The if statement condition is the negation of match, namely:
    // if((s1 != null || s2 != null)
    //    && s1 != null && s2 != null && !s1.equals(s2))
    //    return false; // => !match

    // protocols comparison
    String s1 = uu1.getScheme();
    String s2 = uu2.getScheme();
    if((s1 != null || s2 != null)
       && s1 != null && s2 != null && !s1.equals(s2))
        return false;

    // Match user info; differs from table above
    // because we allow added user info to match null
    //  null  null  match
    //  null !null  match <-- different
    // !null  null  !match
    // !null !null  match = s1.equals(s2)
    s1 = uu1.getUserInfo();
    s2 = uu2.getUserInfo();
    if(s1 != null
       && (s2 == null || !s1.equals(s2)))
        return false;

    // hosts must be same
    s1 = uu1.getHost();
    s2 = uu2.getHost();
    if((s1 != null || s2 != null)
       && s1 != null && s2 != null && !s1.equals(s2))
        return false;

    // ports must be the same
    if(uu1.getPort() != uu2.getPort())
        return false;

    // paths must have prefix relationship
    // and missing is a prefix of anything
    // s1    s2    t/f
    // ---------------
    //  null  null  match
    //  null !null  !match
    // !null  null  !match
    // !null !null  match = (s1.startsWith(s2)||s2.startsWith(s1))
    s1 = uu1.getRawPath();
    s2 = uu2.getRawPath();
    if((s1 != null || s2 != null)
       && s1 != null && s2 != null && !(s1.startsWith(s2) || s2.startsWith(s1)))
        return false;

    return true;
}

//////////////////////////////////////////////////
/**
Primary external interface
 */

/**
 * @param entry
 * @return true if entry already existed and was replaced
 */

static synchronized public boolean
insert(Entry entry)
    throws HTTPException
{
    boolean rval = false;
    Entry found = null;

    if(entry == null || !entry.valid())
	throw new HTTPException("HTTPAuthStore.insert: invalid entry: " + entry);

    for(Entry e: rows) {
        if(Entry.identical(e,entry)) {
	    found = e;
	    break;
	}
    }
    // If the entry already exists, then overwrite it and return true
    if(found != null) {
        found.creds = entry.creds;
	rval = true;
    } else {
        Entry newentry = new Entry(entry);
        rows.add(newentry);
    }
    return rval;
}

/**
 * @param entry
 * @return true if entry existed and was removed
 */

static synchronized public boolean
remove(Entry entry)
    throws HTTPException
{
    Entry found = null;

    if(entry == null || !entry.valid())
	    throw new HTTPException("HTTPAuthStore.remove: invalid entry: " + entry);

    for(Entry e: rows) {
	if(Entry.identical(e,entry)) {
	    found = e;
	    break;
	}
    }
    if(found != null) rows.remove(found);
    return (found != null);
}

/**
 * Remove all auth store entries
 */
static synchronized public void
clear() throws HTTPException
{
   rows.clear();
}

/**
 * Return all entries in the auth store
 */
static public List
getAllRows()
{
  return rows;
}

/**
 * Search:
 * 
 * Search match is defined by the compatibleURI function above.
 * The return list is ordered from most restrictive to least restrictive.
 * 
 * @param entry
 * @return list of matching entries
 */
static synchronized public Entry[]
search(Entry entry)
{

    if(entry == null || !entry.valid() || rows.size() == 0)
        return new Entry[0];

    List matches = new ArrayList();

    for(Entry e: rows) {
        Entry e1 = e;
        if(Entry.matches(entry,e1)) {
            matches.add(e);
        }
    }
    // Sort by scheme then by url, where any_url is last
    Entry[] matchvec = matches.toArray(new Entry[matches.size()]);
    Arrays.sort(matchvec);
    return matchvec;
}

//////////////////////////////////////////////////
// Misc.


static public AuthScope
getAuthScope(Entry entry)
{
    if(entry == null) return null;
    URI uri;
    try {
	uri = new URI(entry.url);
    } catch(URISyntaxException use) {return null;}

    String host = uri.getHost();
    int port = uri.getPort();
    String realm = uri.getRawPath();
    String scheme = (entry.scheme == null ? null : entry.scheme.getSchemeName());

    if(host == null) host = AuthScope.ANY_HOST;
    if(port <= 0) port = AuthScope.ANY_PORT;
    if(realm == null) realm = AuthScope.ANY_REALM;
    AuthScope as = new AuthScope(host,port,realm);
    return as;
}


//////////////////////////////////////////////////
/**
n-readers/1-writer semantics
Note not synchronized because only called
by other synchronized procedures
 */

static int nwriters = 0;
static int nreaders = 0;
static boolean stop = false;

private void
acquirewriteaccess() throws HTTPException
{
    nwriters++;
    while(nwriters > 1) {
	try { wait(); } catch (InterruptedException e) {
	    if(stop) throw new HTTPException("interrupted");
        }
    }
    while(nreaders > 0) {
	try { wait(); } catch (InterruptedException e) {
	    if(stop) throw new HTTPException("interrupted");
        }
    }
}

private void
releasewriteaccess()
{
    nwriters--;
    notify();
}

private void
acquirereadaccess() throws HTTPException
{
    nreaders++;
    while(nwriters > 0) {
	try { wait(); } catch (InterruptedException e) {
	    if(stop) throw new HTTPException("interrupted");
        }
    }
}

private void
releasereadaccess()
{
    nreaders--;
    if(nreaders == 0) notify(); //only affects writers
}

///////////////////////////////////////////////////
// Print functions

static public void
print(PrintStream p)
	throws IOException
{
    print(new PrintWriter(p,true));
}

static public void
print(PrintWriter p)
	throws IOException
{
    List elist = getAllRows();
    for(int i=0;i entries = getDeserializedEntries(istream,password);
    for(Entry e: entries) {
        insert(e);
    }
}

static public List
getDeserializedEntries(InputStream istream, String password)
	throws HTTPException
{
    try {

    // Create Key
    byte key[] = password.getBytes();
    DESKeySpec desKeySpec = new DESKeySpec(key);
    SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
    SecretKey secretKey = keyFactory.generateSecret(desKeySpec);

    // Create Cipher
    Cipher desCipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
    desCipher.init(Cipher.DECRYPT_MODE, secretKey);

    // Create crypto stream
    BufferedInputStream bis = new BufferedInputStream(istream);
    CipherInputStream cis = new CipherInputStream(bis, desCipher);
    ObjectInputStream ois = new ObjectInputStream(cis);

    List entries = new ArrayList();
    int count = ois.readInt();
    for(int i=0;i




© 2015 - 2024 Weber Informatics LLC | Privacy Policy