/**
* '$RCSfile$'
* Copyright: 2013 Regents of the University of California and the
* National Center for Ecological Analysis and Synthesis
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package edu.ucsb.nceas.metacat.authentication;
import java.io.Console;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.ConnectException;
import java.util.HashMap;
import java.util.List;
import java.util.Vector;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.XMLConfiguration;
import org.apache.commons.configuration.tree.xpath.XPathExpressionEngine;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.ucsb.nceas.metacat.AuthInterface;
import edu.ucsb.nceas.metacat.AuthLdap;
import edu.ucsb.nceas.metacat.properties.PropertyService;
import edu.ucsb.nceas.metacat.util.SystemUtil;
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
/**
* This an authentication class base on a username/password file.
* It is an alternative authentication mechanism of the ldap authentication.
* The password file looks like:
*
*
*
*
* *******
* foo@foo.com
* Smith
* John
* NCEAS
* nceas-dev
*
*
*
*
* developers at NCEAS
*
*
*
* http://commons.apache.org/proper/commons-configuration/userguide/howto_xml.html
* @author tao
*
*/
public class AuthFile implements AuthInterface {
private static final String ORGANIZATIONNAME = "Unknown";
private static final String ORGANIZATION = "organization";
private static final String NAME = "name";
private static final String DN = "dn";
private static final String DESCRIPTION = "description";
private static final String PASSWORD = "password";
private static final String SLASH = "/";
private static final String AT = "@";
private static final String SUBJECTS = "subjects";
private static final String USERS = "users";
private static final String USER = "user";
private static final String GROUPS = "groups";
private static final String GROUP = "group";
private static final String EMAIL = "email";
private static final String SURNAME = "surName";
private static final String GIVENNAME = "givenName";
private static final String MEMBEROF = "memberof";
private static final String INITCONTENT = "\n"+
"<"+SUBJECTS+">\n"+"<"+USERS+">\n"+""+USERS+">\n"+"<"+GROUPS+">\n"+""+GROUPS+">\n"+""+SUBJECTS+">\n";
private static Log log = LogFactory.getLog(AuthFile.class);
private static XMLConfiguration userpassword = null;
private String authURI = null;
private static String passwordFilePath = null;
private static AuthFileHashInterface hashClass = null;
private boolean readPathFromProperty = true;
/**
* Get the instance of the AuthFile
* @return
* @throws AuthenticationException
*/
/*public static AuthFile getInstance() throws AuthenticationException {
if(authFile == null) {
authFile = new AuthFile();
}
return authFile;
}*/
/**
* Get the instance of the AuthFile from specified password file
* @return
* @throws AuthenticationException
*/
/*public static AuthFile getInstance(String passwordFile) throws AuthenticationException {
passwordFilePath = passwordFile;
if(authFile == null) {
authFile = new AuthFile();
}
return authFile;
}*/
/**
* Constructor
*/
public AuthFile() throws AuthenticationException {
try {
init();
} catch (Exception e) {
e.printStackTrace();
throw new AuthenticationException(e.getMessage());
}
}
/**
*
* @param passwordFile
* @throws AuthenticationException
*/
public AuthFile (String passwordFile) throws AuthenticationException {
passwordFilePath = passwordFile;
readPathFromProperty = false;
try {
init();
} catch (Exception e) {
e.printStackTrace();
throw new AuthenticationException(e.getMessage());
}
}
/*
* Initialize the user/password configuration
*/
private void init() throws PropertyNotFoundException, IOException, ConfigurationException, ClassNotFoundException, InstantiationException, IllegalAccessException {
if(readPathFromProperty || passwordFilePath == null) {
passwordFilePath = PropertyService.getProperty("auth.file.path");
}
//System.out.println("the password file path is ======================= "+passwordFilePath);
File passwordFile = new File(passwordFilePath);
authURI = SystemUtil.getContextURL();
String hashClassName = PropertyService.getProperty("auth.file.hashClassName");
Class classDefinition = Class.forName(hashClassName);
Object object = classDefinition.newInstance();
hashClass = (AuthFileHashInterface) object;
//if the password file doesn't exist, create a new one and set the initial content
if(!passwordFile.exists()) {
File parent = passwordFile.getParentFile();
if(!parent.exists()) {
boolean success = false;
try {
success = parent.mkdirs();
} catch (Exception e) {
throw new IOException("AuthFile.init - couldn't create the directory "+parent.getAbsolutePath()+ " since "+e.getMessage());
}
if(!success) {
throw new IOException("AuthFile.init - couldn't create the directory "+parent.getAbsolutePath()+ ", probably since the metacat doesn't have the write permission.");
}
}
boolean success = false;
try {
success = passwordFile.createNewFile();
} catch (Exception e) {
throw new IOException("AuthFile.init - couldn't create the file "+passwordFile.getAbsolutePath()+ " since "+e.getMessage());
}
if(!success) {
throw new IOException("AuthFile.init - couldn't create the file "+parent.getAbsolutePath()+ ", probably since the metacat doesn't have the write permission.");
}
OutputStreamWriter writer = null;
FileOutputStream output = null;
try {
output = new FileOutputStream(passwordFile);
writer = new OutputStreamWriter(output, "UTF-8");
writer.write(INITCONTENT);
} finally {
writer.close();
output.close();
}
}
userpassword = new XMLConfiguration(passwordFile);
userpassword.setExpressionEngine(new XPathExpressionEngine());
userpassword.setAutoSave(true);
userpassword.setDelimiterParsingDisabled(true);
userpassword.setAttributeSplittingDisabled(true);
}
@Override
public boolean authenticate(String user, String password)
throws AuthenticationException {
boolean match = false;
String passwordRecord = userpassword.getString(USERS+SLASH+USER+"["+AT+DN+"='"+user+"']"+SLASH+PASSWORD);
if(passwordRecord != null) {
try {
match = hashClass.match(password, passwordRecord);
} catch (Exception e) {
throw new AuthenticationException(e.getMessage());
}
}
return match;
}
@Override
/**
* Get all users. This is two-dimmention array. Each row is a user. The first element of
* a row is the user name. The second element is common name. The third one is the organization name (null).
* The fourth one is the organization unit name (null). The fifth one is the email address.
*/
public String[][] getUsers(String user, String password)
throws ConnectException {
List