View Javadoc

1   /****************************************************************
2    * Licensed to the Apache Software Foundation (ASF) under one   *
3    * or more contributor license agreements.  See the NOTICE file *
4    * distributed with this work for additional information        *
5    * regarding copyright ownership.  The ASF licenses this file   *
6    * to you under the Apache License, Version 2.0 (the            *
7    * "License"); you may not use this file except in compliance   *
8    * with the License.  You may obtain a copy of the License at   *
9    *                                                              *
10   *   http://www.apache.org/licenses/LICENSE-2.0                 *
11   *                                                              *
12   * Unless required by applicable law or agreed to in writing,   *
13   * software distributed under the License is distributed on an  *
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
15   * KIND, either express or implied.  See the License for the    *
16   * specific language governing permissions and limitations      *
17   * under the License.                                           *
18   ****************************************************************/
19  
20  
21  
22  package org.apache.james.mailet.crypto.mailet;
23  
24  import org.apache.mailet.Mail;
25  
26  import javax.mail.MessagingException;
27  import javax.mail.internet.MimeBodyPart;
28  import javax.mail.internet.MimeMessage;
29  import javax.mail.internet.MimeMultipart;
30  
31  import java.io.IOException;
32  
33  /**
34   * <p>Puts a <I>server-side</I> signature on a message.
35   * It is a concrete subclass of {@link AbstractSign}, with very few modifications to it.</p>
36   * <p>A text file with an explanation text is attached to the original message,
37   * and the resulting message with all its attachments is signed.
38   * The resulting appearence of the message is almost unchanged: only an extra attachment
39   * and the signature are added.</p>
40   *<p>The kind of signuture depends on the value of the &lt;keyHolderClass&gt; init parameter.
41   *
42   *  <P>Handles the following init parameters (will comment only the differences from {@link AbstractSign}):</P>
43   * <ul>
44   * <li>&lt;keyHolderClass&gt;: Sets the class of the KeyHolder object that will handle the cryptography functions,
45   * for example org.apache.james.security.SMIMEKeyHolder for SMIME.</li>
46   * <li>&lt;debug&gt;.</li>
47   * <li>&lt;keyStoreFileName&gt;.</li>
48   * <li>&lt;keyStorePassword&gt;.</li>
49   * <li>&lt;keyAlias&gt;.</li>
50   * <li>&lt;keyAliasPassword&gt;.</li>
51   * <li>&lt;keyStoreType&gt;.</li>
52   * <li>&lt;postmasterSigns&gt;. The default is <CODE>true</CODE>.</li>
53   * <li>&lt;rebuildFrom&gt;. The default is <CODE>true</CODE>.</li>
54   * <li>&lt;signerName&gt;.</li>
55   * <li>&lt;explanationText&gt;. There is a default explanation string template in English,
56   * displaying also all the headers of the original message (see {@link #getExplanationText}).</li>
57   * </ul>
58   * @version CVS $Revision: 744745 $ $Date: 2009-02-15 20:30:17 +0000 (Sun, 15 Feb 2009) $
59   * @since 2.2.1
60   */
61  public class Sign extends AbstractSign {
62      
63      /**
64       * Return a string describing this mailet.
65       *
66       * @return a string describing this mailet
67       */
68      public String getMailetInfo() {
69          return "Signature Mailet";
70      }
71      
72      /**
73       *
74       */
75      protected  String[] getAllowedInitParameters() {
76          String[] allowedArray = {
77              "keyHolderClass",
78              "debug",
79              "keyStoreFileName",
80              "keyStorePassword",
81              "keyStoreType",
82              "keyAlias",
83              "keyAliasPassword",
84              "signerName",
85              "postmasterSigns",
86              "rebuildFrom",
87              "explanationText"
88          };
89          return allowedArray;
90      }
91      
92       /* ******************************************************************** */
93      /* ****************** Begin of setters and getters ******************** */
94      /* ******************************************************************** */    
95      
96      /**
97       * Gets text offering an explanation.
98       * If the <CODE>&lt;explanationText&gt;</CODE> init parameter is missing
99       * returns the following default explanation template string:
100      * <pre><code>
101      * The message this file is attached to has been signed on the server by
102      *     "[signerName]" <[signerAddress]>
103      * to certify that the sender is known and truly has the following address (reverse-path):
104      *     [reversePath]
105      * and that the original message has the following message headers:
106      *
107      * [headers]
108      *
109      * The signature envelopes this attachment too.
110      * Please check the signature integrity.
111      *
112      *     "[signerName]" <[signerAddress]>
113      * </code></pre>
114      */
115     public String getExplanationText() {
116         String explanationText = super.getExplanationText();
117         if (explanationText == null) {
118             explanationText = "The message this file is attached to has been signed on the server by\r\n"
119             + "\t\"[signerName]\" <[signerAddress]>"
120             + "\r\nto certify that the sender is known and truly has the following address (reverse-path):\r\n"
121             + "\t[reversePath]"
122             + "\r\nand that the original message has the following message headers:\r\n"
123             + "\r\n[headers]"
124             + "\r\n\r\nThe signature envelopes this attachment too."
125             + "\r\nPlease check the signature integrity."
126             + "\r\n\r\n"
127             + "\t\"[signerName]\" <[signerAddress]>";
128         }
129         
130         return explanationText;
131     }
132     
133     /**
134      * If the <CODE>&lt;postmasterSigns&gt;</CODE> init parameter is missing sets it to <I>true</I>.
135      */
136     protected void initPostmasterSigns() {
137         setPostmasterSigns((getInitParameter("postmasterSigns") == null) ? true : new Boolean(getInitParameter("postmasterSigns")).booleanValue());
138     }
139     
140     /**
141      * If the <CODE>&lt;rebuildFrom&gt;</CODE> init parameter is missing sets it to <I>true</I>.
142      */
143     protected void initRebuildFrom() throws MessagingException {
144         setRebuildFrom((getInitParameter("rebuildFrom") == null) ? true : new Boolean(getInitParameter("rebuildFrom")).booleanValue());
145         if (isDebug()) {
146             if (isRebuildFrom()) {
147                 log("Will modify the \"From:\" header.");
148             } else {
149                 log("Will leave the \"From:\" header unchanged.");
150             }
151         }
152     }
153     
154     /* ******************************************************************** */
155     /* ****************** End of setters and getters ********************** */
156     /* ******************************************************************** */
157     
158     /**
159      * A text file with the massaged contents of {@link #getExplanationText}
160      * is attached to the original message.
161      */    
162     protected MimeBodyPart getWrapperBodyPart(Mail mail) throws MessagingException, IOException {
163         
164         String explanationText = getExplanationText();
165         
166         // if there is no explanation text there should be no wrapping
167         if (explanationText == null) {
168             return null;
169         }
170 
171             MimeMessage originalMessage = mail.getMessage();
172 
173             MimeBodyPart messagePart = new MimeBodyPart();
174             MimeBodyPart signatureReason = new MimeBodyPart();
175             
176             String contentType = originalMessage.getContentType();
177             Object content = originalMessage.getContent();
178             
179             if (contentType != null && content != null) {
180             messagePart.setContent(content, contentType);
181             } else {
182                 throw new MessagingException("Either the content type or the content is null");
183             }
184             
185             String headers = getMessageHeaders(originalMessage);
186             
187             signatureReason.setText(getReplacedExplanationText(getExplanationText(),
188                                                                getSignerName(),
189                                                                getKeyHolder().getSignerAddress(),
190                                                                mail.getSender().toString(),
191                                                                headers));
192             
193             signatureReason.setFileName("SignatureExplanation.txt");
194             
195             MimeMultipart wrapperMultiPart = new MimeMultipart();
196             
197             wrapperMultiPart.addBodyPart(messagePart);
198             wrapperMultiPart.addBodyPart(signatureReason);
199             
200             MimeBodyPart wrapperBodyPart = new MimeBodyPart();
201             
202             wrapperBodyPart.setContent(wrapperMultiPart);
203             
204             return wrapperBodyPart;
205     }
206         
207 }
208