1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.opensaml.xml.security.x509;
18
19 import java.security.cert.CRLException;
20 import java.security.cert.CertificateEncodingException;
21 import java.util.HashSet;
22 import java.util.List;
23 import java.util.Set;
24
25 import javax.security.auth.x500.X500Principal;
26
27 import org.opensaml.xml.Configuration;
28 import org.opensaml.xml.XMLObject;
29 import org.opensaml.xml.security.SecurityException;
30 import org.opensaml.xml.security.credential.BasicKeyInfoGeneratorFactory;
31 import org.opensaml.xml.security.credential.Credential;
32 import org.opensaml.xml.security.keyinfo.KeyInfoGenerator;
33 import org.opensaml.xml.security.keyinfo.KeyInfoHelper;
34 import org.opensaml.xml.signature.KeyInfo;
35 import org.opensaml.xml.signature.X509CRL;
36 import org.opensaml.xml.signature.X509Certificate;
37 import org.opensaml.xml.signature.X509Data;
38 import org.opensaml.xml.signature.X509SKI;
39 import org.opensaml.xml.signature.impl.KeyInfoBuilder;
40 import org.opensaml.xml.signature.impl.X509DataBuilder;
41 import org.opensaml.xml.util.DatatypeHelper;
42 import org.opensaml.xml.util.LazySet;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45
46
47
48
49
50
51
52
53
54 public class X509KeyInfoGeneratorFactory extends BasicKeyInfoGeneratorFactory {
55
56
57 private X509Options options;
58
59
60 public X509KeyInfoGeneratorFactory() {
61 super();
62 options = (X509Options) super.getOptions();
63 }
64
65
66 public Class<? extends Credential> getCredentialType() {
67 return X509Credential.class;
68 }
69
70
71 public boolean handles(Credential credential) {
72 return credential instanceof X509Credential;
73 }
74
75
76 public KeyInfoGenerator newInstance() {
77
78 X509Options newOptions = options.clone();
79 return new X509KeyInfoGenerator(newOptions);
80 }
81
82
83
84
85
86
87 public boolean emitCRLs() {
88 return options.emitCRLs;
89 }
90
91
92
93
94
95
96 public void setEmitCRLs(boolean newValue) {
97 options.emitCRLs = newValue;
98 }
99
100
101
102
103
104
105 public boolean emitEntityCertificate() {
106 return options.emitEntityCertificate;
107 }
108
109
110
111
112
113
114 public void setEmitEntityCertificate(boolean newValue) {
115 options.emitEntityCertificate = newValue;
116 }
117
118
119
120
121
122
123 public boolean emitEntityCertificateChain() {
124 return options.emitEntityCertificateChain;
125 }
126
127
128
129
130
131
132 public void setEmitEntityCertificateChain(boolean newValue) {
133 options.emitEntityCertificateChain = newValue;
134 }
135
136
137
138
139
140
141 public boolean emitSubjectAltNamesAsKeyNames() {
142 return options.emitSubjectAltNamesAsKeyNames;
143 }
144
145
146
147
148
149
150 public void setEmitSubjectAltNamesAsKeyNames(boolean newValue) {
151 options.emitSubjectAltNamesAsKeyNames = newValue;
152 }
153
154
155
156
157
158
159 public boolean emitSubjectCNAsKeyName() {
160 return options.emitSubjectCNAsKeyName;
161 }
162
163
164
165
166
167
168 public void setEmitSubjectCNAsKeyName(boolean newValue) {
169 options.emitSubjectCNAsKeyName = newValue;
170 }
171
172
173
174
175
176
177 public boolean emitSubjectDNAsKeyName() {
178 return options.emitSubjectDNAsKeyName;
179 }
180
181
182
183
184
185
186 public void setEmitSubjectDNAsKeyName(boolean newValue) {
187 options.emitSubjectDNAsKeyName = newValue;
188 }
189
190
191
192
193
194
195
196 public boolean emitX509IssuerSerial() {
197 return options.emitX509IssuerSerial;
198 }
199
200
201
202
203
204
205
206 public void setEmitX509IssuerSerial(boolean newValue) {
207 options.emitX509IssuerSerial = newValue;
208 }
209
210
211
212
213
214
215 public boolean emitX509SKI() {
216 return options.emitX509SKI;
217 }
218
219
220
221
222
223
224 public void setEmitX509SKI(boolean newValue) {
225 options.emitX509SKI = newValue;
226 }
227
228
229
230
231
232
233 public boolean emitX509SubjectName() {
234 return options.emitX509SubjectName;
235 }
236
237
238
239
240
241
242 public void setEmitX509SubjectName(boolean newValue) {
243 options.emitX509SubjectName = newValue;
244 }
245
246
247
248
249
250
251
252
253
254
255 public Set<Integer> getSubjectAltNames() {
256 return options.subjectAltNames;
257 }
258
259
260
261
262
263
264
265
266 public X500DNHandler getX500DNHandler() {
267 return options.x500DNHandler;
268 }
269
270
271
272
273
274
275
276
277 public void setX500DNHandler(X500DNHandler handler) {
278 if (handler == null) {
279 throw new IllegalArgumentException("X500DNHandler may not be null");
280 }
281 options.x500DNHandler = handler;
282 }
283
284
285
286
287
288
289
290
291
292 public String getX500SubjectDNFormat() {
293 return options.x500SubjectDNFormat;
294 }
295
296
297
298
299
300
301
302
303
304 public void setX500SubjectDNFormat(String format) {
305 options.x500SubjectDNFormat = format;
306 }
307
308
309
310
311
312
313
314
315
316 public String getX500IssuerDNFormat() {
317 return options.x500IssuerDNFormat;
318 }
319
320
321
322
323
324
325
326
327
328 public void setX500IssuerDNFormat(String format) {
329 options.x500IssuerDNFormat = format;
330 }
331
332
333 protected X509Options getOptions() {
334 return options;
335 }
336
337
338 protected X509Options newOptions() {
339 return new X509Options();
340 }
341
342
343
344
345
346 public class X509KeyInfoGenerator extends BasicKeyInfoGenerator {
347
348
349 private final Logger log = LoggerFactory.getLogger(X509KeyInfoGenerator.class);
350
351
352 private X509Options options;
353
354
355 private KeyInfoBuilder keyInfoBuilder;
356
357
358 private X509DataBuilder x509DataBuilder;
359
360
361
362
363
364
365 protected X509KeyInfoGenerator(X509Options newOptions) {
366 super(newOptions);
367 options = newOptions;
368
369 keyInfoBuilder =
370 (KeyInfoBuilder) Configuration.getBuilderFactory().getBuilder(KeyInfo.DEFAULT_ELEMENT_NAME);
371 x509DataBuilder =
372 (X509DataBuilder) Configuration.getBuilderFactory().getBuilder(X509Data.DEFAULT_ELEMENT_NAME);
373 }
374
375
376 public KeyInfo generate(Credential credential) throws SecurityException {
377 if ( ! (credential instanceof X509Credential) ) {
378 log.warn("X509KeyInfoGenerator was passed a credential that was not an instance of X509Credential: {}",
379 credential.getClass().getName());
380 return null;
381 }
382 X509Credential x509Credential = (X509Credential) credential;
383
384 KeyInfo keyInfo = super.generate(credential);
385 if (keyInfo == null) {
386 keyInfo = keyInfoBuilder.buildObject();
387 }
388 X509Data x509Data = x509DataBuilder.buildObject();
389
390 processEntityCertificate(keyInfo, x509Data, x509Credential);
391 processEntityCertificateChain(keyInfo, x509Data, x509Credential);
392 processCRLs(keyInfo, x509Data, x509Credential);
393
394 List<XMLObject> x509DataChildren = x509Data.getOrderedChildren();
395 if (x509DataChildren != null && x509DataChildren.size() > 0) {
396 keyInfo.getX509Datas().add(x509Data);
397 }
398
399 List<XMLObject> keyInfoChildren = keyInfo.getOrderedChildren();
400 if (keyInfoChildren != null && keyInfoChildren.size() > 0) {
401 return keyInfo;
402 } else {
403 return null;
404 }
405 }
406
407
408
409
410
411
412
413
414 protected void processEntityCertificate(KeyInfo keyInfo, X509Data x509Data, X509Credential credential)
415 throws SecurityException {
416
417 if (credential.getEntityCertificate() == null) {
418 return;
419 }
420
421 java.security.cert.X509Certificate javaCert = credential.getEntityCertificate();
422
423 processCertX509DataOptions(x509Data, javaCert);
424 processCertKeyNameOptions(keyInfo, javaCert);
425
426
427 if (options.emitEntityCertificate && ! options.emitEntityCertificateChain) {
428 try {
429 X509Certificate xmlCert = KeyInfoHelper.buildX509Certificate(javaCert);
430 x509Data.getX509Certificates().add(xmlCert);
431 } catch (CertificateEncodingException e) {
432 throw new SecurityException("Error generating X509Certificate element "
433 + "from credential's end-entity certificate", e);
434 }
435 }
436
437 }
438
439
440
441
442
443
444
445 protected void processCertX509DataOptions(X509Data x509Data, java.security.cert.X509Certificate cert) {
446 processCertX509SubjectName(x509Data, cert);
447 processCertX509IssuerSerial(x509Data, cert);
448 processCertX509SKI(x509Data, cert);
449 }
450
451
452
453
454
455
456
457 protected void processCertKeyNameOptions(KeyInfo keyInfo, java.security.cert.X509Certificate cert) {
458 processSubjectDNKeyName(keyInfo, cert);
459 processSubjectCNKeyName(keyInfo, cert);
460 processSubjectAltNameKeyNames(keyInfo, cert);
461 }
462
463
464
465
466
467
468
469
470 protected void processCertX509SubjectName(X509Data x509Data, java.security.cert.X509Certificate cert) {
471 if (options.emitX509SubjectName) {
472 String subjectNameValue = getSubjectName(cert);
473 if (! DatatypeHelper.isEmpty(subjectNameValue)) {
474 x509Data.getX509SubjectNames().add( KeyInfoHelper.buildX509SubjectName(subjectNameValue));
475 }
476 }
477 }
478
479
480
481
482
483
484
485
486 protected void processCertX509IssuerSerial(X509Data x509Data, java.security.cert.X509Certificate cert) {
487 if (options.emitX509IssuerSerial) {
488 String issuerNameValue = getIssuerName(cert);
489 if (! DatatypeHelper.isEmpty(issuerNameValue)) {
490 x509Data.getX509IssuerSerials().add(
491 KeyInfoHelper.buildX509IssuerSerial(issuerNameValue, cert.getSerialNumber()) );
492 }
493 }
494 }
495
496
497
498
499
500
501
502
503 protected void processCertX509SKI(X509Data x509Data, java.security.cert.X509Certificate cert) {
504 if (options.emitX509SKI) {
505 X509SKI xmlSKI = KeyInfoHelper.buildX509SKI(cert);
506 if (xmlSKI != null) {
507 x509Data.getX509SKIs().add(xmlSKI);
508 }
509 }
510 }
511
512
513
514
515
516
517
518
519 protected String getSubjectName(java.security.cert.X509Certificate cert) {
520 if (cert == null) {
521 return null;
522 }
523 if (! DatatypeHelper.isEmpty(options.x500SubjectDNFormat)) {
524 return options.x500DNHandler.getName(cert.getSubjectX500Principal(), options.x500SubjectDNFormat);
525 } else {
526 return options.x500DNHandler.getName(cert.getSubjectX500Principal());
527 }
528 }
529
530
531
532
533
534
535
536
537 protected String getIssuerName(java.security.cert.X509Certificate cert) {
538 if (cert == null) {
539 return null;
540 }
541 if (! DatatypeHelper.isEmpty(options.x500IssuerDNFormat)) {
542 return options.x500DNHandler.getName(cert.getIssuerX500Principal(), options.x500IssuerDNFormat);
543 } else {
544 return options.x500DNHandler.getName(cert.getIssuerX500Principal());
545 }
546 }
547
548
549
550
551
552
553
554
555 protected void processSubjectDNKeyName(KeyInfo keyInfo, java.security.cert.X509Certificate cert) {
556 if (options.emitSubjectDNAsKeyName) {
557 String subjectNameValue = getSubjectName(cert);
558 if (! DatatypeHelper.isEmpty(subjectNameValue)) {
559 KeyInfoHelper.addKeyName(keyInfo, subjectNameValue);
560 }
561 }
562 }
563
564
565
566
567
568
569
570
571 protected void processSubjectCNKeyName(KeyInfo keyInfo, java.security.cert.X509Certificate cert) {
572 if (options.emitSubjectCNAsKeyName) {
573 for (String name : X509Util.getCommonNames(cert.getSubjectX500Principal())) {
574 if (! DatatypeHelper.isEmpty(name)) {
575 KeyInfoHelper.addKeyName(keyInfo, name);
576 }
577 }
578 }
579 }
580
581
582
583
584
585
586
587
588 protected void processSubjectAltNameKeyNames(KeyInfo keyInfo, java.security.cert.X509Certificate cert) {
589 if (options.emitSubjectAltNamesAsKeyNames && options.subjectAltNames.size() > 0) {
590 Integer[] nameTypes = new Integer[ options.subjectAltNames.size() ];
591 options.subjectAltNames.toArray(nameTypes);
592 for (Object altNameValue : X509Util.getAltNames(cert, nameTypes)) {
593
594
595 if (altNameValue instanceof String) {
596 KeyInfoHelper.addKeyName(keyInfo, (String) altNameValue);
597 } else if (altNameValue instanceof byte[]){
598 log.warn("Certificate contained an alt name value as a DER-encoded byte[] (not supported)");
599 } else {
600 log.warn("Certificate contained an alt name value with an unexpected type: {}",
601 altNameValue.getClass().getName());
602 }
603 }
604 }
605 }
606
607
608
609
610
611
612
613
614 protected void processEntityCertificateChain(KeyInfo keyInfo, X509Data x509Data, X509Credential credential)
615 throws SecurityException {
616
617 if (options.emitEntityCertificateChain && credential.getEntityCertificateChain() != null) {
618 for (java.security.cert.X509Certificate javaCert : credential.getEntityCertificateChain()) {
619 try {
620 X509Certificate xmlCert = KeyInfoHelper.buildX509Certificate(javaCert);
621 x509Data.getX509Certificates().add(xmlCert);
622 } catch (CertificateEncodingException e) {
623 throw new SecurityException("Error generating X509Certificate element "
624 + "from a certificate in credential's certificate chain", e);
625 }
626 }
627 }
628 }
629
630
631
632
633
634
635
636
637 protected void processCRLs(KeyInfo keyInfo, X509Data x509Data, X509Credential credential)
638 throws SecurityException {
639
640 if (options.emitCRLs && credential.getCRLs() != null) {
641 for (java.security.cert.X509CRL javaCRL : credential.getCRLs()) {
642 try {
643 X509CRL xmlCRL = KeyInfoHelper.buildX509CRL(javaCRL);
644 x509Data.getX509CRLs().add(xmlCRL);
645 } catch (CRLException e) {
646 throw new SecurityException("Error generating X509CRL element "
647 + "from a CRL in credential's CRL list", e);
648 }
649 }
650 }
651 }
652
653 }
654
655
656
657
658 protected class X509Options extends BasicOptions {
659
660
661 private boolean emitEntityCertificate;
662
663
664 private boolean emitEntityCertificateChain;
665
666
667 private boolean emitCRLs;
668
669
670 private boolean emitX509SubjectName;
671
672
673 private boolean emitX509IssuerSerial;
674
675
676 private boolean emitX509SKI;
677
678
679 private boolean emitSubjectDNAsKeyName;
680
681
682 private boolean emitSubjectCNAsKeyName;
683
684
685 private boolean emitSubjectAltNamesAsKeyNames;
686
687
688 private Set<Integer> subjectAltNames;
689
690
691 private X500DNHandler x500DNHandler;
692
693
694 private String x500SubjectDNFormat;
695
696
697 private String x500IssuerDNFormat;
698
699
700 protected X509Options() {
701 subjectAltNames = new LazySet<Integer>();
702 x500DNHandler = new InternalX500DNHandler();
703 x500SubjectDNFormat = X500DNHandler.FORMAT_RFC2253;
704 x500IssuerDNFormat = X500DNHandler.FORMAT_RFC2253;
705 }
706
707
708 protected X509Options clone() {
709 X509Options clonedOptions = (X509Options) super.clone();
710
711 clonedOptions.subjectAltNames = new LazySet<Integer>();
712 clonedOptions.subjectAltNames.addAll(this.subjectAltNames);
713
714 clonedOptions.x500DNHandler = this.x500DNHandler.clone();
715
716 return clonedOptions;
717 }
718
719 }
720
721 }