001    /*
002     * CDDL HEADER START
003     *
004     * The contents of this file are subject to the terms of the
005     * Common Development and Distribution License, Version 1.0 only
006     * (the "License").  You may not use this file except in compliance
007     * with the License.
008     *
009     * You can obtain a copy of the license at
010     * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011     * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012     * See the License for the specific language governing permissions
013     * and limitations under the License.
014     *
015     * When distributing Covered Code, include this CDDL HEADER in each
016     * file and include the License file at
017     * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
018     * add the following below this CDDL HEADER, with the fields enclosed
019     * by brackets "[]" replaced with your own identifying information:
020     *      Portions Copyright [yyyy] [name of copyright owner]
021     *
022     * CDDL HEADER END
023     *
024     *
025     *      Copyright 2006-2008 Sun Microsystems, Inc.
026     */
027    package org.opends.server.loggers;
028    
029    //import java.io.BufferedInputStream;
030    import java.io.File;
031    //import java.io.FileInputStream;
032    //import java.io.RandomAccessFile;
033    //import java.security.MessageDigest;
034    //import java.security.PrivateKey;
035    //import java.security.PublicKey;
036    //import java.security.Signature;
037    //import java.security.cert.X509Certificate;
038    //import javax.net.ssl.KeyManager;
039    //import javax.net.ssl.X509KeyManager;
040    
041    //import org.opends.server.core.DirectoryServer;
042    
043    /**
044     * This class implements a post rotation action that signs
045     * the file.
046     */
047    public class SignatureAction implements PostRotationAction
048    {
049    
050      private static final String delimiter = "---------";
051      private File originalFile;
052      private String signatureAlgorithm = "SHA1withRSA";
053      private String digestAlgorithm = "SHA";
054      private String alias = null;
055    
056      /**
057       * Create the signature action based on the log file name,
058       * and the certificate alias to use for signing.
059       *
060       * @param origFile    The source file name to sign.
061       * @param alias       The certificate alias to use for signing.
062       */
063      public SignatureAction(String origFile, String alias)
064      {
065        this.originalFile = new File(origFile);
066        this.alias = alias;
067      }
068    
069      /**
070       * Create the signature action based on the log file name,
071       * the signature algorithm, the digest algorithm, and the certificate alias
072       * to use for signing.
073       *
074       * @param origFile    The source file name to sign.
075       * @param sigAlg      The signature algorithm to use.
076       * @param digestAlg   The MD5 digest algorithm to use.
077       * @param alias       The certificate alias to use for signing.
078       */
079      public SignatureAction(String origFile, String sigAlg, String digestAlg,
080                             String alias)
081      {
082        this.originalFile = new File(origFile);
083        this.signatureAlgorithm = sigAlg;
084        this.digestAlgorithm = digestAlg;
085        this.alias = alias;
086      }
087    
088      /**
089       * The signature action that is executed. Returns true if the
090       * action succeeded and false otherwise.
091       *
092       * @return  <CODE>true</CODE> if the signature was generated successfully, or
093       *          <CODE>false</CODE> if not.
094       */
095      public boolean execute()
096      {
097        // FIXME -- It is currently not possible to sign on rotate because of the
098        // way that they key manager providers are defined.  However, this function
099        // wasn't implemented in an ideal fashion anyway, so the signing capability
100        // should remain disabled until the rotation action mechanism is rewritten.
101        // The original code has been preserved here for reference purposes.
102        return false;
103    //
104    //    FileInputStream fis = null;
105    //    boolean inputStreamOpen = false;
106    //    try
107    //    {
108    //      KeyManager[] keyMgrs =
109    //           DirectoryServer.getKeyManagerProvider().getKeyManagers();
110    //      if(keyMgrs.length == 0)
111    //      {
112    //        // No keys available.
113    //        // FIXME - Log in error log.
114    //        System.err.println("No private key available to sign with.");
115    //        return false;
116    //      }
117    //      X509KeyManager mgr = (X509KeyManager) keyMgrs[0];
118    //      PrivateKey priv = mgr.getPrivateKey(alias);
119    //
120    //      Signature sig = Signature.getInstance(signatureAlgorithm);
121    //      sig.initSign(priv);
122    //
123    //      MessageDigest md = MessageDigest.getInstance(digestAlgorithm);
124    //      md.reset();
125    //
126    //      fis = new FileInputStream(originalFile);
127    //      inputStreamOpen = true;
128    //      BufferedInputStream bufin = new BufferedInputStream(fis);
129    //      byte[] buffer = new byte[1024];
130    //      int len;
131    //      while (bufin.available() != 0)
132    //      {
133    //        len = bufin.read(buffer);
134    //        md.update(buffer, 0, len);
135    //      }
136    //      bufin.close();
137    //
138    //      // Create a hash of the log file contents.
139    //      byte[] hash = md.digest();
140    //      // printBytes(hash);
141    //      sig.update(hash);
142    //
143    //      // Sign the hash.
144    //      byte[] realSig = sig.sign();
145    //      // printBytes(realSig);
146    //
147    //      // Append the signature to the end of the file.
148    //      RandomAccessFile raf = new RandomAccessFile(originalFile, "rw");
149    //      raf.seek(raf.length());
150    //      raf.write(delimiter.getBytes());
151    //      raf.write("\n".getBytes());
152    //      raf.write(realSig);
153    //
154    //      return true;
155    //    } catch(Exception ioe)
156    //    {
157    //      assert debugException(CLASS_NAME, "execute", ioe);
158    //      if(inputStreamOpen)
159    //      {
160    //        try
161    //        {
162    //          fis.close();
163    //        } catch(Exception fe)
164    //        {
165    //                assert debugException(CLASS_NAME, "execute", fe);
166    //          // Cannot do much. Ignore.
167    //        }
168    //      }
169    //      return false;
170    //    }
171      }
172    
173    
174      /**
175       * Verify the signature int the log file. Returns true if the
176       * the signature is valid and false otherwise.
177       *
178       * @return  <CODE>true</CODE> if the signature is valid, or <CODE>false</CODE>
179       *          if not.
180       */
181      public boolean verify()
182      {
183        // FIXME -- It is currently not possible to sign on rotate because of the
184        // way that they key manager providers are defined.  However, this function
185        // wasn't implemented in an ideal fashion anyway, so the signing capability
186        // should remain disabled until the rotation action mechanism is rewritten.
187        // The original code has been preserved here for reference purposes.
188        return false;
189    //    RandomAccessFile inFile = null;
190    //    boolean inputStreamOpen = false;
191    //    try
192    //    {
193    //      KeyManager[] keyMgrs =
194    //           DirectoryServer.getKeyManagerProvider().getKeyManagers();
195    //
196    //      if(keyMgrs.length == 0)
197    //      {
198    //        // No keys available.
199    //        // FIXME - Log in error log.
200    //        System.err.println("No public key available to verify signature.");
201    //        return false;
202    //      }
203    //
204    //      X509KeyManager mgr = (X509KeyManager) keyMgrs[0];
205    //      X509Certificate[] certChain = mgr.getCertificateChain(alias);
206    //
207    //      if(certChain == null || certChain.length == 0)
208    //      {
209    //        System.err.println("Cannot find the public key for the signature.");
210    //        return false;
211    //      }
212    //
213    //      PublicKey pubKey = certChain[0].getPublicKey();
214    //
215    //      Signature sig = Signature.getInstance(signatureAlgorithm);
216    //      sig.initVerify(pubKey);
217    //
218    //      MessageDigest md = MessageDigest.getInstance(digestAlgorithm);
219    //      md.reset();
220    //
221    //      inFile = new RandomAccessFile(originalFile, "r");
222    //      inputStreamOpen = true;
223    //      String line = null;
224    //      while ((line = inFile.readLine()) != null)
225    //      {
226    //        if(line.equals(delimiter))
227    //        {
228    //          break;
229    //        }
230    //        // int len = line.length();
231    //        // md.update(line.getBytes(), 0, len);
232    //        byte[] b = (line + "\n").getBytes();
233    //        md.update(b);
234    //      }
235    //
236    //      // Read signature
237    //      byte[] sigToVerify = new byte[128];
238    //      int val = inFile.read(sigToVerify, 0, 128);
239    //      // printBytes(sigToVerify);
240    //
241    //      // Create a hash of the log file contents.
242    //      byte[] hash = md.digest();
243    //      // printBytes(hash);
244    //      sig.update(hash);
245    //
246    //
247    //      // Verify the hash.
248    //      boolean verifies = sig.verify(sigToVerify);
249    //
250    //      return verifies;
251    //    } catch(Exception ioe)
252    //    {
253    //      assert debugException(CLASS_NAME, "execute", ioe);
254    //      if(inputStreamOpen)
255    //      {
256    //        try
257    //        {
258    //          inFile.close();
259    //        } catch(Exception fe)
260    //        {
261    //                assert debugException(CLASS_NAME, "execute", fe);
262    //          // Cannot do much. Ignore.
263    //        }
264    //      }
265    //      return false;
266    //    }
267      }
268    
269    
270    
271      /**
272       * Prints a representation of the contents of the provided byte array to
273       * standard output.
274       *
275       * @param  bArray  The array containing the data to be printed.
276       */
277      private void printBytes(byte[] bArray)
278      {
279        for(int i = 0; i < bArray.length; i++)
280        {
281          System.out.print(Integer.toHexString((int)bArray[i]));
282        }
283        System.out.println("");
284      }
285    
286    
287    }
288