/* * JBoss, Home of Professional Open Source * * Copyright 2013 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.picketlink.identity.federation.core.saml.v2.metadata.store; import org.picketlink.common.ErrorCodes; import org.picketlink.common.PicketLinkLogger; import org.picketlink.common.PicketLinkLoggerFactory; import org.picketlink.common.exceptions.ParsingException; import org.picketlink.common.exceptions.ProcessingException; import org.picketlink.common.util.StaxParserUtil; import org.picketlink.common.util.StaxUtil; import org.picketlink.common.util.StringUtil; import org.picketlink.identity.federation.core.constants.PicketLinkFederationConstants; import org.picketlink.identity.federation.core.parsers.saml.metadata.SAMLEntityDescriptorParser; import org.picketlink.identity.federation.core.saml.v2.writers.SAMLMetadataWriter; import org.picketlink.identity.federation.saml.v2.metadata.EntityDescriptorType; import org.picketlink.identity.federation.saml.v2.metadata.EntityDescriptorType.EDTChoiceType; import org.picketlink.identity.federation.saml.v2.metadata.EntityDescriptorType.EDTDescriptorChoiceType; import org.picketlink.identity.federation.saml.v2.metadata.IDPSSODescriptorType; import org.picketlink.identity.federation.saml.v2.metadata.SPSSODescriptorType; import javax.xml.stream.XMLStreamWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.StringTokenizer; /** * File based metadata store that uses the ${user.home}/jbid-store location to persist the data * * @author Anil.Saldhana@redhat.com * @since Apr 27, 2009 */ public class FileBasedMetadataConfigurationStore implements IMetadataConfigurationStore { private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger(); private String userHome = null; private String baseDirectory = null; public FileBasedMetadataConfigurationStore() { bootstrap(); } /** * @see {@code IMetadataConfigurationStore#bootstrap()} */ public void bootstrap() { userHome = SecurityActions.getSystemProperty("user.home"); if (userHome == null) throw logger.systemPropertyMissingError("user.home"); StringBuilder builder = new StringBuilder(userHome); builder.append(PicketLinkFederationConstants.FILE_STORE_DIRECTORY); baseDirectory = builder.toString(); File plStore = new File(baseDirectory); if (plStore.exists() == false) { logger.trace(plStore.getPath() + " does not exist. Hence creating."); plStore.mkdir(); } } /** * @see IMetadataConfigurationStore#getIdentityProviderID() */ public Set<String> getIdentityProviderID() { Set<String> identityProviders = new HashSet<String>(); Properties idp = new Properties(); StringBuilder builder = new StringBuilder(baseDirectory); builder.append(PicketLinkFederationConstants.IDP_PROPERTIES); File identityProviderFile = new File(builder.toString()); if (identityProviderFile.exists()) { FileInputStream fis = null; try { fis = new FileInputStream(identityProviderFile); idp.load(fis); String listOfIDP = (String) idp.get("IDP"); if (StringUtil.isNotNull(listOfIDP)) { identityProviders.addAll(StringUtil.tokenize(listOfIDP)); } } catch (Exception e) { logger.samlMetaDataIdentityProviderLoadingError(e); } finally { if(fis != null){ try { fis.close(); } catch (IOException e) { } } } } return identityProviders; } /** * @see IMetadataConfigurationStore#getServiceProviderID() */ public Set<String> getServiceProviderID() { Set<String> serviceProviders = new HashSet<String>(); Properties sp = new Properties(); StringBuilder builder = new StringBuilder(baseDirectory); builder.append(PicketLinkFederationConstants.SP_PROPERTIES); File serviceProviderFile = new File(builder.toString()); if (serviceProviderFile.exists()) { FileInputStream fis = null; try { fis = new FileInputStream(serviceProviderFile); sp.load(fis); String listOfSP = (String) sp.get("SP"); // Comma separated list StringTokenizer st = new StringTokenizer(listOfSP, ","); while (st.hasMoreTokens()) { String token = st.nextToken(); serviceProviders.add(token); } } catch (Exception e) { logger.samlMetaDataServiceProviderLoadingError(e); } finally { if(fis != null){ try { fis.close(); } catch (IOException e) { } } } } return serviceProviders; } /** * @see IMetadataConfigurationStore#load(String) */ public EntityDescriptorType load(String id) throws IOException { File persistedFile = validateIdAndReturnMDFile(id); SAMLEntityDescriptorParser parser = new SAMLEntityDescriptorParser(); try { return (EntityDescriptorType) parser.parse(StaxParserUtil.getXMLEventReader(new FileInputStream(persistedFile))); } catch (ParsingException e) { throw new RuntimeException(e); } } /** * @see IMetadataConfigurationStore#persist(EntityDescriptorType, String) */ public void persist(EntityDescriptorType entity, String id) throws IOException { File persistedFile = validateIdAndReturnMDFile(id); try { XMLStreamWriter streamWriter = StaxUtil.getXMLStreamWriter(new FileOutputStream(persistedFile)); SAMLMetadataWriter writer = new SAMLMetadataWriter(streamWriter); writer.writeEntityDescriptor(entity); } catch (ProcessingException e) { throw new RuntimeException(e); } logger.trace("Persisted entity descriptor into " + persistedFile.getPath()); // Process the EDT List<EDTChoiceType> edtChoiceTypeList = entity.getChoiceType(); for (EDTChoiceType edtChoiceType : edtChoiceTypeList) { List<EDTDescriptorChoiceType> edtDescriptorChoiceTypeList = edtChoiceType.getDescriptors(); for (EDTDescriptorChoiceType edtDesc : edtDescriptorChoiceTypeList) { IDPSSODescriptorType idpSSO = edtDesc.getIdpDescriptor(); if (idpSSO != null) { addIdentityProvider(id); } SPSSODescriptorType spSSO = edtDesc.getSpDescriptor(); if (spSSO != null) { addServiceProvider(id); } } } } /** * @see IMetadataConfigurationStore#delete(String) */ public void delete(String id) { File persistedFile = validateIdAndReturnMDFile(id); if (persistedFile.exists()) persistedFile.delete(); } /** * @throws IOException * @throws ClassNotFoundException * @see IMetadataConfigurationStore#loadTrustedProviders(String) */ @SuppressWarnings("unchecked") public Map<String, String> loadTrustedProviders(String id) throws IOException, ClassNotFoundException { File trustedFile = validateIdAndReturnTrustedProvidersFile(id); ObjectInputStream ois = null; try { ois = new ObjectInputStream(new FileInputStream(trustedFile)); Map<String, String> trustedMap = (Map<String, String>) ois.readObject(); return trustedMap; } finally { if (ois != null) { try { ois.close(); } catch (IOException ioe) { } } } } /** * @throws IOException * @see IMetadataConfigurationStore#persistTrustedProviders(Map) */ public void persistTrustedProviders(String id, Map<String, String> trusted) throws IOException { File trustedFile = validateIdAndReturnTrustedProvidersFile(id); ObjectOutputStream oos = null; try { oos = new ObjectOutputStream(new FileOutputStream(trustedFile)); oos.writeObject(trusted); } finally { if (oos != null) { try { oos.close(); } catch (IOException ioe) { } } } logger.trace("Persisted trusted map into " + trustedFile.getPath()); } /** * @see IMetadataConfigurationStore#deleteTrustedProviders(String) */ public void deleteTrustedProviders(String id) { File persistedFile = validateIdAndReturnTrustedProvidersFile(id); if (persistedFile.exists()) persistedFile.delete(); } private File validateIdAndReturnMDFile(String id) { String serializationExtension = PicketLinkFederationConstants.SERIALIZATION_EXTENSION; if (id == null) throw new IllegalArgumentException(ErrorCodes.NULL_ARGUMENT + "id"); if (!id.endsWith(serializationExtension)) id += serializationExtension; StringBuilder builder = new StringBuilder(baseDirectory); builder.append("/").append(id); return new File(builder.toString()); } private File validateIdAndReturnTrustedProvidersFile(String id) { if (id == null) throw new IllegalArgumentException(ErrorCodes.NULL_ARGUMENT + "id"); id += "-trusted" + PicketLinkFederationConstants.SERIALIZATION_EXTENSION; StringBuilder builder = new StringBuilder(baseDirectory); builder.append("/").append(id); return new File(builder.toString()); } private void addServiceProvider(String id) { Properties sp = new Properties(); StringBuilder builder = new StringBuilder(baseDirectory); builder.append(PicketLinkFederationConstants.SP_PROPERTIES); File serviceProviderFile = new File(builder.toString()); FileInputStream fileInputStream = null; try { if (serviceProviderFile.exists() == false) serviceProviderFile.createNewFile(); fileInputStream = new FileInputStream(serviceProviderFile); sp.load(fileInputStream); String listOfSP = (String) sp.get("SP"); if (listOfSP == null) { listOfSP = id; } else { listOfSP += "," + id; } sp.put("SP", listOfSP); sp.store(new FileWriter(serviceProviderFile), ""); } catch (Exception e) { logger.samlMetaDataServiceProviderLoadingError(e); } finally { if(fileInputStream != null){ try{ fileInputStream.close(); } catch (IOException ioe){ } } } } private void addIdentityProvider(String id) { Properties idp = new Properties(); StringBuilder builder = new StringBuilder(baseDirectory); builder.append(PicketLinkFederationConstants.IDP_PROPERTIES); File idpProviderFile = new File(builder.toString()); FileInputStream fileInputStream = null; try { if (idpProviderFile.exists() == false) idpProviderFile.createNewFile(); fileInputStream = new FileInputStream(idpProviderFile); idp.load(fileInputStream); String listOfIDP = (String) idp.get("IDP"); if (listOfIDP == null) { listOfIDP = id; } else { listOfIDP += "," + id; } idp.put("IDP", listOfIDP); idp.store(new FileWriter(idpProviderFile), ""); } catch (Exception e) { logger.samlMetaDataIdentityProviderLoadingError(e); } finally { if(fileInputStream != null){ try{ fileInputStream.close(); } catch (IOException ioe){ } } } } /** * @see {@code IMetadataConfigurationStore#cleanup()} */ public void cleanup() { } }