View Javadoc

1   /**
2    * LICENCIA LGPL:
3    * 
4    * Esta librería es Software Libre; Usted puede redistribuirla y/o modificarla
5    * bajo los términos de la GNU Lesser General Public License (LGPL) tal y como 
6    * ha sido publicada por la Free Software Foundation; o bien la versión 2.1 de 
7    * la Licencia, o (a su elección) cualquier versión posterior.
8    * 
9    * Esta librería se distribuye con la esperanza de que sea útil, pero SIN 
10   * NINGUNA GARANTÍA; tampoco las implícitas garantías de MERCANTILIDAD o 
11   * ADECUACIÓN A UN PROPÓSITO PARTICULAR. Consulte la GNU Lesser General Public 
12   * License (LGPL) para más detalles
13   * 
14   * Usted debe recibir una copia de la GNU Lesser General Public License (LGPL) 
15   * junto con esta librería; si no es así, escriba a la Free Software Foundation 
16   * Inc. 51 Franklin Street, 5º Piso, Boston, MA 02110-1301, USA o consulte
17   * <http://www.gnu.org/licenses/>.
18   *
19   * Copyright 2011 Agencia de Tecnología y Certificación Electrónica
20   */
21  package es.accv.arangi.util.smime;
22  
23  
24  import java.io.ByteArrayInputStream;
25  import java.io.ByteArrayOutputStream;
26  import java.io.IOException;
27  import java.io.InputStream;
28  
29  import javax.activation.CommandMap;
30  import javax.activation.MailcapCommandMap;
31  import javax.mail.MessagingException;
32  import javax.mail.Part;
33  import javax.mail.Session;
34  import javax.mail.internet.MimeBodyPart;
35  import javax.mail.internet.MimeMessage;
36  import javax.mail.internet.MimeMultipart;
37  import javax.mail.internet.MimePart;
38  
39  import org.bouncycastle.cms.CMSException;
40  import org.bouncycastle.cms.CMSSignedData;
41  import org.bouncycastle.mail.smime.CMSProcessableBodyPart;
42  
43  /**
44   * Esta clase se copia directamente de la antigua librería IDEAS. Su función es
45   * la de permitir la validación de los tokens de validación de la ACCV, ya que
46   * las primeras versiones de Bouncy Castle que se utilizaron construían los 
47   * S-MIMEs de un modo incompatible con las nuevas versiones.
48   */
49  public class SMIMESigned extends CMSSignedData {
50  
51    
52    Object                  message;
53    MimeBodyPart            content;
54  
55    static
56    {
57        MailcapCommandMap mc = (MailcapCommandMap)CommandMap.getDefaultCommandMap();
58  
59        mc.addMailcap("application/pkcs7-signature;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.pkcs7_signature");
60        mc.addMailcap("application/pkcs7-mime;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.pkcs7_mime");
61        mc.addMailcap("application/x-pkcs7-signature;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.x_pkcs7_signature");
62        mc.addMailcap("application/x-pkcs7-mime;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.x_pkcs7_mime");
63        mc.addMailcap("multipart/signed;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.multipart_signed");
64        
65        CommandMap.setDefaultCommandMap(mc);
66    }
67    
68  
69    private static InputStream getInputStream(
70        Part    bodyPart)
71        throws MessagingException
72    {
73        try
74        {
75            if (bodyPart.isMimeType("multipart/signed"))
76            {
77                throw new MessagingException("attempt to create signed data object from multipart content - use MimeMultipart constructor.");
78            }
79            
80            return bodyPart.getInputStream();
81        }
82        catch (IOException e)
83        {
84            throw new MessagingException("can't extract input stream: " + e);
85        }
86    }
87  
88    
89    
90  
91    /**
92     * @param message
93     * @throws MessagingException
94     * @throws CMSException
95     */
96    public SMIMESigned(MimeMultipart message) throws MessagingException, CMSException {
97      super(new CMSProcessableBodyPart(message.getBodyPart(0)), getInputStream(message.getBodyPart(1)));
98  
99      this.message = message;
100     this.content = (MimeBodyPart)message.getBodyPart(0);
101   }
102 
103 
104 
105   /**
106    * return the content that was signed.
107    */
108   public MimeBodyPart getContent() {
109     return content;
110   }
111 
112 
113   /**
114    * Return the content that was signed as a mime message.
115    * 
116    * @param session
117    * @return a MimeMessage holding the content.
118    * @throws MessagingException
119    */
120   public MimeMessage getContentAsMimeMessage(Session session) throws MessagingException, IOException {
121     Object content = getSignedContent().getContent();
122     byte[] contentBytes = null;
123 
124     if (content instanceof byte[]) {
125       contentBytes = (byte[]) content;
126     } else if (content instanceof MimePart) {
127       MimePart part = (MimePart) content;
128       ByteArrayOutputStream out;
129 
130       if (part.getSize() > 0) {
131         out = new ByteArrayOutputStream(part.getSize());
132       } else {
133         out = new ByteArrayOutputStream();
134       }
135 
136       part.writeTo(out);
137       contentBytes = out.toByteArray();
138     } else {
139       String type = "<null>";
140       if (content != null) {
141         type = content.getClass().getName();
142       }
143 
144       throw new MessagingException("Could not transfrom content of type " + type + " into MimeMessage.");
145     }
146 
147     if (contentBytes != null) {
148       ByteArrayInputStream in = new ByteArrayInputStream(contentBytes);
149 
150       return new MimeMessage(session, in);
151     }
152 
153     return null;
154   }
155 
156 
157   /**
158    * return the content that was signed - depending on whether this was
159    * unencapsulated or not it will return a MimeMultipart or a MimeBodyPart
160    */
161   public Object getContentWithSignature() {
162     return message;
163   }
164 
165 
166 }