/* * Copyright (C) 2007 - 2011 GeoSolutions S.A.S. * http://www.geo-solutions.it * * GPLv3 + Classpath exception * * 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 3 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, see <http://www.gnu.org/licenses/>. */ package it.geosolutions.geostore.core.security.password; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URISyntaxException; import java.net.URL; import java.net.URLConnection; import static it.geosolutions.geostore.core.security.password.SecurityUtils.scramble; import static it.geosolutions.geostore.core.security.password.SecurityUtils.toBytes; import static it.geosolutions.geostore.core.security.password.SecurityUtils.toChars; import org.apache.commons.codec.binary.Base64; import org.apache.commons.io.IOUtils; import org.jasypt.encryption.pbe.StandardPBEByteEncryptor; /** * Master password provider that retrieves and optionally stores the master password from a url. * * @author Lorenzo Natali (lorenzo.natali at geo-solutions.it) */ public final class URLMasterPasswordProvider implements MasterPasswordProvider { private URL URL; private String configDirPath ="."; public void setEncrypting(boolean encrypting) { this.encrypting = encrypting; } private boolean encrypting = true; static final char[] BASE = new char[]{ 'U','n','6','d','I','l','X','T','Q','c','L',')','$','#','q','J', 'U','l','X','Q','U','!','n','n','p','%','U','r','5','U','u','3','5','H','`','x','P','F','r','X' }; static final int[] PERM = new int[] {32,19,30,11,34,26,3,21,9,37,38,13,23,2,18,4,20,1,29,17,0,31,14,36,12,24,15,35,16,39,25,5,10,8,7,6,33,27,28,22 }; /** * Encode the password * @param passwd * @return */ byte[] encode(char[] passwd) { if (!isEncrypting()) { return toBytes(passwd); } //encrypt the password StandardPBEByteEncryptor encryptor = new StandardPBEByteEncryptor(); char[] key = key(); try { encryptor.setPasswordCharArray(key); return Base64.encodeBase64(encryptor.encrypt(toBytes(passwd))); } finally { scramble(key); } } /** * Decode the password * @param passwd * @return */ byte[] decode(byte[] passwd) { if (!isEncrypting()) { return passwd; } //decrypt the password StandardPBEByteEncryptor encryptor = new StandardPBEByteEncryptor(); char[] key = key(); try { encryptor.setPasswordCharArray(key); return encryptor.decrypt(Base64.decodeBase64(passwd)); } finally { scramble(key); } } /** * Generate the key for permutation * @return */ char[] key() { //generate the key return SecurityUtils.permute(BASE, 32, PERM); } /** * Gets the Master Password * */ @Override public char[] doGetMasterPassword() throws Exception { try { InputStream in = input(getURL(), getConfigDir()); try { return toChars(decode(IOUtils.toByteArray(in))); } finally { in.close(); } } catch (IOException e) { throw new RuntimeException(e); } } @Override public void doSetMasterPassword(char[] passwd) throws Exception { OutputStream out = output(getURL(), getConfigDir()); try { out.write(encode(passwd)); } finally { out.close(); } } File getConfigDir() throws IOException { return new File(configDirPath); } /** * Writes the master password in the file * @param url * @param configDir * @return * @throws IOException */ static OutputStream output(URL url, File configDir) throws IOException { //check for file URL if ("file".equalsIgnoreCase(url.getProtocol())) { File f; try { f = new File(url.toURI()); } catch(URISyntaxException e) { f = new File(url.getPath()); } if (!f.isAbsolute()) { //make relative to config dir f = new File(configDir, f.getPath()); } return new FileOutputStream(f); } else { URLConnection cx = url.openConnection(); cx.setDoOutput(true); return cx.getOutputStream(); } } static InputStream input(URL url, File configDir) throws IOException { //check for a file url if(url == null){ //default master password url = URLMasterPasswordProvider.class.getClassLoader().getResource("passwd"); } if ("file".equalsIgnoreCase(url.getProtocol())) { File f; try { f = new File(url.toURI()); } catch(URISyntaxException e) { f = new File(url.getPath()); } //check if the file is relative if (!f.isAbsolute()) { //make it relative to the config directory for this password provider f = new File(configDir, f.getPath()); } return new FileInputStream(f); } else { return url.openStream(); } } /** * * @return the config dir path */ public String getConfigDirPath() { return configDirPath; } /** * Set the config dir path * @param path */ public void setConfigDirPath(String path){ this.configDirPath = path; } /** * Set the URL of the master password file * @return */ public URL getURL() { // TODO Auto-generated method stub return URL; } /** * Set the URL of the master password file * @param url url of the master password file */ public void setURL(URL url) { // TODO Auto-generated method stub this.URL=url; } /** * is encrypting * @return */ private boolean isEncrypting() { return encrypting; } }