OCSPManager.java

  1. /*
  2.  * GovWay - A customizable API Gateway
  3.  * https://govway.org
  4.  *
  5.  * Copyright (c) 2005-2025 Link.it srl (https://link.it).
  6.  *
  7.  * This program is free software: you can redistribute it and/or modify
  8.  * it under the terms of the GNU General Public License version 3, as published by
  9.  * the Free Software Foundation.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  18.  *
  19.  */

  20. package org.openspcoop2.utils.certificate.ocsp;

  21. import java.io.File;
  22. import java.io.FileInputStream;
  23. import java.io.InputStream;
  24. import java.util.ArrayList;
  25. import java.util.Collections;
  26. import java.util.Enumeration;
  27. import java.util.HashMap;
  28. import java.util.List;
  29. import java.util.Map;
  30. import java.util.Properties;

  31. import org.openspcoop2.utils.SortedMap;
  32. import org.openspcoop2.utils.UtilsException;
  33. import org.openspcoop2.utils.properties.PropertiesReader;
  34. import org.slf4j.Logger;

  35. /**
  36.  * OCSPManager
  37.  *
  38.  * @author Poli Andrea (apoli@link.it)
  39.  * @author $Author$
  40.  * @version $Rev$, $Date$
  41.  */
  42. public class OCSPManager {

  43.     private static OCSPManager staticInstance;
  44.     public static synchronized void init(File f, boolean throwNotExists, boolean loadDefault, Logger log) throws UtilsException {
  45.         if(staticInstance==null) {
  46.             staticInstance = new OCSPManager(f, throwNotExists, loadDefault, log);
  47.         }
  48.     }
  49.     public static OCSPManager getInstance() {
  50.         // spotbugs warning 'SING_SINGLETON_GETTER_NOT_SYNCHRONIZED': l'istanza viene creata allo startup
  51.         if (staticInstance == null) {
  52.             synchronized (OCSPManager.class) {
  53.                 if (staticInstance == null) {
  54.                     return null;
  55.                 }
  56.             }
  57.         }
  58.         return staticInstance;
  59.     }
  60.    
  61.     private HashMap<String, OCSPConfig> hsmOCSPConfigMapIDtoConfig = new HashMap<>();
  62.    
  63.     private HashMap<String, String> hsmOCSPConfigMapTypeToID = new HashMap<>();
  64.     private HashMap<String, String> hsmOCSPConfigMapLabelToID = new HashMap<>();
  65.    
  66.     private SortedMap<String> hsmOCSPConfigSortedMapTypeLabel = new SortedMap<>();
  67.    
  68.     private OCSPManager(File f, boolean throwNotExists, boolean loadDefault, Logger log) throws UtilsException {
  69.         if(!f.exists()) {
  70.             if(throwNotExists) {
  71.                 throw new UtilsException("File '"+f.getAbsolutePath()+"' not exists");
  72.             }
  73.             else {
  74.                 if(loadDefault) {
  75.                     try {
  76.                         try(InputStream isDefault = OCSPManager.class.getResourceAsStream("/org/openspcoop2/utils/certificate/ocsp/default.properties")){
  77.                             if(isDefault!=null) {
  78.                                 Properties p = new Properties();
  79.                                 try {
  80.                                     p.load(isDefault);
  81.                                 }catch(Exception t) {
  82.                                     throw new UtilsException("File '"+f.getAbsolutePath()+"'; initialize error: "+t.getMessage(),t);
  83.                                 }
  84.                                 init(p, log);
  85.                             }
  86.                         }
  87.                     }catch(Exception t) {
  88.                         throw new UtilsException("Default configuration; initialize error: "+t.getMessage(),t);
  89.                     }
  90.                 }
  91.             }
  92.         }
  93.         else {
  94.             if(!f.canRead()) {
  95.                 throw new UtilsException("File '"+f.getAbsolutePath()+"' cannot read");
  96.             }
  97.             Properties p = new Properties();
  98.             try {
  99.                 try(FileInputStream fin = new FileInputStream(f)){
  100.                     p.load(fin);
  101.                 }
  102.             }catch(Exception t) {
  103.                 throw new UtilsException("File '"+f.getAbsolutePath()+"'; initialize error: "+t.getMessage(),t);
  104.             }
  105.             init(p, log);
  106.         }
  107.     }
  108.     /**private OCSPManager(Properties p, Logger log) throws UtilsException {
  109.         init(p, log);
  110.     }*/
  111.     private void init(Properties p, Logger log) throws UtilsException {
  112.        
  113.         List<String> idKeystore = new ArrayList<>();
  114.        
  115.         if(p!=null && !p.isEmpty()) {
  116.            
  117.             Enumeration<?> enKeys = p.keys();
  118.             while (enKeys.hasMoreElements()) {
  119.                 Object object = enKeys.nextElement();
  120.                 if(object instanceof String) {
  121.                     String key = (String) object;
  122.                    
  123.                     if(key.startsWith(OCSPCostanti.PROPERTY_PREFIX) && key.length()>(OCSPCostanti.PROPERTY_PREFIX.length())) {
  124.                         String tmp = key.substring(OCSPCostanti.PROPERTY_PREFIX.length());
  125.                         if(tmp!=null && tmp.contains(".")) {
  126.                             int indeoOf = tmp.indexOf(".");
  127.                             if(indeoOf>0) {
  128.                                 String idK = tmp.substring(0,indeoOf);
  129.                                 if(!idKeystore.contains(idK)) {
  130.                                     idKeystore.add(idK);
  131.                                 }
  132.                             }
  133.                         }
  134.                     }
  135.                 }
  136.             }
  137.            
  138.         }
  139.        
  140.         if(!idKeystore.isEmpty()) {
  141.            
  142.             List<String> types = new ArrayList<>();
  143.             List<String> labels = new ArrayList<>();
  144.            
  145.             for (String idK : idKeystore) {
  146.                 String prefix = OCSPCostanti.PROPERTY_PREFIX + idK + ".";
  147.                 PropertiesReader pReader = new PropertiesReader(p, true);
  148.                 Properties pKeystore = pReader.readProperties_convertEnvProperties(prefix);
  149.                 OCSPConfig ocspConfig = new OCSPConfig(idK, pKeystore, log);
  150.                
  151.                 // type (value è id del ocsp.properties)
  152.                 boolean alreadyExists = false;
  153.                 for (String type : this.hsmOCSPConfigMapTypeToID.keySet()) {
  154.                     if(ocspConfig.getType().equalsIgnoreCase(type)) {
  155.                         alreadyExists = true;
  156.                     }
  157.                 }
  158.                 if(alreadyExists) {
  159.                     throw new UtilsException("Same ocsp type found for responder '"+this.hsmOCSPConfigMapTypeToID.get(ocspConfig.getType())+"' e '"+idK+"'");
  160.                 }
  161.                 this.hsmOCSPConfigMapTypeToID.put(ocspConfig.getType(), idK);
  162.                
  163.                 // label (value è id del ocsp.properties)
  164.                 alreadyExists = false;
  165.                 for (String label : this.hsmOCSPConfigMapLabelToID.keySet()) {
  166.                     if(ocspConfig.getLabel().equalsIgnoreCase(label)) {
  167.                         alreadyExists = true;
  168.                     }
  169.                 }
  170.                 if(alreadyExists) {
  171.                     throw new UtilsException("Same ocsp label found for responder '"+this.hsmOCSPConfigMapLabelToID.get(ocspConfig.getLabel())+"' e '"+idK+"'");
  172.                 }
  173.                 this.hsmOCSPConfigMapLabelToID.put(ocspConfig.getLabel(), idK);
  174.                
  175.                 // id di ocsp.properties to config
  176.                 this.hsmOCSPConfigMapIDtoConfig.put(idK, ocspConfig);
  177.                            
  178.                 String msg = "OCSP config "+idK+" registrato (OCSP Type:"+ocspConfig.getType()+")";
  179.                 log.info(msg);
  180.                
  181.                 types.add(ocspConfig.getType());
  182.                 labels.add(ocspConfig.getLabel());
  183.             }
  184.            
  185.             // SortedMap by label
  186.             Map<String, String> m = new HashMap<>();
  187.             for (int i = 0; i < types.size(); i++) {
  188.                 String type = types.get(i);
  189.                 String label = labels.get(i);
  190.                 m.put(label, type);
  191.             }
  192.             Collections.sort(labels);
  193.             for (String l : labels) {
  194.                 this.hsmOCSPConfigSortedMapTypeLabel.add(m.get(l), l);  
  195.             }
  196.         }
  197.         else {
  198.             log.warn("La configurazione fornita per HSM non contiene alcun keystore");
  199.         }
  200.     }
  201.    
  202.     public OCSPConfig getOCSPConfig(String ocspConfigType) throws UtilsException {
  203.         if(!this.hsmOCSPConfigMapTypeToID.containsKey(ocspConfigType)) {
  204.             throw new UtilsException("OCSP config type '"+ocspConfigType+"' unknown");
  205.         }
  206.         String idK = this.hsmOCSPConfigMapTypeToID.get(ocspConfigType);
  207.         if(!this.hsmOCSPConfigMapIDtoConfig.containsKey(idK)) {
  208.             throw new UtilsException("OCSP config type '"+ocspConfigType+"' unknown ? (id:"+idK+")");
  209.         }
  210.         return this.hsmOCSPConfigMapIDtoConfig.get(idK);
  211.     }
  212.    

  213.     public List<String> getOCSPConfigTypes() {
  214.         List<String> l = new ArrayList<>();
  215.         if(!this.hsmOCSPConfigMapTypeToID.isEmpty()) {
  216.             for (String type : this.hsmOCSPConfigMapTypeToID.keySet()) {
  217.                 l.add(type);
  218.             }
  219.         }
  220.         return l;
  221.     }
  222.     public List<String> getOCSPConfigLabels() {
  223.         List<String> l = new ArrayList<>();
  224.         if(!this.hsmOCSPConfigMapLabelToID.isEmpty()) {
  225.             for (String label : this.hsmOCSPConfigMapLabelToID.keySet()) {
  226.                 l.add(label);
  227.             }
  228.         }
  229.         return l;
  230.     }
  231.     public SortedMap<String> getOCSPConfigTypesLabels() {
  232.         return this.hsmOCSPConfigSortedMapTypeLabel;
  233.     }
  234.    
  235.     public boolean existsOCSPConfig(String ocspConfigType) {
  236.         if(ocspConfigType==null) {
  237.             return false;
  238.         }
  239.         for (String type : this.hsmOCSPConfigMapTypeToID.keySet()) {
  240.             if(ocspConfigType.equalsIgnoreCase(type)) {
  241.                 return true;
  242.             }
  243.         }
  244.         return false;
  245.     }
  246. }