📄 smimeabstractsign.java
字号:
/**************************************************************** * Licensed to the Apache Software Foundation (ASF) under one * * or more contributor license agreements. See the NOTICE file * * distributed with this work for additional information * * regarding copyright ownership. The ASF licenses this file * * to you under the Apache License, Version 2.0 (the * * "License"); you may not use this file except in compliance * * with the License. You may obtain a copy of the License at * * * * http://www.apache.org/licenses/LICENSE-2.0 * * * * Unless required by applicable law or agreed to in writing, * * software distributed under the License is distributed on an * * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * * KIND, either express or implied. See the License for the * * specific language governing permissions and limitations * * under the License. * ****************************************************************/package org.apache.james.transport.mailets.smime;import org.apache.james.security.KeyHolder;import org.apache.james.security.SMIMEAttributeNames;import org.apache.mailet.GenericMailet;import org.apache.mailet.Mail;import org.apache.mailet.MailAddress;import org.apache.mailet.RFC2822Headers;import javax.mail.MessagingException;import javax.mail.Session;import javax.mail.internet.InternetAddress;import javax.mail.internet.MimeBodyPart;import javax.mail.internet.MimeMessage;import javax.mail.internet.MimeMultipart;import javax.mail.internet.ParseException;import java.io.IOException;import java.util.ArrayList;import java.util.Collection;import java.util.Enumeration;import java.util.HashSet;import java.util.Iterator;/** * <P>Abstract mailet providing common SMIME signature services.<BR> * It can be subclassed to make authoring signing mailets simple.<BR> * By extending it and overriding one or more of the following methods a new behaviour can * be quickly created without the author having to address any issue other than * the relevant one:</P> * <ul> * <li>{@link #initDebug}, {@link #setDebug} and {@link #isDebug} manage the debugging mode.</li> * <li>{@link #initExplanationText}, {@link #setExplanationText} and {@link #getExplanationText} manage the text of * an attachment that will be added to explain the meaning of this server-side signature.</li> * <li>{@link #initKeyHolder}, {@link #setKeyHolder} and {@link #getKeyHolder} manage the {@link KeyHolder} object that will * contain the keys and certificates and will do the crypto work.</li> * <li>{@link #initPostmasterSigns}, {@link #setPostmasterSigns} and {@link #isPostmasterSigns} * determines whether messages originated by the Postmaster will be signed or not.</li> * <li>{@link #initRebuildFrom}, {@link #setRebuildFrom} and {@link #isRebuildFrom} * determines whether the "From:" header will be rebuilt to neutralize the wrong behaviour of * some MUAs like Microsoft Outlook Express.</li> * <li>{@link #initSignerName}, {@link #setSignerName} and {@link #getSignerName} manage the name * of the signer to be shown in the explanation text.</li> * <li>{@link #isOkToSign} controls whether the mail can be signed or not.</li> * <li>The abstract method {@link #getWrapperBodyPart} returns the massaged {@link javax.mail.internet.MimeBodyPart} * that will be signed, or null if the message has to be signed "as is".</li> * </ul> * * <P>Handles the following init parameters:</P> * <ul> * <li><debug>: if <CODE>true</CODE> some useful information is logged. * The default is <CODE>false</CODE>.</li> * <li><keyStoreFileName>: the {@link java.security.KeyStore} full file name.</li> * <li><keyStorePassword>: the <CODE>KeyStore</CODE> password. * If given, it is used to check the integrity of the keystore data, * otherwise, if null, the integrity of the keystore is not checked.</li> * <li><keyAlias>: the alias name to use to search the Key using {@link java.security.KeyStore#getKey}. * The default is to look for the first and only alias in the keystore; * if zero or more than one is found a {@link java.security.KeyStoreException} is thrown.</li> * <li><keyAliasPassword>: the alias password. The default is to use the <CODE>KeyStore</CODE> password. * At least one of the passwords must be provided.</li> * <li><keyStoreType>: the type of the keystore. The default will use {@link java.security.KeyStore#getDefaultType}.</li> * <li><postmasterSigns>: if <CODE>true</CODE> the message will be signed even if the sender is the Postmaster. * The default is <CODE>false</CODE>.</li></li> * <li><rebuildFrom>: If <CODE>true</CODE> will modify the "From:" header. * For more info see {@link #isRebuildFrom}. * The default is <CODE>false</CODE>.</li> * <li><signerName>: the name of the signer to be shown in the explanation text. * The default is to use the "CN=" property of the signing certificate.</li> * <li><explanationText>: the text of an explanation of the meaning of this server-side signature. * May contain the following substitution patterns (see also {@link #getReplacedExplanationText}): * <CODE>[signerName]</CODE>, <CODE>[signerAddress]</CODE>, <CODE>[reversePath]</CODE>, <CODE>[headers]</CODE>. * It should be included in the signature. * The actual presentation of the text depends on the specific concrete mailet subclass: * see for example {@link SMIMESign}. * The default is to not have any explanation text.</li> * </ul> * @version CVS $Revision: 494012 $ $Date: 2007-01-08 11:23:58 +0100 (Mo, 08 Jan 2007) $ * @since 2.2.1 */public abstract class SMIMEAbstractSign extends GenericMailet { private static final String HEADERS_PATTERN = "[headers]"; private static final String SIGNER_NAME_PATTERN = "[signerName]"; private static final String SIGNER_ADDRESS_PATTERN = "[signerAddress]"; private static final String REVERSE_PATH_PATTERN = "[reversePath]"; /** * Holds value of property debug. */ private boolean debug; /** * Holds value of property explanationText. */ private String explanationText; /** * Holds value of property keyHolder. */ private KeyHolder keyHolder; /** * Holds value of property postmasterSigns. */ private boolean postmasterSigns; /** * Holds value of property rebuildFrom. */ private boolean rebuildFrom; /** * Holds value of property signerName. */ private String signerName; /** * Gets the expected init parameters. * @return An array containing the parameter names allowed for this mailet. */ protected abstract String[] getAllowedInitParameters(); /* ******************************************************************** */ /* ****************** Begin of setters and getters ******************** */ /* ******************************************************************** */ /** * Initializer for property debug. */ protected void initDebug() { setDebug((getInitParameter("debug") == null) ? false : new Boolean(getInitParameter("debug")).booleanValue()); } /** * Getter for property debug. * @return Value of property debug. */ public boolean isDebug() { return this.debug; } /** * Setter for property debug. * @param debug New value of property debug. */ public void setDebug(boolean debug) { this.debug = debug; } /** * Initializer for property explanationText. */ protected void initExplanationText() { setExplanationText(getInitParameter("explanationText")); if (isDebug()) { log("Explanation text:\r\n" + getExplanationText()); } } /** * Getter for property explanationText. * Text to be used in the SignatureExplanation.txt file. * @return Value of property explanationText. */ public String getExplanationText() { return this.explanationText; } /** * Setter for property explanationText. * @param explanationText New value of property explanationText. */ public void setExplanationText(String explanationText) { this.explanationText = explanationText; } /** * Initializer for property keyHolder. */ protected void initKeyHolder() throws Exception { String keyStoreFileName = getInitParameter("keyStoreFileName"); if (keyStoreFileName == null) { throw new MessagingException("<keyStoreFileName> parameter missing."); } String keyStorePassword = getInitParameter("keyStorePassword"); if (keyStorePassword == null) { throw new MessagingException("<keyStorePassword> parameter missing."); } String keyAliasPassword = getInitParameter("keyAliasPassword"); if (keyAliasPassword == null) { keyAliasPassword = keyStorePassword; if (isDebug()) { log("<keyAliasPassword> parameter not specified: will default to the <keyStorePassword> parameter."); } } String keyStoreType = getInitParameter("keyStoreType"); if (keyStoreType == null) { if (isDebug()) { log("<type> parameter not specified: will default to \"" + KeyHolder.getDefaultType() + "\"."); } } String keyAlias = getInitParameter("keyAlias"); if (keyAlias == null) { if (isDebug()) { log("<keyAlias> parameter not specified: will look for the first one in the keystore."); } } if (isDebug()) { StringBuffer logBuffer = new StringBuffer(1024) .append("KeyStore related parameters:") .append(" keyStoreFileName=").append(keyStoreFileName) .append(", keyStoreType=").append(keyStoreType) .append(", keyAlias=").append(keyAlias) .append(" "); log(logBuffer.toString()); } // Certificate preparation setKeyHolder(new KeyHolder(keyStoreFileName, keyStorePassword, keyAlias, keyAliasPassword, keyStoreType)); if (isDebug()) { log("Subject Distinguished Name: " + getKeyHolder().getSignerDistinguishedName()); } if (getKeyHolder().getSignerAddress() == null) { throw new MessagingException("Signer address missing in the certificate."); } } /** * Getter for property keyHolder. * It is <CODE>protected</CODE> instead of <CODE>public</CODE> for security reasons. * @return Value of property keyHolder. */ protected KeyHolder getKeyHolder() { return this.keyHolder; } /** * Setter for property keyHolder. * It is <CODE>protected</CODE> instead of <CODE>public</CODE> for security reasons. * @param keyHolder New value of property keyHolder. */ protected void setKeyHolder(KeyHolder keyHolder) { this.keyHolder = keyHolder; } /** * Initializer for property postmasterSigns. */ protected void initPostmasterSigns() { setPostmasterSigns((getInitParameter("postmasterSigns") == null) ? false : new Boolean(getInitParameter("postmasterSigns")).booleanValue()); } /** * Getter for property postmasterSigns. * If true will sign messages signed by the postmaster. * @return Value of property postmasterSigns. */ public boolean isPostmasterSigns() { return this.postmasterSigns; } /** * Setter for property postmasterSigns. * @param postmasterSigns New value of property postmasterSigns. */ public void setPostmasterSigns(boolean postmasterSigns) { this.postmasterSigns = postmasterSigns; } /** * Initializer for property rebuildFrom. */ protected void initRebuildFrom() throws MessagingException { setRebuildFrom((getInitParameter("rebuildFrom") == null) ? false : new Boolean(getInitParameter("rebuildFrom")).booleanValue()); if (isDebug()) { if (isRebuildFrom()) { log("Will modify the \"From:\" header."); } else { log("Will leave the \"From:\" header unchanged."); } } } /** * Getter for property rebuildFrom. * If true will modify the "From:" header. * <P>The modification is as follows: * assuming that the signer mail address in the signer certificate is <I>trusted-server@xxx.com></I> * and that <I>From: "John Smith" <john.smith@xxx.com></I> * we will get <I>From: "John Smith" <john.smith@xxx.com>" <trusted-server@xxx.com></I>.</P> * <P>If the "ReplyTo:" header is missing or empty it will be set to the original "From:" header.</P> * <P>Such modification is necessary to achieve a correct behaviour * with some mail clients (e.g. Microsoft Outlook Express).</P> * @return Value of property rebuildFrom. */ public boolean isRebuildFrom() { return this.rebuildFrom; } /** * Setter for property rebuildFrom. * @param rebuildFrom New value of property rebuildFrom. */ public void setRebuildFrom(boolean rebuildFrom) { this.rebuildFrom = rebuildFrom; } /** * Initializer for property signerName. */ protected void initSignerName() { setSignerName(getInitParameter("signerName")); if (getSignerName() == null) { if (getKeyHolder() == null) { throw new RuntimeException("initKeyHolder() must be invoked before initSignerName()"); } setSignerName(getKeyHolder().getSignerCN()); if (isDebug()) { log("<signerName> parameter not specified: will use the certificate signer \"CN=\" attribute."); } } } /** * Getter for property signerName. * @return Value of property signerName. */ public String getSignerName() {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -