1 /*
   2  * reserved comment block
   3  * DO NOT REMOVE OR ALTER!
   4  */
   5 /**
   6  * Licensed to the Apache Software Foundation (ASF) under one
   7  * or more contributor license agreements. See the NOTICE file
   8  * distributed with this work for additional information
   9  * regarding copyright ownership. The ASF licenses this file
  10  * to you under the Apache License, Version 2.0 (the
  11  * "License"); you may not use this file except in compliance
  12  * with the License. You may obtain a copy of the License at
  13  *
  14  * http://www.apache.org/licenses/LICENSE-2.0
  15  *
  16  * Unless required by applicable law or agreed to in writing,
  17  * software distributed under the License is distributed on an
  18  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  19  * KIND, either express or implied. See the License for the
  20  * specific language governing permissions and limitations
  21  * under the License.
  22  */
  23 package com.sun.org.apache.xml.internal.security;
  24 
  25 import java.io.InputStream;
  26 import java.security.AccessController;
  27 import java.security.PrivilegedAction;
  28 import java.util.ArrayList;
  29 import java.util.List;
  30 
  31 import javax.xml.XMLConstants;
  32 import javax.xml.parsers.DocumentBuilder;
  33 import javax.xml.parsers.DocumentBuilderFactory;
  34 
  35 import com.sun.org.apache.xml.internal.security.algorithms.JCEMapper;
  36 import com.sun.org.apache.xml.internal.security.algorithms.SignatureAlgorithm;
  37 import com.sun.org.apache.xml.internal.security.c14n.Canonicalizer;
  38 import com.sun.org.apache.xml.internal.security.keys.keyresolver.KeyResolver;
  39 import com.sun.org.apache.xml.internal.security.transforms.Transform;
  40 import com.sun.org.apache.xml.internal.security.utils.ElementProxy;
  41 import com.sun.org.apache.xml.internal.security.utils.I18n;
  42 import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
  43 import com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolver;
  44 import org.w3c.dom.Attr;
  45 import org.w3c.dom.Document;
  46 import org.w3c.dom.Element;
  47 import org.w3c.dom.Node;
  48 
  49 
  50 /**
  51  * This class does the configuration of the library. This includes creating
  52  * the mapping of Canonicalization and Transform algorithms. Initialization is
  53  * done by calling {@link Init#init} which should be done in any static block
  54  * of the files of this library. We ensure that this call is only executed once.
  55  */
  56 public class Init {
  57 
  58     /** The namespace for CONF file **/
  59     public static final String CONF_NS = "http://www.xmlsecurity.org/NS/#configuration";
  60 
  61     /** {@link org.apache.commons.logging} logging facility */
  62     private static java.util.logging.Logger log =
  63         java.util.logging.Logger.getLogger(Init.class.getName());
  64 
  65     /** Field alreadyInitialized */
  66     private static boolean alreadyInitialized = false;
  67 
  68     /**
  69      * Method isInitialized
  70      * @return true if the library is already initialized.
  71      */
  72     public static synchronized final boolean isInitialized() {
  73         return Init.alreadyInitialized;
  74     }
  75 
  76     /**
  77      * Method init
  78      *
  79      */
  80     public static synchronized void init() {
  81         if (alreadyInitialized) {
  82             return;
  83         }
  84 
  85         InputStream is =
  86             AccessController.doPrivileged(
  87                 new PrivilegedAction<InputStream>() {
  88                     public InputStream run() {
  89                         String cfile =
  90                             System.getProperty("com.sun.org.apache.xml.internal.security.resource.config");
  91                         if (cfile == null) {
  92                             return null;
  93                         }
  94                         return getClass().getResourceAsStream(cfile);
  95                     }
  96                 });
  97         if (is == null) {
  98             dynamicInit();
  99         } else {
 100             fileInit(is);
 101         }
 102 
 103         alreadyInitialized = true;
 104     }
 105 
 106     /**
 107      * Dynamically initialise the library by registering the default algorithms/implementations
 108      */
 109     private static void dynamicInit() {
 110         //
 111         // Load the Resource Bundle - the default is the English resource bundle.
 112         // To load another resource bundle, call I18n.init(...) before calling this
 113         // method.
 114         //
 115         I18n.init("en", "US");
 116 
 117         if (log.isLoggable(java.util.logging.Level.FINE)) {
 118             log.log(java.util.logging.Level.FINE, "Registering default algorithms");
 119         }
 120         try {
 121             //
 122             // Bind the default prefixes
 123             //
 124             ElementProxy.registerDefaultPrefixes();
 125 
 126             //
 127             // Set the default Transforms
 128             //
 129             Transform.registerDefaultAlgorithms();
 130 
 131             //
 132             // Set the default signature algorithms
 133             //
 134             SignatureAlgorithm.registerDefaultAlgorithms();
 135 
 136             //
 137             // Set the default JCE algorithms
 138             //
 139             JCEMapper.registerDefaultAlgorithms();
 140 
 141             //
 142             // Set the default c14n algorithms
 143             //
 144             Canonicalizer.registerDefaultAlgorithms();
 145 
 146             //
 147             // Register the default resolvers
 148             //
 149             ResourceResolver.registerDefaultResolvers();
 150 
 151             //
 152             // Register the default key resolvers
 153             //
 154             KeyResolver.registerDefaultResolvers();
 155         } catch (Exception ex) {
 156             log.log(java.util.logging.Level.SEVERE, ex.getMessage(), ex);
 157             ex.printStackTrace();
 158         }
 159     }
 160 
 161     /**
 162      * Initialise the library from a configuration file
 163      */
 164     private static void fileInit(InputStream is) {
 165         try {
 166             /* read library configuration file */
 167             DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 168             dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, Boolean.TRUE);
 169 
 170             dbf.setNamespaceAware(true);
 171             dbf.setValidating(false);
 172 
 173             DocumentBuilder db = dbf.newDocumentBuilder();
 174             Document doc = db.parse(is);
 175             Node config = doc.getFirstChild();
 176             for (; config != null; config = config.getNextSibling()) {
 177                 if ("Configuration".equals(config.getLocalName())) {
 178                     break;
 179                 }
 180             }
 181             if (config == null) {
 182                 log.log(java.util.logging.Level.SEVERE, "Error in reading configuration file - Configuration element not found");
 183                 return;
 184             }
 185             for (Node el = config.getFirstChild(); el != null; el = el.getNextSibling()) {
 186                 if (Node.ELEMENT_NODE != el.getNodeType()) {
 187                     continue;
 188                 }
 189                 String tag = el.getLocalName();
 190                 if (tag.equals("ResourceBundles")) {
 191                     Element resource = (Element)el;
 192                     /* configure internationalization */
 193                     Attr langAttr = resource.getAttributeNode("defaultLanguageCode");
 194                     Attr countryAttr = resource.getAttributeNode("defaultCountryCode");
 195                     String languageCode =
 196                         (langAttr == null) ? null : langAttr.getNodeValue();
 197                     String countryCode =
 198                         (countryAttr == null) ? null : countryAttr.getNodeValue();
 199                     I18n.init(languageCode, countryCode);
 200                 }
 201 
 202                 if (tag.equals("CanonicalizationMethods")) {
 203                     Element[] list =
 204                         XMLUtils.selectNodes(el.getFirstChild(), CONF_NS, "CanonicalizationMethod");
 205 
 206                     for (int i = 0; i < list.length; i++) {
 207                         String uri = list[i].getAttributeNS(null, "URI");
 208                         String javaClass =
 209                             list[i].getAttributeNS(null, "JAVACLASS");
 210                         try {
 211                             Canonicalizer.register(uri, javaClass);
 212                             if (log.isLoggable(java.util.logging.Level.FINE)) {
 213                                 log.log(java.util.logging.Level.FINE, "Canonicalizer.register(" + uri + ", " + javaClass + ")");
 214                             }
 215                         } catch (ClassNotFoundException e) {
 216                             Object exArgs[] = { uri, javaClass };
 217                             log.log(java.util.logging.Level.SEVERE, I18n.translate("algorithm.classDoesNotExist", exArgs));
 218                         }
 219                     }
 220                 }
 221 
 222                 if (tag.equals("TransformAlgorithms")) {
 223                     Element[] tranElem =
 224                         XMLUtils.selectNodes(el.getFirstChild(), CONF_NS, "TransformAlgorithm");
 225 
 226                     for (int i = 0; i < tranElem.length; i++) {
 227                         String uri = tranElem[i].getAttributeNS(null, "URI");
 228                         String javaClass =
 229                             tranElem[i].getAttributeNS(null, "JAVACLASS");
 230                         try {
 231                             Transform.register(uri, javaClass);
 232                             if (log.isLoggable(java.util.logging.Level.FINE)) {
 233                                 log.log(java.util.logging.Level.FINE, "Transform.register(" + uri + ", " + javaClass + ")");
 234                             }
 235                         } catch (ClassNotFoundException e) {
 236                             Object exArgs[] = { uri, javaClass };
 237 
 238                             log.log(java.util.logging.Level.SEVERE, I18n.translate("algorithm.classDoesNotExist", exArgs));
 239                         } catch (NoClassDefFoundError ex) {
 240                             log.log(java.util.logging.Level.WARNING, "Not able to found dependencies for algorithm, I'll keep working.");
 241                         }
 242                     }
 243                 }
 244 
 245                 if ("JCEAlgorithmMappings".equals(tag)) {
 246                     Node algorithmsNode = ((Element)el).getElementsByTagName("Algorithms").item(0);
 247                     if (algorithmsNode != null) {
 248                         Element[] algorithms =
 249                             XMLUtils.selectNodes(algorithmsNode.getFirstChild(), CONF_NS, "Algorithm");
 250                         for (int i = 0; i < algorithms.length; i++) {
 251                             Element element = algorithms[i];
 252                             String id = element.getAttribute("URI");
 253                             JCEMapper.register(id, new JCEMapper.Algorithm(element));
 254                         }
 255                     }
 256                 }
 257 
 258                 if (tag.equals("SignatureAlgorithms")) {
 259                     Element[] sigElems =
 260                         XMLUtils.selectNodes(el.getFirstChild(), CONF_NS, "SignatureAlgorithm");
 261 
 262                     for (int i = 0; i < sigElems.length; i++) {
 263                         String uri = sigElems[i].getAttributeNS(null, "URI");
 264                         String javaClass =
 265                             sigElems[i].getAttributeNS(null, "JAVACLASS");
 266 
 267                         /** $todo$ handle registering */
 268 
 269                         try {
 270                             SignatureAlgorithm.register(uri, javaClass);
 271                             if (log.isLoggable(java.util.logging.Level.FINE)) {
 272                                 log.log(java.util.logging.Level.FINE, "SignatureAlgorithm.register(" + uri + ", "
 273                                           + javaClass + ")");
 274                             }
 275                         } catch (ClassNotFoundException e) {
 276                             Object exArgs[] = { uri, javaClass };
 277 
 278                             log.log(java.util.logging.Level.SEVERE, I18n.translate("algorithm.classDoesNotExist", exArgs));
 279                         }
 280                     }
 281                 }
 282 
 283                 if (tag.equals("ResourceResolvers")) {
 284                     Element[]resolverElem =
 285                         XMLUtils.selectNodes(el.getFirstChild(), CONF_NS, "Resolver");
 286 
 287                     for (int i = 0; i < resolverElem.length; i++) {
 288                         String javaClass =
 289                             resolverElem[i].getAttributeNS(null, "JAVACLASS");
 290                         String description =
 291                             resolverElem[i].getAttributeNS(null, "DESCRIPTION");
 292 
 293                         if ((description != null) && (description.length() > 0)) {
 294                             if (log.isLoggable(java.util.logging.Level.FINE)) {
 295                                 log.log(java.util.logging.Level.FINE, "Register Resolver: " + javaClass + ": "
 296                                           + description);
 297                             }
 298                         } else {
 299                             if (log.isLoggable(java.util.logging.Level.FINE)) {
 300                                 log.log(java.util.logging.Level.FINE, "Register Resolver: " + javaClass
 301                                           + ": For unknown purposes");
 302                             }
 303                         }
 304                         try {
 305                             ResourceResolver.register(javaClass);
 306                         } catch (Throwable e) {
 307                             log.log(java.util.logging.Level.WARNING,
 308                                  "Cannot register:" + javaClass
 309                                  + " perhaps some needed jars are not installed",
 310                                  e
 311                              );
 312                         }
 313                     }
 314                 }
 315 
 316                 if (tag.equals("KeyResolver")){
 317                     Element[] resolverElem =
 318                         XMLUtils.selectNodes(el.getFirstChild(), CONF_NS, "Resolver");
 319                     List<String> classNames = new ArrayList<String>(resolverElem.length);
 320                     for (int i = 0; i < resolverElem.length; i++) {
 321                         String javaClass =
 322                             resolverElem[i].getAttributeNS(null, "JAVACLASS");
 323                         String description =
 324                             resolverElem[i].getAttributeNS(null, "DESCRIPTION");
 325 
 326                         if ((description != null) && (description.length() > 0)) {
 327                             if (log.isLoggable(java.util.logging.Level.FINE)) {
 328                                 log.log(java.util.logging.Level.FINE, "Register Resolver: " + javaClass + ": "
 329                                           + description);
 330                             }
 331                         } else {
 332                             if (log.isLoggable(java.util.logging.Level.FINE)) {
 333                                 log.log(java.util.logging.Level.FINE, "Register Resolver: " + javaClass
 334                                           + ": For unknown purposes");
 335                             }
 336                         }
 337                         classNames.add(javaClass);
 338                     }
 339                     KeyResolver.registerClassNames(classNames);
 340                 }
 341 
 342 
 343                 if (tag.equals("PrefixMappings")){
 344                     if (log.isLoggable(java.util.logging.Level.FINE)) {
 345                         log.log(java.util.logging.Level.FINE, "Now I try to bind prefixes:");
 346                     }
 347 
 348                     Element[] nl =
 349                         XMLUtils.selectNodes(el.getFirstChild(), CONF_NS, "PrefixMapping");
 350 
 351                     for (int i = 0; i < nl.length; i++) {
 352                         String namespace = nl[i].getAttributeNS(null, "namespace");
 353                         String prefix = nl[i].getAttributeNS(null, "prefix");
 354                         if (log.isLoggable(java.util.logging.Level.FINE)) {
 355                             log.log(java.util.logging.Level.FINE, "Now I try to bind " + prefix + " to " + namespace);
 356                         }
 357                         ElementProxy.setDefaultPrefix(namespace, prefix);
 358                     }
 359                 }
 360             }
 361         } catch (Exception e) {
 362             log.log(java.util.logging.Level.SEVERE, "Bad: ", e);
 363             e.printStackTrace();
 364         }
 365     }
 366 
 367 }
 368