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 <keyHolderClass> init parameter. 41 * 42 * <P>Handles the following init parameters (will comment only the differences from {@link AbstractSign}):</P> 43 * <ul> 44 * <li><keyHolderClass>: 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><debug>.</li> 47 * <li><keyStoreFileName>.</li> 48 * <li><keyStorePassword>.</li> 49 * <li><keyAlias>.</li> 50 * <li><keyAliasPassword>.</li> 51 * <li><keyStoreType>.</li> 52 * <li><postmasterSigns>. The default is <CODE>true</CODE>.</li> 53 * <li><rebuildFrom>. The default is <CODE>true</CODE>.</li> 54 * <li><signerName>.</li> 55 * <li><explanationText>. 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><explanationText></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><postmasterSigns></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><rebuildFrom></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