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 package org.apache.james.transport.mailets.smime;
21
22 import org.apache.mailet.Mail;
23
24 import javax.mail.MessagingException;
25 import javax.mail.internet.MimeBodyPart;
26 import javax.mail.internet.MimeMessage;
27 import javax.mail.internet.MimeMultipart;
28
29 import java.io.IOException;
30
31 /***
32 * <p>Puts a <I>server-side</I> SMIME signature on a message.<br>
33 * It is a concrete subclass of {@link SMIMEAbstractSign}, with very few modifications to it.</p>
34 * <p>A text file with an explanation text is attached to the original message,
35 * and the resulting message with all its attachments is signed.
36 * The resulting appearence of the message is almost unchanged: only an extra attachment
37 * and the signature are added.</p>
38 *
39 * <P>Handles the following init parameters (will comment only the differences from {@link SMIMEAbstractSign}):</P>
40 * <ul>
41 * <li><debug>.</li>
42 * <li><keyStoreFileName>.</li>
43 * <li><keyStorePassword>.</li>
44 * <li><keyAlias>.</li>
45 * <li><keyAliasPassword>.</li>
46 * <li><keyStoreType>.</li>
47 * <li><postmasterSigns>. The default is <CODE>true</CODE>.</li>
48 * <li><rebuildFrom>. The default is <CODE>true</CODE>.</li>
49 * <li><signerName>.</li>
50 * <li><explanationText>. There is a default explanation string template in English,
51 * displaying also all the headers of the original message (see {@link #getExplanationText}).</li>
52 * </ul>
53 * @version CVS $Revision: 494012 $ $Date: 2007-01-08 10:23:58 +0000 (Mon, 08 Jan 2007) $
54 * @since 2.2.1
55 */
56 public class SMIMESign extends SMIMEAbstractSign {
57
58 /***
59 * Return a string describing this mailet.
60 *
61 * @return a string describing this mailet
62 */
63 public String getMailetInfo() {
64 return "SMIME Signature Mailet";
65 }
66
67 /***
68 *
69 */
70 protected String[] getAllowedInitParameters() {
71 String[] allowedArray = {
72 "debug",
73 "keyStoreFileName",
74 "keyStorePassword",
75 "keyStoreType",
76 "keyAlias",
77 "keyAliasPassword",
78 "signerName",
79 "postmasterSigns",
80 "rebuildFrom",
81 "explanationText"
82 };
83 return allowedArray;
84 }
85
86
87
88
89
90 /***
91 * If the <CODE><explanationText></CODE> init parameter is missing
92 * returns the following default explanation template string:
93 * <pre><code>
94 * The message this file is attached to has been signed on the server by
95 * "[signerName]" <[signerAddress]>
96 * to certify that the sender is known and truly has the following address (reverse-path):
97 * [reversePath]
98 * and that the original message has the following message headers:
99 *
100 * [headers]
101 *
102 * The signature envelopes this attachment too.
103 * Please check the signature integrity.
104 *
105 * "[signerName]" <[signerAddress]>
106 * </code></pre>
107 */
108 public String getExplanationText() {
109 String explanationText = super.getExplanationText();
110 if (explanationText == null) {
111 explanationText = "The message this file is attached to has been signed on the server by\r\n"
112 + "\t\"[signerName]\" <[signerAddress]>"
113 + "\r\nto certify that the sender is known and truly has the following address (reverse-path):\r\n"
114 + "\t[reversePath]"
115 + "\r\nand that the original message has the following message headers:\r\n"
116 + "\r\n[headers]"
117 + "\r\n\r\nThe signature envelopes this attachment too."
118 + "\r\nPlease check the signature integrity."
119 + "\r\n\r\n"
120 + "\t\"[signerName]\" <[signerAddress]>";
121 }
122
123 return explanationText;
124 }
125
126 /***
127 * If the <CODE><postmasterSigns></CODE> init parameter is missing sets it to <I>true</I>.
128 */
129 protected void initPostmasterSigns() {
130 setPostmasterSigns((getInitParameter("postmasterSigns") == null) ? true : new Boolean(getInitParameter("postmasterSigns")).booleanValue());
131 }
132
133 /***
134 * If the <CODE><rebuildFrom></CODE> init parameter is missing sets it to <I>true</I>.
135 */
136 protected void initRebuildFrom() throws MessagingException {
137 setRebuildFrom((getInitParameter("rebuildFrom") == null) ? true : new Boolean(getInitParameter("rebuildFrom")).booleanValue());
138 if (isDebug()) {
139 if (isRebuildFrom()) {
140 log("Will modify the \"From:\" header.");
141 } else {
142 log("Will leave the \"From:\" header unchanged.");
143 }
144 }
145 }
146
147
148
149
150
151 /***
152 * A text file with the massaged contents of {@link #getExplanationText}
153 * is attached to the original message.
154 */
155 protected MimeBodyPart getWrapperBodyPart(Mail mail) throws MessagingException, IOException {
156
157 String explanationText = getExplanationText();
158
159
160 if (explanationText == null) {
161 return null;
162 }
163
164 MimeMessage originalMessage = mail.getMessage();
165
166 MimeBodyPart messagePart = new MimeBodyPart();
167 MimeBodyPart signatureReason = new MimeBodyPart();
168
169 String contentType = originalMessage.getContentType();
170 Object content = originalMessage.getContent();
171
172 if (contentType != null && content != null) {
173 messagePart.setContent(content, contentType);
174 } else {
175 throw new MessagingException("Either the content type or the content is null");
176 }
177
178 String headers = getMessageHeaders(originalMessage);
179
180 signatureReason.setText(getReplacedExplanationText(getExplanationText(),
181 getSignerName(),
182 getKeyHolder().getSignerAddress(),
183 mail.getSender().toString(),
184 headers));
185
186 signatureReason.setFileName("SignatureExplanation.txt");
187
188 MimeMultipart wrapperMultiPart = new MimeMultipart();
189
190 wrapperMultiPart.addBodyPart(messagePart);
191 wrapperMultiPart.addBodyPart(signatureReason);
192
193 MimeBodyPart wrapperBodyPart = new MimeBodyPart();
194
195 wrapperBodyPart.setContent(wrapperMultiPart);
196
197 return wrapperBodyPart;
198 }
199
200 }
201