1 package es.caib.signatura.impl;
2
3 import java.io.ByteArrayOutputStream;
4 import java.io.File;
5 import java.io.FileFilter;
6 import java.io.FileInputStream;
7 import java.io.FileNotFoundException;
8 import java.io.FileWriter;
9 import java.io.IOException;
10 import java.io.InputStream;
11 import java.io.OutputStream;
12 import java.io.PrintWriter;
13 import java.lang.reflect.Constructor;
14 import java.lang.reflect.InvocationTargetException;
15 import java.lang.reflect.Method;
16 import java.net.URL;
17 import java.security.Provider;
18 import java.security.ProviderException;
19 import java.security.Security;
20 import java.security.cert.X509Certificate;
21 import java.util.Collection;
22 import java.util.Date;
23 import java.util.Iterator;
24 import java.util.LinkedHashMap;
25 import java.util.LinkedList;
26 import java.util.Map;
27 import java.util.Properties;
28 import java.util.StringTokenizer;
29 import java.util.Vector;
30
31 import es.caib.signatura.api.ParsedCertificate;
32 import es.caib.signatura.api.SMIMEParser;
33 import es.caib.signatura.api.Signature;
34 import es.caib.signatura.api.SignatureCertNotFoundException;
35 import es.caib.signatura.api.SignatureException;
36 import es.caib.signatura.api.SignaturePrivKeyException;
37 import es.caib.signatura.api.SignatureProviderException;
38 import es.caib.signatura.api.SignatureTimestampException;
39 import es.caib.signatura.api.SignatureVerifyException;
40 import es.caib.signatura.api.Signer;
41 import es.caib.signatura.impl.ui.FirefoxSignerProfileChooser;
42
43
44
45
46
47 public class CAIBSigner implements Signer {
48
49 private static LinkedHashMap realSigners = null;
50 private static LinkedHashMap remoteRealSigners = null;
51 private SignaturaProperties properties = null;
52 private static ClassLoaderFactory factory;
53 private static Object lock = new Object();
54
55 private SignerProviderInterface getSigner(String certificateName, String contentType)
56 throws SignatureCertNotFoundException {
57
58 boolean recognized = properties.needsRecognizedCertificate(contentType);
59 Iterator signersIterator = realSigners.values().iterator();
60 Iterator remoteSignersIterator = remoteRealSigners.values().iterator();
61
62 LinkedList providers = new LinkedList();
63 LinkedList certs = new LinkedList();
64
65 while ( signersIterator.hasNext() ) {
66
67 LocalSignerProviderInterface s = (LocalSignerProviderInterface)signersIterator.next();
68
69 ParsedCertificate[] providerCerts;
70
71 try {
72
73 providerCerts = s.getCertList(recognized);
74
75 for (int j = 0; j < providerCerts.length; j++) {
76
77 if ( providerCerts[j].getCommonName().equals(certificateName) ) {
78
79
80
81
82 providers.add(s);
83 certs.add(providerCerts[j]);
84 break;
85
86 }
87
88 }
89
90
91
92 } catch (SignatureCertNotFoundException e) {
93 } catch (SignaturePrivKeyException e) {
94 } catch (ProviderException e){
95 }
96
97 }
98
99
100
101
102 while ( remoteSignersIterator.hasNext() ) {
103
104 RemoteSignerProviderInterface s = (RemoteSignerProviderInterface)remoteSignersIterator.next();
105
106 String[] providerCerts;
107
108 try {
109
110 providerCerts = s.getCertList(recognized);
111
112 for (int j = 0; j < providerCerts.length; j++) {
113
114 if ( providerCerts[j].equals(certificateName) ) {
115 System.out.println("Seleccionado "+certificateName+" con el provider "+s.getClass().getName());
116 return s;
117 }
118
119 }
120
121
122
123 } catch (SignatureCertNotFoundException e) {
124 } catch (SignaturePrivKeyException e) {
125 } catch (ProviderException e){
126 }
127
128 }
129
130 if (SigDebug.isActive())
131 SigDebug.write("CAIBSIGNER: filtrando certificados con el CN '" + certificateName + "' entre signers...");
132
133
134
135
136 if (certs.size() > 0) {
137
138 LocalSignerProviderInterface s = null;
139 Date validSince = null;
140
141
142
143 int i=0;
144 for(i=0;i<providers.size();i++) {
145
146 LocalSignerProviderInterface key = (LocalSignerProviderInterface)providers.get(i);
147 ParsedCertificate parsed = (ParsedCertificate)certs.get(i);
148
149 if (SigDebug.isActive()) {
150 SigDebug.write("CAIBSIGNER: comprobando signer " + key);
151 SigDebug.write("CAIBSIGNER: Emisión: " + parsed.getValidSince().getTime());
152 }
153
154 if (validSince != null)
155 if (SigDebug.isActive())
156 SigDebug.write("CAIBSIGNER: Stored Emisión: " + validSince.getTime());
157 else
158 if (SigDebug.isActive())
159 SigDebug.write("CAIBSIGNER: Stored Emisión: null");
160
161
162
163
164
165 if ( validSince == null || validSince.getTime() < parsed.getValidSince().getTime() ) {
166
167 if (SigDebug.isActive()) {
168 SigDebug.write("CAIBSIGNER: El certificado del signer " + key.getClass().getName() + " tiene una fecha de emisión más reciente que el del signer almacenado " + s.getClass().getName());
169 SigDebug.write("CAIBSIGNER: Actualizando datos temporales");
170 }
171
172 validSince = parsed.getValidSince();
173 s = key;
174
175 } else {
176
177 if (SigDebug.isActive()) {
178 SigDebug.write("CAIBSIGNER: El certificado del signer " + key.getClass().getName() + " tiene una fecha de emisión menor o igual que el del signer almacenado " + s.getClass().getName());
179 SigDebug.write("CAIBSIGNER: DESCARTADO...");
180 }
181
182 }
183
184 }
185
186 if (SigDebug.isActive())
187 SigDebug.write("CAIBSIGNER: filtro de certificados duplicados para '" + certificateName + "' completado");
188
189
190 if ( s != null ) {
191 System.out.println("Seleccionado "+certificateName+" con el provider "+s.getClass().getName());
192 return s;
193
194 } else {
195
196 throw new SignatureCertNotFoundException();
197
198 }
199
200 } else {
201
202 throw new SignatureCertNotFoundException();
203
204 }
205
206 }
207
208 public String[] getCertList(String contentType)
209 throws SignatureCertNotFoundException, SignaturePrivKeyException {
210
211 synchronized (lock) {
212
213 Vector v = new Vector();
214 Collection signersCollection = realSigners.values();
215 Collection remoteSignersCollection = remoteRealSigners.values();
216
217 if (signersCollection != null) {
218
219 Iterator signersIterator = signersCollection.iterator();
220
221 if (signersIterator != null) {
222
223 while ( signersIterator.hasNext() ) {
224
225 LocalSignerProviderInterface s = (LocalSignerProviderInterface)signersIterator.next();
226
227 ParsedCertificate certs[];
228 boolean recognized = properties.needsRecognizedCertificate(contentType);
229
230 try {
231 certs = s.getCertList(recognized);
232 for (int j = 0 ; j < certs.length; j++)
233 {
234 if (!v.contains(certs[j].getCommonName()))
235 v.add(certs[j].getCommonName());
236 }
237 } catch (SignatureCertNotFoundException e) {
238
239
240 } catch (SignaturePrivKeyException e) {
241 e.printStackTrace();
242 } catch(Throwable e) {
243 System.err.println ("CANNOT LOAD on signature provider " + s.getClass().getName());
244 e.printStackTrace();
245 }
246
247 }
248
249 }
250
251 }
252
253 if (remoteSignersCollection != null) {
254
255 Iterator remoteSignersIterator = remoteSignersCollection.iterator();
256
257 if (remoteSignersIterator != null) {
258
259 while ( remoteSignersIterator.hasNext() ) {
260
261 RemoteSignerProviderInterface s = (RemoteSignerProviderInterface)remoteSignersIterator.next();
262
263 String certs[];
264 boolean recognized = properties.needsRecognizedCertificate(contentType);
265
266 try {
267 certs = s.getCertList(recognized);
268 for (int j = 0 ; j < certs.length; j++)
269 {
270 if (!v.contains(certs[j]))
271 v.add(certs[j]);
272 }
273 } catch (SignatureCertNotFoundException e) {
274
275
276 } catch (SignaturePrivKeyException e) {
277 e.printStackTrace();
278 } catch(Throwable e) {
279 System.err.println ("CANNOT LOAD on signature provider " + s.getClass().getName());
280 e.printStackTrace();
281 }
282
283 }
284
285 }
286
287 }
288
289 return (String[])v.toArray(new String[v.size()]);
290
291 }
292
293 }
294
295 public Signature sign(String fileName, String certificateName,
296 String password, String contentType) throws IOException,
297 SignatureException {
298 return sign (new FileInputStream (fileName), certificateName, password, contentType);
299 }
300
301 public Signature sign(InputStream contentStream, String certificateName,
302 String password, String contentType) throws IOException,
303 SignatureException {
304 synchronized (lock){
305 boolean recognized = properties.needsRecognizedCertificate(contentType);
306 boolean timeStamp = properties.needsTimeStamp(contentType);
307 boolean rawSign = properties.needsRawSignature(contentType);
308 SignerProviderInterface signer = getSigner (certificateName, contentType);
309
310 if( password == null ) {
311 if( SigDebug.isActive() ) SigDebug.write( "Password is null." );
312 password = "";
313 }
314 if( SigDebug.isActive() ) {
315 SigDebug.write( "CAIBSigned.sign: password is" + (password.length() == 0? "" : " not") + " empty." );
316 }
317 return signer.sign(contentStream, certificateName, password, contentType, recognized, timeStamp, rawSign);
318 }
319 }
320
321 public Signature sign(URL url, String certificateName, String password, String contentType)
322 throws IOException, SignatureException
323 {
324 return sign (url.openStream(), certificateName, password, contentType);
325 }
326
327
328
329
330
331 public void signPDF(InputStream contentStream, OutputStream signedStream,
332 String certificateName, String password, String contentType, String url,
333 int position, boolean allowMultipleSignature)
334 throws IOException, SignatureException {
335
336 synchronized (lock) {
337
338 boolean recognized = properties.needsRecognizedCertificate(contentType);
339 SignerProviderInterface signer = getSigner (certificateName, contentType);
340
341 if ( SigDebug.isActive() ) {
342 SigDebug.write( "Comprovacio password null." );
343 }
344
345 if ( password == null ) {
346
347 if ( SigDebug.isActive() )
348 SigDebug.write( "Posem el password a cadena buida." );
349
350 password = "";
351
352 }
353
354 if ( SigDebug.isActive() ) {
355 SigDebug.write( "CAIBSigned.sign: password " + (password.length() == 0? "es" : "no es") + " buit." );
356 }
357
358 signer.signPDF(contentStream, signedStream, certificateName, password, contentType, recognized, url, position, allowMultipleSignature);
359
360 }
361
362 }
363
364 public void signPDF(InputStream pdfInputStream, OutputStream signedStream, String certificateName, String password, String contentType, String textoAdicional, int stampOptions, float top, float left, float height, float width, float rotation, boolean allowMultipleSignature) throws IOException, SignatureException {
365 synchronized (lock) {
366
367 boolean recognized = properties.needsRecognizedCertificate(contentType);
368 SignerProviderInterface signer = getSigner (certificateName, contentType);
369
370 if ( SigDebug.isActive() ) {
371 SigDebug.write( "Comprovacio password null." );
372 }
373
374 if ( password == null ) {
375
376 if ( SigDebug.isActive() )
377 SigDebug.write( "Posem el password a cadena buida." );
378
379 password = "";
380
381 }
382
383 if ( SigDebug.isActive() ) {
384 SigDebug.write( "CAIBSigned.sign: password " + (password.length() == 0? "es" : "no es") + " buit." );
385 }
386
387 signer.signPDF(pdfInputStream, signedStream, certificateName, password, contentType, recognized, textoAdicional, stampOptions,top, left, height,width,rotation, allowMultipleSignature);
388
389 }
390 }
391
392
393
394
395 public void signPDF(InputStream contentStream, OutputStream signedStream,
396 String certificateName, String password, String contentType, String url,
397 int position)
398 throws IOException, SignatureException {
399
400 signPDF(contentStream,signedStream,certificateName,password,contentType,url,position,false);
401
402 }
403
404
405
406
407
408 public OutputStream signPDF(InputStream contentStream,
409 String certificateName, String password, String contentType, String url,
410 int position, boolean allowMultipleSignature)
411 throws IOException, SignatureException {
412
413 OutputStream out = new ByteArrayOutputStream();
414 signPDF(contentStream, out, certificateName, password, contentType, url, position, allowMultipleSignature);
415 return out;
416
417 }
418
419
420
421
422
423 public OutputStream signPDF(InputStream contentStream,
424 String certificateName, String password, String contentType, String url,
425 int position)
426 throws IOException, SignatureException {
427
428
429 return signPDF(contentStream,certificateName,password,contentType,url,position,false);
430
431 }
432
433
434
435
436 public void certifyDigitalCopy (InputStream contentStream, OutputStream signedStream, String certificateName,
437 String password, String contentType, String url, String localidad, float x, float y, float rotation)
438 throws IOException, SignatureException {
439
440 synchronized (lock) {
441
442 boolean recognized = properties.needsRecognizedCertificate(contentType);
443 SignerProviderInterface signer = getSigner (certificateName, contentType);
444
445 if ( SigDebug.isActive() ) {
446 SigDebug.write( "Comprovacio password null." );
447 }
448
449 if ( password == null ) {
450
451 if ( SigDebug.isActive() )
452 SigDebug.write( "Posem el password a cadena buida." );
453
454 password = "";
455
456 }
457
458 if ( SigDebug.isActive() ) {
459 SigDebug.write( "CAIBSigned.certify: password " + (password.length() == 0? "es" : "no es") + " buit." );
460 }
461
462 signer.certifyDigitalCopy(contentStream, signedStream, certificateName, password, contentType, recognized, url, localidad, x, y, rotation,properties);
463
464 }
465
466 }
467
468
469
470
471 public boolean verify(InputStream contentStream, Signature signatureData)
472 throws SignatureProviderException, IOException, SignatureVerifyException
473 {
474 try{
475 boolean isVerified = false;
476 isVerified = signatureData.verify(contentStream);
477 return isVerified;
478 } catch(SignatureVerifyException e){
479 throw e;
480 } catch(Exception e){
481 throw new SignatureVerifyException(e);
482 }
483 }
484
485 public boolean verifyAPosterioriTimeStamp(InputStream contentStream, Signature signatureData)
486 throws SignatureProviderException, IOException, SignatureVerifyException
487 {
488 boolean isVerified = false;
489 try{
490 isVerified = signatureData.verifyAPosterioriTimestamp(contentStream);
491 }catch(SignatureVerifyException e){
492 throw e;
493 } catch(Exception e){
494 throw new SignatureVerifyException(e);
495 }
496 return isVerified;
497 }
498
499 public boolean verify(String fileName, Signature signatureData)
500 throws FileNotFoundException, SignatureProviderException, IOException, SignatureVerifyException
501 {
502 return verify( new FileInputStream(fileName) ,signatureData);
503 }
504
505 public boolean verify(URL url, Signature signatureData)
506 throws SignatureProviderException, IOException, SignatureVerifyException
507 {
508 return verify( url.openStream() ,signatureData);
509 }
510
511
512
513
514
515 public boolean verifyAPosterioriTimeStamp(String fileName, Signature signatureData)
516 throws FileNotFoundException, SignatureProviderException, IOException, SignatureVerifyException
517 {
518 return verifyAPosterioriTimeStamp(new FileInputStream(fileName), signatureData);
519 }
520
521 public boolean verifyAPosterioriTimeStamp(URL url, Signature signatureData)
522 throws SignatureProviderException, IOException, SignatureVerifyException
523 {
524 return verifyAPosterioriTimeStamp(url.openStream(), signatureData);
525 }
526
527
528
529
530
531
532 public void generateSMIME(InputStream document, Signature signature,
533 OutputStream smime) throws IOException {
534 SMIMEGenerator smimeGenerator;
535 try {
536 Class c = factory.getMasterClassLoader().loadClass("es.caib.signatura.provider.impl.common.SMIMEGeneratorImpl");
537 smimeGenerator = (SMIMEGenerator)c.newInstance();
538 }
539 catch(Exception e){
540 throw new RuntimeException (e);
541 }
542
543 InputStream in = smimeGenerator.generateSMIME(document,signature);
544
545 byte b []= new byte [8192];
546 int read;
547 while ( (read = in.read(b)) > 0)
548 {
549 smime.write(b, 0, read);
550 }
551 in.close();
552 }
553
554
555
556 public void generateSMIMEParalell(InputStream document, Signature[] signatures, OutputStream smime) throws IOException, SignatureException {
557
558 try {
559
560 Class c = factory.getMasterClassLoader().loadClass("es.caib.signatura.provider.impl.common.GeneradorSMIMEParaleloImpl");
561 GeneradorSMIMEParalelo generadorSMIMEParalelo = (GeneradorSMIMEParalelo)c.newInstance();
562 SMIMEInputStream in = generadorSMIMEParalelo.generarSMIMEParalelo(document,signatures);
563
564 byte b[] = new byte[8192];
565 int read;
566 while ( (read=in.read(b) ) > 0) {
567 smime.write(b,0,read);
568 }
569 in.close();
570
571 }catch (IOException iox) {
572 throw iox;
573 }catch (Exception e) {
574 throw new SignatureException(e.getMessage());
575 }
576 }
577
578
579
580 public Date getCurrentDate(String certificateName, String password,
581 String contentType) throws SignatureTimestampException,
582 SignatureException, IOException {
583 if( password == null ) password = "";
584 if( SigDebug.isActive() ) {
585 SigDebug.write( "CAIBSigned.getCurrentDate: password " + (password.length() == 0? "is" : "is not") + " null." );
586 }
587 boolean recognized = properties.needsRecognizedCertificate(contentType);
588 return getSigner(certificateName, contentType).getCurrentDate(certificateName, password, recognized);
589 }
590
591 public String getAPIVersion()
592 {
593 try {
594 InputStream inputStream = CAIBSigner.class.getResourceAsStream("version.properties");
595 if (inputStream==null)
596 {
597 throw new FileNotFoundException();
598 }
599 Properties tempProperties = new Properties();
600 tempProperties.load(inputStream);
601
602 inputStream.close();
603 return tempProperties.getProperty("Version");
604 } catch (FileNotFoundException e) {
605 throw new RuntimeException (e);
606 } catch (IOException e) {
607 throw new RuntimeException (e);
608 }
609 }
610
611
612
613
614
615 public CAIBSigner () throws FileNotFoundException {
616 preInitialize();
617
618 try {
619 properties = new SignaturaProperties();
620
621 } catch (Exception e1) {
622 throw new RuntimeException (e1);
623 }
624 initialize();
625 }
626
627
628
629
630
631
632
633
634 public CAIBSigner(String updateSite,URL configurationFile,String propertiesCachePath) throws FileNotFoundException {
635 preInitialize();
636
637
638 try {
639 properties = new SignaturaProperties(updateSite,configurationFile,propertiesCachePath);
640
641 } catch (Exception e1) {
642 throw new RuntimeException (e1);
643 }
644 initialize();
645 }
646
647
648
649
650
651
652 public CAIBSigner (Map signerConfiguration) throws FileNotFoundException
653 {
654 preInitialize();
655
656
657 try {
658 properties = new SignaturaProperties(signerConfiguration);
659 } catch (Exception e1) {
660 throw new RuntimeException (e1);
661 }
662 initialize();
663 }
664
665 protected void preInitialize() throws FileNotFoundException{
666
667 CAIBSecurityManager.register();
668
669
670
671 if (factory == null) {
672 factory = ClassLoaderFactory.getFactory ();
673 realSigners = new LinkedHashMap();
674 remoteRealSigners = new LinkedHashMap();
675 }
676 }
677
678 protected void initialize () throws FileNotFoundException {
679
680
681
682 try {
683
684
685
686
687
688
689 if (Security.getProvider("BC") == null) {
690 Provider p = (Provider) factory.getMasterClassLoader().loadClass("org.bouncycastle.jce.provider.BouncyCastleProvider").newInstance();
691 Security.addProvider(p);
692 }
693
694
695
696 InputStream inputStream = factory.getMasterClassLoader().getResourceAsStream("es/caib/signatura/provider/impl/lunaPCI/LunaPCISigner.class");
697 if (inputStream != null) {
698
699 if (Security.getProvider("LunaJCE") == null) {
700 Provider p = (Provider) factory.getMasterClassLoader().loadClass("com.chrysalisits.cryptox.LunaJCEProvider").newInstance();
701 Security.addProvider(p);
702 }
703
704 if (Security.getProvider("LunaJCA") == null) {
705 Provider p = (Provider) factory.getMasterClassLoader().loadClass("com.chrysalisits.crypto.LunaJCAProvider").newInstance();
706 Security.addProvider(p);
707 }
708
709 }
710
711 } catch(Exception e) {
712
713 throw new RuntimeException (e);
714
715 }
716
717
718
719
720
721 if ( SigDebug.getLevel() == SigDebug.DEBUG_LEVEL_NONE ) {
722 SigDebug.setLevel( properties.getProperty("debugLevel") );
723 }
724
725
726
727
728
729
730
731 if (System.getProperty("es.caib.provider.unactive") == null
732 || System.getProperty("es.caib.provider.unactive").indexOf("tradise") == -1) {
733
734 try {
735 addTradiseSigner( "tradise");
736 SigDebug.write( "[DBG] ACTIVAT TRADISE." );
737 } catch (FileNotFoundException e) {
738
739 } catch (Exception e) {
740 e.printStackTrace();
741 }
742
743 File dirDev = new File (factory.getLibraryDir(), "tradise-dev");
744 if (dirDev.isDirectory())
745 {
746 try {
747 addTradiseSigner( "tradise-dev");
748 SigDebug.write( "[DBG] ACTIVAT TRADISE TEST." );
749 } catch (Exception e) {
750 e.printStackTrace();
751 }
752 }
753
754 }
755
756
757 if (System.getProperty("es.caib.provider.unactive") == null
758 || System.getProperty("es.caib.provider.unactive").indexOf("PKCS11") == -1) {
759
760 String drivers []= properties.getPKCS11Drivers();
761
762 for (int i = 0; i < drivers.length; i++)
763 {
764 try{
765 if(addPKCS11Signer(drivers[i]))
766 SigDebug.write( "[DBG] ACTIVAT PKCS11 "+drivers[i]+"." );
767 }
768 catch (Throwable e){
769 e.printStackTrace();
770 }
771 }
772
773 }
774
775
776
777 if ( System.getProperty("os.name").contains("Windows") ) {
778
779 if (System.getProperty("es.caib.provider.unactive") == null
780 || System.getProperty("es.caib.provider.unactive").indexOf("MSCRYPTOAPI") == -1) {
781
782 try {
783 addMscryptoapiSigner();
784
785 }
786 catch (Exception e){
787 e.printStackTrace();
788 }
789
790 }
791
792 }
793
794
795 if (System.getProperty("es.caib.provider.unactive") == null
796 || System.getProperty("es.caib.provider.unactive").indexOf("LUNAPCI") == -1) {
797
798 try {
799 if ( addLunaPCISigner() )
800 SigDebug.write( "[DBG] ACTIVAT LUNAPCI." );
801 }
802 catch (Exception e){
803 e.printStackTrace();
804 }
805
806 }
807
808
809 if (System.getProperty("es.caib.provider.unactive") == null
810 || System.getProperty("es.caib.provider.unactive").indexOf("WEBSERVICESIGNER") == -1) {
811
812 try {
813 if ( addWebServiceSigner() )
814 SigDebug.write( "[DBG] ACTIVAT WEBSERVICESIGNER." );
815 }
816 catch (Throwable e){
817 e.printStackTrace();
818 }
819
820 }
821
822
823 if (System.getProperty("es.caib.provider.unactive") == null
824 || System.getProperty("es.caib.provider.unactive").indexOf("FIREFOXSIGNER") == -1) {
825
826 try{
827 if ( addFirefoxSigner(factory) )
828 SigDebug.write("[DBG] ACTIVAT FIREFOXSIGNER.");
829 }
830 catch (Throwable e){
831 e.printStackTrace();
832 }
833
834
835 }
836
837
838
839 if ( System.getProperty("es.caib.provider.unactive") == null
840 || System.getProperty("es.caib.provider.unactive").indexOf("BC") == -1 ) {
841
842 if ( System.getProperty("caib-crypto-keystore-password") != null ) {
843
844 try {
845
846 if(addBcCryptoApiSigner())
847 SigDebug.write("[DBG] ACTIVAT BC.");
848
849 } catch (Exception e) {
850
851 if (e instanceof SignatureException
852 && e.getMessage().contains(".keystore")) {
853
854 SigDebug.write("WARNING (BC): el usuario no posee keystore por defecto. No se cargará el signer de BC.");
855
856 } else {
857
858 e.printStackTrace();
859
860 }
861
862 }
863
864 } else {
865
866 SigDebug.write("[DBG] System properties needed for BC signer are not set");
867
868 }
869
870 }
871
872
873
874 }
875
876 private boolean addPKCS11Signer (String libraryName) throws Exception
877 {
878
879 File f = new File (libraryName);
880 if ( f.isAbsolute())
881 {
882 String name = f.getName();
883 if (realSigners.get(name) == null)
884 {
885 if(addPKCS11Signer (name, f)) return true;
886 }
887 } else {
888 if (realSigners.get(libraryName) == null)
889 {
890 String path = System.getProperty("java.library.path");
891 StringTokenizer tokenizer = new StringTokenizer (path, File.pathSeparator);
892 while (tokenizer.hasMoreTokens())
893 {
894 File next = new File( tokenizer.nextToken() );
895 f = new File (next, libraryName);
896 if (addPKCS11Signer (libraryName, f))
897 return true;
898 f = new File (next, libraryName+".dll") ;
899 if (addPKCS11Signer (libraryName, f))
900 return true;
901
902 }
903 }else{
904 return true;
905 }
906 }
907
908 return false;
909 }
910
911 private boolean addPKCS11Signer(String libraryName, File f) throws Exception {
912 if (f.canRead())
913 {
914 String providerName = properties.getPKCS11DriversDescription(libraryName);
915
916 File cfg = File.createTempFile(libraryName, "pkcs11.cfg");
917 PrintWriter writer = new PrintWriter (new FileWriter (cfg));
918 writer.println("name="+libraryName);
919 writer.println("library="+f.getAbsolutePath());
920 writer.close();
921 cfg.deleteOnExit();
922 Class c = factory.getMasterClassLoader().loadClass("es.caib.signatura.provider.impl.pkcs11.PKCS11Signer");
923 Constructor constructor = c.getConstructor(new Class [] {String.class,String.class});
924 realSigners.put(libraryName, constructor.newInstance(new Object [] {cfg.getAbsolutePath(),providerName}));
925 return true;
926
927
928 }
929 else
930 return false;
931 }
932
933 private void addTradiseSigner (String name) throws ClassNotFoundException, InstantiationException, IllegalAccessException, FileNotFoundException
934 {
935
936 if (realSigners.get(name) == null)
937 {
938 ClassLoader loader = factory.getClassLoader(name);
939 Class c = loader.loadClass("es.caib.signatura.provider.impl.tradise.TradiseSigner");
940 realSigners.put(name, c.newInstance());
941 }
942
943 }
944
945 private boolean addBcCryptoApiSigner()
946 throws SignatureException, ClassNotFoundException, InstantiationException, IllegalAccessException
947 {
948
949
950
951 Class c = factory.getMasterClassLoader().loadClass("es.caib.signatura.provider.impl.bccryptoapi.BcCryptoApiSigner");
952 realSigners.put("bccryptoapi", c.newInstance());
953
954 if ( SigDebug.isActive() )
955 SigDebug.write("CAIBSigner: addBcCryptoApiSigner: Keystore certificates loaded.");
956
957 return true;
958 }
959
960 private boolean addWebServiceSigner() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
961
962
963
964
965 InputStream inputStream = factory.getMasterClassLoader().getResourceAsStream("es/caib/signatura/provider/impl/webServiceSigner/WebServiceSigner.class");
966
967 if (inputStream != null) {
968
969 Class c = factory.getMasterClassLoader().loadClass("es.caib.signatura.provider.impl.webServiceSigner.WebServiceSigner");
970 remoteRealSigners.put("WebServiceSigner", c.newInstance());
971
972 if ( SigDebug.isActive() )
973 SigDebug.write("CAIBSigner: addWebServiceSigner: WebServiceSigner loaded.");
974
975 return true;
976
977 }
978
979 return false;
980
981
982
983 }
984
985
986
987
988
989
990 private void addMscryptoapiSigner() {
991 if (realSigners.get("mscryptoapi") == null)
992 {
993
994 String fullVersion = System.getProperty("java.version");
995
996 int lastIndex = fullVersion.lastIndexOf(".");
997
998 String version = fullVersion.substring(0, lastIndex);
999
1000 float versionNumber = Float.valueOf(version).floatValue();
1001
1002 boolean is64bits = (System.getProperty("os.arch").indexOf("64") != -1);
1003
1004
1005
1006
1007
1008 if (versionNumber >= 1.6 && is64bits) {
1009
1010 try {
1011
1012
1013
1014 Class c = factory.getMasterClassLoader().loadClass("es.caib.signatura.provider.impl.sunmscapi.SunMSCAPIProvider");
1015 realSigners.put("mscryptoapi", c.newInstance());
1016
1017 if( SigDebug.isActive() )
1018 SigDebug.write("CAIBSigner: addMscryptoapiSigner: es.caib.signatura.provider.impl.sunmscapi.SunMSCAPIProvider");
1019
1020 SigDebug.write( "[DBG] ACTIVAT MSCAPI." );
1021 } catch (Throwable e) {
1022
1023 e.printStackTrace();
1024 SigDebug.write("es.caib.signatura.provider.impl.sunmscapi.SunMSCAPIProvider cannot be loaded.");
1025
1026 }
1027
1028
1029
1030
1031
1032 } else {
1033
1034 try {
1035
1036
1037
1038 String libraryName = System.getProperty("java.home")+"\\lib\\signaturacaib\\mscryptofunctions.dll";
1039
1040 if( SigDebug.isActive() )
1041 SigDebug.write("CAIBSigner: addMscryptoapiSigner: Path mscryptofunctions = " + libraryName);
1042
1043 File f = new File (libraryName);
1044
1045 if (f.canRead()){
1046
1047 Class c = factory.getMasterClassLoader().loadClass("es.caib.signatura.provider.impl.mscryptoapi.MscryptoapiSigner");
1048 realSigners.put("mscryptoapi", c.newInstance());
1049
1050 if( SigDebug.isActive() )
1051 SigDebug.write("CAIBSigner: addMscryptoapiSigner: Cargada mscryptofunctions.dll");
1052
1053 }
1054
1055 SigDebug.write( "[DBG] ACTIVAT MSCRYPTOAPI." );
1056 } catch(Exception e) {
1057
1058 e.printStackTrace();
1059 SigDebug.write("mscryptofunctions.dll cannot be loaded.");
1060
1061 }
1062
1063 }
1064 }
1065
1066 }
1067
1068
1069
1070
1071
1072
1073
1074 private boolean addLunaPCISigner() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
1075
1076
1077
1078
1079 InputStream inputStream = factory.getMasterClassLoader().getResourceAsStream("es/caib/signatura/provider/impl/lunaPCI/LunaPCISigner.class");
1080
1081 if (inputStream != null) {
1082
1083 Class c = factory.getMasterClassLoader().loadClass("es.caib.signatura.provider.impl.lunaPCI.LunaPCISigner");
1084 realSigners.put("lunaPCI", c.newInstance());
1085
1086 if ( SigDebug.isActive() )
1087 SigDebug.write("CAIBSigner: addLunaPCISigner: Cargados los certificados del dispositivo");
1088
1089 return true;
1090
1091 }
1092
1093 return false;
1094
1095
1096
1097 }
1098
1099 public SMIMEParser getSMIMEParser(InputStream smime) throws InstantiationException, IllegalAccessException, IOException, SignatureException {
1100 return new SMIMEParserProxy(smime);
1101 }
1102
1103 public ParsedCertificate parseCertificate(X509Certificate certificate) {
1104 try {
1105 Class c = factory.getMasterClassLoader().loadClass("es.caib.signatura.provider.impl.common.ParsedCertificateImpl");
1106 Constructor constructor = c.getConstructor(new Class [] {X509Certificate[].class, boolean.class});
1107
1108
1109 return (ParsedCertificate) constructor.newInstance(new Object [] {new X509Certificate[] {certificate}, new Boolean(false)});
1110 } catch (Exception e) {
1111 throw new RuntimeException(e);
1112 }
1113 }
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127 private boolean addFirefoxSigner(ClassLoaderFactory factory) throws Exception {
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138 String osName = null;
1139 String[] nssDirs = null;
1140 String nssLibraryDirectory = null;
1141 String profilesPath = null;
1142 String[] profileDirs = null;
1143
1144 String homeDir = System.getProperty("user.home").replaceAll("\\\\","/");
1145
1146 if ( System.getProperty("os.name").contains("Windows") ) {
1147
1148 osName = "windows";
1149
1150 String programFiles32=System.getenv("ProgramFiles").replaceAll("\\\\", "/");
1151 String programFiles64=System.getenv("ProgramFiles(x86)");
1152
1153
1154 if(programFiles64!=null && !"".equals(programFiles64)){
1155
1156 programFiles64=programFiles64.replaceAll("\\\\", "/");
1157 if(System.getProperty("os.arch").indexOf("64")!=-1){
1158
1159 nssDirs = new String[] {
1160 programFiles64+"/Mozilla Firefox"
1161 };
1162 }else{
1163
1164 nssDirs = new String[] {
1165 programFiles32+"/Mozilla Firefox"
1166 };
1167 }
1168 }else{
1169
1170 nssDirs = new String[] {
1171 programFiles32+"/Mozilla Firefox"
1172 };
1173
1174 }
1175
1176 String appdata=System.getenv("APPDATA").replaceAll("\\\\", "/");
1177 profileDirs = new String[] {
1178 appdata+"/Mozilla/Firefox/Profiles"
1179 };
1180
1181 } else if ( System.getProperty("os.name").contains("Linux") ) {
1182
1183 osName = "linux";
1184
1185
1186
1187 File sysLibPath=new File("/usr/lib");
1188 File[] firefoxLibDirs=sysLibPath.listFiles(new FileFilter() {
1189
1190 public boolean accept(File pathname) {
1191 if(pathname.getAbsolutePath().contains("firefox")) return true;
1192 return false;
1193 }
1194 });
1195
1196
1197 nssDirs=new String [firefoxLibDirs.length];
1198
1199 int i=0;
1200 for(i=0;i<firefoxLibDirs.length;i++){
1201 nssDirs[i]=firefoxLibDirs[i].getAbsolutePath();
1202 }
1203
1204
1205
1206
1207 profileDirs = new String[] {
1208 homeDir + "/.mozilla/firefox"
1209 };
1210
1211
1212
1213
1214 } else if ( System.getProperty("os.name").contains("Mac OS") ) {
1215
1216 osName = "mac";
1217
1218
1219 nssDirs = new String[] {
1220 "/Applications/Firefox.app/Contents/MacOS"
1221 };
1222
1223
1224 profileDirs = new String[] {
1225 homeDir+"/Library/Mozilla/Firefox/Profiles",
1226 homeDir+"/Library/Application Support/Firefox/Profiles"
1227 };
1228
1229
1230
1231
1232 } else {
1233
1234 SigDebug.write("WARNING: OS not supported yet '" + System.getProperty("os.name") + "'");
1235 return false;
1236
1237 }
1238
1239
1240 for(int i=0;i<nssDirs.length;i++)
1241 SigDebug.write("NSSDir: "+nssDirs[i]);
1242
1243 if(nssDirs!=null)
1244 nssLibraryDirectory = firefoxSignerFindNSSLibraryDirectory(nssDirs, osName);
1245
1246 SigDebug.write("nssLibraryDirectory: "+nssLibraryDirectory);
1247
1248 if (nssLibraryDirectory == null) {
1249 SigDebug.write("WARNING: NSS library directory not found");
1250 return false;
1251 }
1252
1253
1254 firefoxSignerLoadNSSLibraries(nssLibraryDirectory, osName);
1255
1256
1257 profilesPath = firefoxSignerFindProfilesDirectory(profileDirs);
1258 if ( profilesPath == null ) {
1259 SigDebug.write("WARNING: Profiles directory not found");
1260 return false;
1261 }
1262
1263
1264 File profilesDir = new File( profilesPath );
1265 File[] profilesDirFiles = firefoxSignerFilterProfileDirectories( profilesDir.listFiles() );
1266
1267 if (profilesDirFiles.length > 0) {
1268
1269 int i = 0;
1270
1271 try {
1272
1273
1274
1275 if (profilesDirFiles.length > 1)
1276 i = firefoxSignerAskForUserProfile(profilesDirFiles);
1277
1278 String providerConfig = firefoxSignerGetProviderConfig(profilesDirFiles[i], profilesPath, nssLibraryDirectory);
1279
1280 Class c = factory.getMasterClassLoader().loadClass("es.caib.signatura.provider.impl.firefox.FirefoxSigner");
1281 Constructor constructor = c.getConstructor(new Class [] {String.class, String.class});
1282 realSigners.put(
1283 "FIREFOXSIGNER",
1284 constructor.newInstance(new Object [] {providerConfig, profilesDirFiles[i].getName()})
1285 );
1286
1287 }catch (InvocationTargetException e) {
1288 e.getTargetException().printStackTrace();
1289 return false;
1290
1291 } catch (Exception e) {
1292
1293 e.printStackTrace();
1294 return false;
1295
1296 }
1297
1298 } else {
1299
1300 SigDebug.write("WARNING: No avalaible Firefox profiles found");
1301 return false;
1302
1303 }
1304
1305 return true;
1306
1307
1308 }
1309
1310
1311
1312
1313
1314
1315
1316
1317 private static int firefoxSignerAskForUserProfile(File[] profilesDirFiles) throws Exception {
1318
1319 return FirefoxSignerProfileChooser.getFirefoxProfile(profilesDirFiles);
1320
1321 }
1322
1323
1324
1325
1326
1327
1328
1329 private static String firefoxSignerFindNSSLibraryDirectory(String[] dirs, String osName) {
1330
1331 boolean found = false;
1332 String nssLibraryDirectory = null;
1333 String libName = null;
1334
1335 if ( "windows".equals(osName) )
1336 libName = "/softokn3.dll";
1337 else if ( "linux".equals(osName) )
1338 libName = "/libsoftokn3.so";
1339 else if ( "mac".equals(osName) )
1340 libName = "/libsoftokn3.dylib";
1341 else
1342
1343
1344 return null;
1345
1346 for (int i = 0; i < dirs.length; i++) {
1347
1348 found = new File( dirs[i] + libName ).exists();
1349
1350 if ( found ) {
1351 nssLibraryDirectory = dirs[i];
1352 break;
1353 }
1354
1355 }
1356
1357 return nssLibraryDirectory;
1358
1359 }
1360
1361
1362
1363
1364
1365
1366
1367 private static String firefoxSignerFindProfilesDirectory(String[] dirs) {
1368
1369 boolean found = false;
1370 String profilesPath = null;
1371
1372 for (int i = 0; i < dirs.length; i++) {
1373
1374 found = new File( dirs[i] ).exists() && new File( dirs[i] ).isDirectory();
1375
1376 if ( found ) {
1377 profilesPath = dirs[i];
1378 break;
1379 }
1380
1381 }
1382
1383 return profilesPath;
1384
1385 }
1386
1387
1388
1389
1390
1391
1392
1393 private static void firefoxSignerLoadNSSLibraries(String nssLibraryDirectory, String osName) {
1394
1395 if ( "windows".equals(osName) ) {
1396
1397 try{System.load(nssLibraryDirectory + "/mozcrt19.dll");}catch(UnsatisfiedLinkError e){e.printStackTrace();}
1398 try{System.load(nssLibraryDirectory + "/sqlite3.dll");}catch(UnsatisfiedLinkError e){e.printStackTrace();}
1399 try{System.load(nssLibraryDirectory + "/nspr4.dll");}catch(UnsatisfiedLinkError e){e.printStackTrace();}
1400 try{System.load(nssLibraryDirectory + "/plc4.dll");}catch(UnsatisfiedLinkError e){e.printStackTrace();}
1401 try{System.load(nssLibraryDirectory + "/plds4.dll");}catch(UnsatisfiedLinkError e){e.printStackTrace();}
1402 try{System.load(nssLibraryDirectory + "/nssutil3.dll");}catch(UnsatisfiedLinkError e){e.printStackTrace();}
1403
1404 } else if ( "linux".equals(osName) || "mac".equals(osName) ) {
1405
1406 File nssLibDir=new File(nssLibraryDirectory);
1407 File [] nssLibs=nssLibDir.listFiles(new FileFilter() {
1408 public boolean accept(File pathname) {
1409 if(pathname.getAbsolutePath().endsWith(".so") || pathname.getAbsolutePath().endsWith(".dylib")) return true;
1410 return false;
1411 }
1412 });
1413 int i=0;
1414 for(i=0;i<nssLibs.length;i++)
1415 try{System.load(nssLibs[i].getAbsolutePath());}catch(UnsatisfiedLinkError e){e.printStackTrace();}
1416
1417
1418 }
1419
1420 }
1421
1422
1423
1424
1425
1426
1427 private static File[] firefoxSignerFilterProfileDirectories(File[] dirs) {
1428
1429
1430 Vector out = new Vector();
1431
1432 for (int i = 0; i < dirs.length; i++) {
1433
1434 String dir = dirs[i].getName();
1435
1436
1437
1438 if (dir.length() > 8 && dir.charAt(8) == '.' && !dir.contains("profiles.ini"))
1439 out.add( dirs[i] );
1440
1441 }
1442
1443 return (File[])out.toArray(new File[out.size()]);
1444
1445 }
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457 private static String firefoxSignerGetProviderConfig(File profileDir, String profilesPath, String nssLibraryDirectory) throws FileNotFoundException {
1458
1459 String profileDirName = profileDir.getName();
1460
1461
1462
1463
1464
1465
1466 String nssSecmodDirectory = profilesPath + "/" + profileDirName;
1467
1468
1469 if(System.getProperty("os.name").contains("Windows")){
1470 if(System.getProperty("java.version").contains("7")){
1471
1472 nssLibraryDirectory=getWindowsShortPath(new File(nssLibraryDirectory)).replaceAll("\\\\", "\\\\");
1473 nssSecmodDirectory=getWindowsShortPath(new File(nssSecmodDirectory.replaceAll("/","\\\\"))).replaceAll("\\\\", "\\\\").replaceAll("\\\\","/");
1474 }else{
1475 nssLibraryDirectory=new File(nssLibraryDirectory).getAbsolutePath().replaceAll("\\\\", "\\\\");
1476 nssSecmodDirectory=new File(nssSecmodDirectory).getAbsolutePath().replaceAll("\\\\", "\\\\").replaceAll("\\\\","/");
1477 }
1478 }
1479
1480 String providerCfg = "name = NSS" + profileDirName + "\n"+
1481 "nssLibraryDirectory = " + nssLibraryDirectory + "\n"+
1482 "nssSecmodDirectory = \"" + nssSecmodDirectory + "\"\n"+
1483 "nssDbMode = readOnly\n" +
1484 "nssModule = keystore\n";
1485
1486
1487
1488 return providerCfg;
1489
1490 }
1491
1492
1493 public static String getWindowsShortPath(File f) throws FileNotFoundException{
1494 if(!f.exists()) throw new FileNotFoundException("Cannot get short path of a non existing file");
1495
1496 String shortpath = "";
1497 StringTokenizer tokenizer = new StringTokenizer(f.getAbsolutePath(), "\\");
1498 String temp = null;
1499 String nextTemp=null;
1500 while(tokenizer.hasMoreTokens() == true)
1501 {
1502 int counter=1;
1503
1504 temp=(temp==null)?tokenizer.nextToken():nextTemp;
1505 nextTemp=tokenizer.nextToken();
1506 String tempShortpath=null;
1507 do{
1508 if(temp.length() > 8)
1509 tempShortpath = temp.replaceAll(" ","").substring(0, 6) + "~"+counter + "\\";
1510 else
1511 tempShortpath = temp + "\\";
1512
1513 counter++;
1514
1515 }while(!new File(shortpath+tempShortpath+nextTemp).exists() && counter<100);
1516 if(counter==100) throw new FileNotFoundException("Short path counter limit exceeded");
1517
1518 shortpath+=tempShortpath;
1519
1520 }
1521 return shortpath+nextTemp;
1522 }
1523 }
1524
1525
1526
1527
1528
1529