1use std::{
2
3 fmt::{
4
5 Formatter as FmtFormatter,
6 Result as FmtResult,
7 Debug as FmtDebug,
8 },
9
10 time::{SystemTime},
11 net::{IpAddr},
12};
13
14use chrono::{
15
16 NaiveDateTime,
17 DateTime,
18 Utc,
19};
20
21use rustls_native_certs::{Certificate as TlsNativeCertificate};
22
23use rustls::{
24
25 server::{
26 AllowAnyAuthenticatedClient as TlsAllowAnyAuthenticatedClient,
27 ClientCertVerifier as TlsClientCertVerifier,
28 },
29
30 OwnedTrustAnchor as TlsOwnedTrustAnchor,
31 RootCertStore as TlsRootCertStore,
32 Certificate as TlsCertificate,
33};
34
35use serde::{
36
37 Deserialize,
38 Serialize,
39};
40
41use webpki_roots::{TLS_SERVER_ROOTS};
42
43use x509_parser::prelude::{
44
45 X509Certificate,
46 TbsCertificate,
47 GeneralName,
48 FromDer,
49};
50
51#[derive(Clone, Copy, Debug)]
52#[derive(Serialize, Deserialize)]
53pub struct CertificateValidity {
54 begin: DateTime<Utc>,
55 end: DateTime<Utc>,
56}
57
58impl CertificateValidity {
59 pub(crate) fn from_timestamps(begin: i64, end: i64) -> CertificateValidity {
60 CertificateValidity {
61 begin: DateTime::from_utc(NaiveDateTime::from_timestamp_opt(begin.min(end), 0)
62 .unwrap_or_default(), Utc),
63 end: DateTime::from_utc(NaiveDateTime::from_timestamp_opt(end.max(begin), 0)
64 .unwrap_or_default(), Utc),
65 }
66 }
67
68 pub fn is_within_valid_time(&self) -> bool {
69 let now = Utc::now();
70
71 if self.end > now {
72 if self.begin < now {
73 return true
74 }
75 }
76
77 false
78 }
79
80 pub fn timestamp_begin(&self) -> i64 {
81 self.begin.timestamp()
82 }
83
84 pub fn time_begin(&self) -> DateTime<Utc> {
85 self.begin.clone()
86 }
87
88 pub fn timestamp_end(&self) -> i64 {
89 self.end.timestamp()
90 }
91
92 pub fn time_end(&self) -> DateTime<Utc> {
93 self.end.clone()
94 }
95}
96
97#[derive(Clone, Debug)]
98#[derive(Serialize, Deserialize)]
99pub enum CertificateAlternateName {
100 Directory(String),
101 Hostname(String),
102 Address(String),
103 Email(String),
104 Uri(String),
105}
106
107impl<'a> CertificateAlternateName {
108 pub fn to_string(&'a self) -> String{
109 match self {
110 CertificateAlternateName::Directory(ref string) => string.clone(),
111 CertificateAlternateName::Hostname(ref string) => string.clone(),
112 CertificateAlternateName::Address(ref string) => string.clone(),
113 CertificateAlternateName::Email(ref string) => string.clone(),
114 CertificateAlternateName::Uri(ref string) => string.clone(),
115 }
116 }
117
118 pub fn as_str(&'a self) -> &'a str {
119 match self {
120 CertificateAlternateName::Directory(ref string) => string.as_str(),
121 CertificateAlternateName::Hostname(ref string) => string.as_str(),
122 CertificateAlternateName::Address(ref string) => string.as_str(),
123 CertificateAlternateName::Email(ref string) => string.as_str(),
124 CertificateAlternateName::Uri(ref string) => string.as_str(),
125 }
126 }
127}
128
129#[derive(Clone)]
130#[derive(Serialize, Deserialize)]
131pub struct CertificateData {
132 pub(crate) authority: bool,
133 pub(crate) issuer_name: Option<String>,
134 pub(crate) issuer_country:Option<String>,
135 pub(crate) issuer_state:Option<String>,
136 pub(crate) issuer_organization:Option<String>,
137 pub(crate) issuer_organizational_unit:Option<String>,
138 pub(crate) subject_name: Option<String>,
139 pub(crate) subject_alternate_names: Vec<CertificateAlternateName>,
140 pub(crate) subject_country:Option<String>,
141 pub(crate) subject_state:Option<String>,
142 pub(crate) subject_organization:Option<String>,
143 pub(crate) subject_organizational_unit:Option<String>,
144 pub(crate) validity: CertificateValidity,
145 pub(crate) serial: Vec<u8>,
146 pub(crate) raw_der_encoded: Vec<u8>,
147}
148
149impl CertificateData {
150 pub fn authority(&self) -> bool {
151 self.authority
152 }
153
154 pub fn issuer_name(&self) -> Option<&str> {
155 if let Some(ref issuer_name) = self.issuer_name {
156 return Some(issuer_name.as_str())
157 }
158
159 None
160 }
161
162 pub fn issuer_country(&self) -> Option<&str> {
163 if let Some(ref issuer_country) = self.issuer_country {
164 return Some(issuer_country.as_str())
165 }
166
167 None
168 }
169
170 pub fn issuer_state(&self) -> Option<&str> {
171 if let Some(ref issuer_state) = self.issuer_state {
172 return Some(issuer_state.as_str())
173 }
174
175 None
176 }
177
178 pub fn issuer_organization(&self) -> Option<&str> {
179 if let Some(ref issuer_organization) = self.issuer_organization {
180 return Some(issuer_organization.as_str())
181 }
182
183 None
184 }
185
186 pub fn issuer_organizational_unit(&self) -> Option<&str> {
187 if let Some(ref issuer_organizational_unit) = self.issuer_organizational_unit {
188 return Some(issuer_organizational_unit.as_str())
189 }
190
191 None
192 }
193
194 pub fn subject_name(&self) -> Option<&str> {
195 if let Some(ref subject_name) = self.subject_name {
196 return Some(subject_name.as_str())
197 }
198
199 None
200 }
201
202 pub fn subject_alternate_names(&self) -> &[CertificateAlternateName] {
203 self.subject_alternate_names.as_slice()
204 }
205
206 pub fn subject_country(&self) -> Option<&str> {
207 if let Some(ref subject_country) = self.subject_country {
208 return Some(subject_country.as_str())
209 }
210
211 None
212 }
213
214 pub fn subject_state(&self) -> Option<&str> {
215 if let Some(ref subject_state) = self.subject_state {
216 return Some(subject_state.as_str())
217 }
218
219 None
220 }
221
222 pub fn subject_organization(&self) -> Option<&str> {
223 if let Some(ref subject_organization) = self.subject_organization {
224 return Some(subject_organization.as_str())
225 }
226
227 None
228 }
229
230 pub fn subject_organizational_unit(&self) -> Option<&str> {
231 if let Some(ref subject_organizational_unit) = self.subject_organizational_unit {
232 return Some(subject_organizational_unit.as_str())
233 }
234
235 None
236 }
237
238 pub fn validity(&self) -> CertificateValidity {
239 self.validity
240 }
241
242 pub fn serial(&self) -> &[u8] {
243 self.serial.as_slice()
244 }
245
246 pub fn raw_der_encoded(&self) -> &[u8] {
247 self.raw_der_encoded.as_slice()
248 }
249}
250
251impl FmtDebug for CertificateData {
252 fn fmt(&self, formatter: &mut FmtFormatter<'_>) -> FmtResult {
253 formatter.debug_struct("Certificate")
254 .field("authority", &(self.authority()))
255 .field("issuer_name", &(self.issuer_name()))
256 .field("issuer_country", &(self.issuer_country()))
257 .field("issuer_state", &(self.issuer_state()))
258 .field("issuer_organization", &(self.issuer_organization()))
259 .field("issuer_organizational_unit", &(self.issuer_organizational_unit()))
260 .field("subject_name", &(self.subject_name()))
261 .field("subject_alternate_names", &(self.subject_alternate_names()))
262 .field("subject_country", &(self.subject_country()))
263 .field("subject_state", &(self.subject_state()))
264 .field("subject_organization", &(self.subject_organization()))
265 .field("subject_organizational_unit", &(self.subject_organizational_unit()))
266 .field("validity", &(self.validity()))
267 .finish()
268 }
269}
270
271#[derive(Clone, Debug)]
272#[derive(Serialize, Deserialize)]
273pub enum Certificate {
274 Signed(CertificateData),
275 Pending(CertificateData),
276}
277
278impl Certificate {
279 pub fn parse(data: &[u8]) -> Option<Certificate> {
281 let (pending, remaining, certificate) = if let Ok((remaining, certificate)) = X509Certificate::from_der(data) {
282 (false, remaining, certificate.tbs_certificate)
283 }
284
285 else {
286
287 if let Ok((remaining, tbs_certificate)) = TbsCertificate::from_der(data) {
288 (true, remaining, tbs_certificate)
289 }
290
291 else {
292
293 return None
294 }
295 };
296
297 let authority = certificate.is_ca();
298
299 let issuer_name = certificate.issuer().iter_common_name()
300 .filter_map(|name| name.as_str().ok())
301 .next().and_then(|name| Some({
302 Some(name.to_owned())
303 })).unwrap_or(None);
304
305 let issuer_country = certificate.issuer().iter_country()
306 .filter_map(|name| name.as_str().ok())
307 .next().and_then(|name| Some({
308 Some(name.to_owned())
309 })).unwrap_or(None);
310
311 let issuer_state = certificate.issuer().iter_state_or_province()
312 .filter_map(|name| name.as_str().ok())
313 .next().and_then(|name| Some({
314 Some(name.to_owned())
315 })).unwrap_or(None);
316
317 let issuer_organization = certificate.issuer().iter_organization()
318 .filter_map(|name| name.as_str().ok())
319 .next().and_then(|name| Some({
320 Some(name.to_owned())
321 })).unwrap_or(None);
322
323 let issuer_organizational_unit = certificate.issuer().iter_organizational_unit()
324 .filter_map(|name| name.as_str().ok())
325 .next().and_then(|name| Some({
326 Some(name.to_owned())
327 })).unwrap_or(None);
328
329 let subject_name = certificate.subject().iter_common_name()
330 .filter_map(|name| name.as_str().ok())
331 .next().and_then(|name| Some({
332 Some(name.to_owned())
333 })).unwrap_or(None);
334
335 let subject_alternate = if let Ok(Some(extension)) = certificate.subject_alternative_name() {
336 extension.value.general_names.iter().filter_map(|name| match name {
337 GeneralName::DirectoryName(name) => Some({
338 CertificateAlternateName::Directory(name.to_string())
339 }),
340 GeneralName::RFC822Name(name) => Some({
341 CertificateAlternateName::Email(name.to_string())
342 }),
343 GeneralName::IPAddress(octets) => Some({
344 CertificateAlternateName::Address(match octets {
345 octets if octets.len() == 4 => {
346 let mut array: [u8; 4] = Default::default();
347 for i in 0..4 { array[i] = octets[i] }
348 IpAddr::from(array).to_string()
349 },
350 octets if octets.len() == 16 => {
351 let mut array: [u8; 16] = Default::default();
352 for i in 0..16 { array[i] = octets[i] }
353 IpAddr::from(array).to_string()
354 },
355 _ => return None
356 })
357 }),
358 GeneralName::DNSName(name) => Some({
359 CertificateAlternateName::Hostname(name.to_string())
360 }),
361 GeneralName::URI(name) => Some({
362 CertificateAlternateName::Uri(name.to_string())
363 }),
364 _ => None,
365 }).filter_map(|alternate| match alternate.clone() {
366 CertificateAlternateName::Directory(ref item) |
367 CertificateAlternateName::Hostname(ref item) |
368 CertificateAlternateName::Address(ref item) |
369 CertificateAlternateName::Email(ref item) |
370 CertificateAlternateName::Uri(ref item) => {
371 if let Some(ref subject) = subject_name {
372 if item == subject.as_str() {
373 return None
374 }
375 }
376
377 Some(alternate)
378 }
379 }).collect()
380 } else { Default::default() };
381
382 let subject_country = certificate.subject().iter_country()
383 .filter_map(|name| name.as_str().ok())
384 .next().and_then(|name| Some({
385 Some(name.to_owned())
386 })).unwrap_or(None);
387
388 let subject_state = certificate.subject().iter_state_or_province()
389 .filter_map(|name| name.as_str().ok())
390 .next().and_then(|name| Some({
391 Some(name.to_owned())
392 })).unwrap_or(None);
393
394 let subject_organization = certificate.subject().iter_organization()
395 .filter_map(|name| name.as_str().ok())
396 .next().and_then(|name| Some({
397 Some(name.to_owned())
398 })).unwrap_or(None);
399
400 let subject_organizational_unit = certificate.subject().iter_organizational_unit()
401 .filter_map(|name| name.as_str().ok())
402 .next().and_then(|name| Some({
403 Some(name.to_owned())
404 })).unwrap_or(None);
405
406 let validity = {
407
408 let begin = certificate.validity.not_before.timestamp();
409 let end = certificate.validity.not_after.timestamp();
410
411 CertificateValidity::from_timestamps(begin, end)
412 };
413
414 let serial = certificate.serial.to_bytes_be();
415
416 let raw_der_encoded = data[..(data.len() - remaining.len())].to_vec();
417
418 let data = CertificateData {
419
420 authority,
421 issuer_name,
422 issuer_country,
423 issuer_state,
424 issuer_organization,
425 issuer_organizational_unit,
426 subject_name,
427 subject_alternate_names: subject_alternate,
428 subject_country,
429 subject_state,
430 subject_organization,
431 subject_organizational_unit,
432 validity,
433 serial,
434 raw_der_encoded,
435 };
436
437 if pending { Some(Certificate::Pending(data)) }
438 else { Some(Certificate::Signed(data)) }
439 }
440
441 pub fn verify_trust_chain_web_roots(&self, chain: &[Certificate]) -> bool {
442 let mut trust_store = TlsRootCertStore::empty();
443
444 trust_store.add_server_trust_anchors(TLS_SERVER_ROOTS.0.iter().map(|anchor| {
445 TlsOwnedTrustAnchor::from_subject_spki_name_constraints(anchor.subject, anchor.spki, anchor.name_constraints)
446 }));
447
448 let ref certificate = TlsCertificate(self.raw_der_encoded().to_owned());
449 let chain: Vec<TlsCertificate> = chain.iter().map(|certificate| {
450 TlsCertificate(certificate.raw_der_encoded().to_vec())
451 }).collect();
452
453 TlsAllowAnyAuthenticatedClient::new(trust_store)
454 .verify_client_cert(certificate, chain.as_slice(), SystemTime::now())
455 .is_ok()
456 }
457
458 pub fn verify_trust_chain_system_roots(&self, chain: &[Certificate]) -> bool {
459 if let Ok(native) = rustls_native_certs::load_native_certs() {
460 let mut trust_store = TlsRootCertStore::empty();
461
462 for TlsNativeCertificate(data) in native.iter() {
463 let ref root = TlsCertificate(data.to_vec());
464 if let Err(..) = trust_store.add(root) {
465 continue
466 }
467 }
468
469 let ref certificate = TlsCertificate(self.raw_der_encoded().to_owned());
470 let chain: Vec<TlsCertificate> = chain.iter().map(|certificate| {
471 TlsCertificate(certificate.raw_der_encoded().to_vec())
472 }).collect();
473
474 return TlsAllowAnyAuthenticatedClient::new(trust_store)
475 .verify_client_cert(certificate, chain.as_slice(), SystemTime::now())
476 .is_ok()
477 }
478
479 false
480 }
481
482 pub fn verify_trust_chain(&self, chain: &[Certificate], roots: &[Certificate]) -> bool {
483 let mut trust_store = TlsRootCertStore::empty();
484
485 for root in roots.iter() {
486 let ref certificate = TlsCertificate(root.raw_der_encoded().to_owned());
487 if let Err(..) = trust_store.add(certificate) {
488 return false
489 }
490 }
491
492 let ref certificate = TlsCertificate(self.raw_der_encoded().to_owned());
493 let chain: Vec<TlsCertificate> = chain.iter().map(|certificate| {
494 TlsCertificate(certificate.raw_der_encoded().to_vec())
495 }).collect();
496
497 TlsAllowAnyAuthenticatedClient::new(trust_store)
498 .verify_client_cert(certificate, chain.as_slice(), SystemTime::now())
499 .is_ok()
500 }
501
502 pub fn authority(&self) -> bool {
503 match self {
504 Certificate::Signed(data) => data.authority(),
505 Certificate::Pending(data) => data.authority(),
506 }
507 }
508
509 pub fn issuer_name(&self) -> Option<&str> {
510 match self {
511 Certificate::Signed(data) => data.issuer_name(),
512 Certificate::Pending(data) => data.issuer_name(),
513 }
514 }
515
516 pub fn issuer_country(&self) -> Option<&str> {
517 match self {
518 Certificate::Signed(data) => data.issuer_country(),
519 Certificate::Pending(data) => data.issuer_country(),
520 }
521 }
522
523 pub fn issuer_state(&self) -> Option<&str> {
524 match self {
525 Certificate::Signed(data) => data.issuer_state(),
526 Certificate::Pending(data) => data.issuer_state(),
527 }
528 }
529
530 pub fn issuer_organization(&self) -> Option<&str> {
531 match self {
532 Certificate::Signed(data) => data.issuer_organization(),
533 Certificate::Pending(data) => data.issuer_organization(),
534 }
535 }
536
537 pub fn issuer_organizational_unit(&self) -> Option<&str> {
538 match self {
539 Certificate::Signed(data) => data.issuer_organizational_unit(),
540 Certificate::Pending(data) => data.issuer_organizational_unit(),
541 }
542 }
543
544 pub fn subject_name(&self) -> Option<&str> {
545 match self {
546 Certificate::Signed(data) => data.subject_name(),
547 Certificate::Pending(data) => data.subject_name(),
548 }
549 }
550
551 pub fn subject_alternate_names(&self) -> &[CertificateAlternateName] {
552 match self {
553 Certificate::Signed(data) => data.subject_alternate_names(),
554 Certificate::Pending(data) => data.subject_alternate_names(),
555 }
556 }
557
558 pub fn subject_country(&self) -> Option<&str> {
559 match self {
560 Certificate::Signed(data) => data.subject_country(),
561 Certificate::Pending(data) => data.subject_country(),
562 }
563 }
564
565 pub fn subject_state(&self) -> Option<&str> {
566 match self {
567 Certificate::Signed(data) => data.subject_state(),
568 Certificate::Pending(data) => data.subject_state(),
569 }
570 }
571
572 pub fn subject_organization(&self) -> Option<&str> {
573 match self {
574 Certificate::Signed(data) => data.subject_organization(),
575 Certificate::Pending(data) => data.subject_organization(),
576 }
577 }
578
579 pub fn subject_organizational_unit(&self) -> Option<&str> {
580 match self {
581 Certificate::Signed(data) => data.subject_organizational_unit(),
582 Certificate::Pending(data) => data.subject_organizational_unit(),
583 }
584 }
585
586 pub fn validity(&self) -> CertificateValidity {
587 match self {
588 Certificate::Signed(data) => data.validity(),
589 Certificate::Pending(data) => data.validity(),
590 }
591 }
592
593 pub fn serial(&self) -> &[u8] {
594 match self {
595 Certificate::Signed(data) => data.serial(),
596 Certificate::Pending(data) => data.serial(),
597 }
598 }
599
600 pub fn raw_der_encoded(&self) -> &[u8] {
601 match self {
602 Certificate::Signed(data) => data.raw_der_encoded(),
603 Certificate::Pending(data) => data.raw_der_encoded(),
604 }
605 }
606}