📄 smimeabstractsign.java
字号:
return this.signerName; } /** * Setter for property signerName. * @param signerName New value of property signerName. */ public void setSignerName(String signerName) { this.signerName = signerName; } /* ******************************************************************** */ /* ****************** End of setters and getters ********************** */ /* ******************************************************************** */ /** * Mailet initialization routine. */ public void init() throws MessagingException { // check that all init parameters have been declared in allowedInitParameters checkInitParameters(getAllowedInitParameters()); try { initDebug(); if (isDebug()) { log("Initializing"); } initKeyHolder(); initSignerName(); initPostmasterSigns(); initRebuildFrom(); initExplanationText(); } catch (MessagingException me) { throw me; } catch (Exception e) { log("Exception thrown", e); throw new MessagingException("Exception thrown", e); } finally { if (isDebug()) { StringBuffer logBuffer = new StringBuffer(1024) .append("Other parameters:") .append(", signerName=").append(getSignerName()) .append(", postmasterSigns=").append(postmasterSigns) .append(", rebuildFrom=").append(rebuildFrom) .append(" "); log(logBuffer.toString()); } } } /** * Service does the hard work, and signs * * @param mail the mail to sign * @throws MessagingException if a problem arises signing the mail */ public void service(Mail mail) throws MessagingException { try { if (!isOkToSign(mail)) { return; } MimeBodyPart wrapperBodyPart = getWrapperBodyPart(mail); MimeMessage originalMessage = mail.getMessage(); // do it MimeMultipart signedMimeMultipart; if (wrapperBodyPart != null) { signedMimeMultipart = getKeyHolder().generate(wrapperBodyPart); } else { signedMimeMultipart = getKeyHolder().generate(originalMessage); } MimeMessage newMessage = new MimeMessage(Session.getDefaultInstance(System.getProperties(), null)); Enumeration headerEnum = originalMessage.getAllHeaderLines(); while (headerEnum.hasMoreElements()) { newMessage.addHeaderLine((String) headerEnum.nextElement()); } newMessage.setSender(new InternetAddress(getKeyHolder().getSignerAddress(), getSignerName())); if (isRebuildFrom()) { // builds a new "mixed" "From:" header InternetAddress modifiedFromIA = new InternetAddress(getKeyHolder().getSignerAddress(), mail.getSender().toString()); newMessage.setFrom(modifiedFromIA); // if the original "ReplyTo:" header is missing sets it to the original "From:" header newMessage.setReplyTo(originalMessage.getReplyTo()); } newMessage.setContent(signedMimeMultipart, signedMimeMultipart.getContentType()); String messageId = originalMessage.getMessageID(); newMessage.saveChanges(); if (messageId != null) { newMessage.setHeader(RFC2822Headers.MESSAGE_ID, messageId); } mail.setMessage(newMessage); // marks this mail as server-signed mail.setAttribute(SMIMEAttributeNames.SMIME_SIGNING_MAILET, this.getClass().getName()); // it is valid for us by definition (signed here by us) mail.setAttribute(SMIMEAttributeNames.SMIME_SIGNATURE_VALIDITY, "valid"); // saves the trusted server signer address // warning: should be same as the mail address in the certificate, but it is not guaranteed mail.setAttribute(SMIMEAttributeNames.SMIME_SIGNER_ADDRESS, getKeyHolder().getSignerAddress()); if (isDebug()) { log("Message signed, reverse-path: " + mail.getSender() + ", Id: " + messageId); } } catch (MessagingException me) { log("MessagingException found - could not sign!", me); throw me; } catch (Exception e) { log("Exception found", e); throw new MessagingException("Exception thrown - could not sign!", e); } } /** * <P>Checks if the mail can be signed.</P> * <P>Rules:</P> * <OL> * <LI>The reverse-path != null (it is not a bounce).</LI> * <LI>The sender user must have been SMTP authenticated.</LI> * <LI>Either:</LI> * <UL> * <LI>The reverse-path is the postmaster address and {@link #isPostmasterSigns} returns <I>true</I></LI> * <LI>or the reverse-path == the authenticated user * and there is at least one "From:" address == reverse-path.</LI>. * </UL> * <LI>The message has not already been signed (mimeType != <I>multipart/signed</I> * and != <I>application/pkcs7-mime</I>).</LI> * </OL> * @param mail The mail object to check. * @return True if can be signed. */ protected boolean isOkToSign(Mail mail) throws MessagingException { MailAddress reversePath = mail.getSender(); // Is it a bounce? if (reversePath == null) { return false; } String authUser = (String) mail.getAttribute("org.apache.james.SMTPAuthUser"); // was the sender user SMTP authorized? if (authUser == null) { return false; } // The sender is the postmaster? if (getMailetContext().getPostmaster().equals(reversePath)) { // should not sign postmaster sent messages? if (!isPostmasterSigns()) { return false; } } else { // is the reverse-path user different from the SMTP authorized user? if (!reversePath.getUser().equals(authUser)) { return false; } // is there no "From:" address same as the reverse-path? if (!fromAddressSameAsReverse(mail)) { return false; } } // if already signed return false MimeMessage mimeMessage = mail.getMessage(); if (mimeMessage.isMimeType("multipart/signed") || mimeMessage.isMimeType("application/pkcs7-mime")) { return false; } return true; } /** * Creates the {@link javax.mail.internet.MimeBodyPart} that will be signed. * For example, may attach a text file explaining the meaning of the signature, * or an XML file containing information that can be checked by other MTAs. * @param mail The mail to massage. * @return The massaged MimeBodyPart to sign, or null to have the whole message signed "as is". */ protected abstract MimeBodyPart getWrapperBodyPart(Mail mail) throws MessagingException, IOException; /** * Checks if there are unallowed init parameters specified in the configuration file * against the String[] allowedInitParameters. */ private void checkInitParameters(String[] allowedArray) throws MessagingException { // if null then no check is requested if (allowedArray == null) { return; } Collection allowed = new HashSet(); Collection bad = new ArrayList(); for (int i = 0; i < allowedArray.length; i++) { allowed.add(allowedArray[i]); } Iterator iterator = getInitParameterNames(); while (iterator.hasNext()) { String parameter = (String) iterator.next(); if (!allowed.contains(parameter)) { bad.add(parameter); } } if (bad.size() > 0) { throw new MessagingException("Unexpected init parameters found: " + arrayToString(bad.toArray())); } } /** * Utility method for obtaining a string representation of an array of Objects. */ private final String arrayToString(Object[] array) { if (array == null) { return "null"; } StringBuffer sb = new StringBuffer(1024); sb.append("["); for (int i = 0; i < array.length; i++) { if (i > 0) { sb.append(","); } sb.append(array[i]); } sb.append("]"); return sb.toString(); } /** * Utility method that checks if there is at least one address in the "From:" header * same as the <i>reverse-path</i>. * @param mail The mail to check. * @return True if an address is found, false otherwise. */ protected final boolean fromAddressSameAsReverse(Mail mail) { MailAddress reversePath = mail.getSender(); if (reversePath == null) { return false; } try { InternetAddress[] fromArray = (InternetAddress[]) mail.getMessage().getFrom(); if (fromArray != null) { for (int i = 0; i < fromArray.length; i++) { MailAddress mailAddress = null; try { mailAddress = new MailAddress(fromArray[i]); } catch (ParseException pe) { log("Unable to parse a \"FROM\" header address: " + fromArray[i].toString() + "; ignoring."); continue; } if (mailAddress.equals(reversePath)) { return true; } } } } catch (MessagingException me) { log("Unable to parse the \"FROM\" header; ignoring."); } return false; } /** * Utility method for obtaining a string representation of the Message's headers * @param message The message to extract the headers from. * @return The string containing the headers. */ protected final String getMessageHeaders(MimeMessage message) throws MessagingException { Enumeration heads = message.getAllHeaderLines(); StringBuffer headBuffer = new StringBuffer(1024); while(heads.hasMoreElements()) { headBuffer.append(heads.nextElement().toString()).append("\r\n"); } return headBuffer.toString(); } /** * Prepares the explanation text making substitutions in the <I>explanationText</I> template string. * Utility method that searches for all occurrences of some pattern strings * and substitute them with the appropriate params. * @param explanationText The template string for the explanation text. * @param signerName The string that will replace the <CODE>[signerName]</CODE> pattern. * @param signerAddress The string that will replace the <CODE>[signerAddress]</CODE> pattern. * @param reversePath The string that will replace the <CODE>[reversePath]</CODE> pattern. * @param headers The string that will replace the <CODE>[headers]</CODE> pattern. * @return The actual explanation text string with all replacements done. */ protected final String getReplacedExplanationText(String explanationText, String signerName, String signerAddress, String reversePath, String headers) { String replacedExplanationText = explanationText; replacedExplanationText = getReplacedString(replacedExplanationText, SIGNER_NAME_PATTERN, signerName); replacedExplanationText = getReplacedString(replacedExplanationText, SIGNER_ADDRESS_PATTERN, signerAddress); replacedExplanationText = getReplacedString(replacedExplanationText, REVERSE_PATH_PATTERN, reversePath); replacedExplanationText = getReplacedString(replacedExplanationText, HEADERS_PATTERN, headers); return replacedExplanationText; } /** * Searches the <I>template</I> String for all occurrences of the <I>pattern</I> string * and creates a new String substituting them with the <I>actual</I> String. * @param template The template String to work on. * @param pattern The string to search for the replacement. * @param actual The actual string to use for the replacement. */ private String getReplacedString(String template, String pattern, String actual) { if (actual != null) { StringBuffer sb = new StringBuffer(template.length()); int fromIndex = 0; int index; while ((index = template.indexOf(pattern, fromIndex)) >= 0) { sb.append(template.substring(fromIndex, index)); sb.append(actual); fromIndex = index + pattern.length(); } if (fromIndex < template.length()){ sb.append(template.substring(fromIndex)); } return sb.toString(); } else { return new String(template); } } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -