rusthound/modules/adcs/
parser.rs

1extern crate lazy_static;
2
3use lazy_static::lazy_static;
4use colored::Colorize;
5use ldap3::SearchEntry;
6use x509_parser::prelude::*;
7use std::collections::HashMap;
8use log::{info, debug, trace, error};
9
10use crate::enums::sid::decode_guid;
11use crate::enums::acl::parse_ntsecuritydescriptor;
12use crate::json::templates::bh_41::{prepare_adcs_ca_json_template,prepare_adcs_template_json_template};
13use crate::modules::adcs::utils::*;
14use crate::modules::adcs::flags::*;
15
16#[derive(Debug)]
17pub struct CA {
18    pub domain: String,
19    pub name: String,
20    pub dnshostname: String,
21    pub object_id: String,
22    pub user_specified_san: String,
23    pub request_disposition: String,
24    pub security: Vec<serde_json::value::Value>,
25    pub web_enrollment: String,
26    pub subject_name: String,
27    pub serial_number: String,
28    pub validity_start: String,
29    pub validity_end: String,
30    pub enabled_templates: Vec<String>
31}
32
33impl CA {
34    pub fn new(domain: &String) -> CA {
35        CA {
36            domain: String::from(domain.to_uppercase()),
37            name: String::from("name"),
38            dnshostname: String::from("name"),
39            object_id: String::from("object_id"),
40            user_specified_san: String::from("Unknown"),
41            request_disposition: String::from("Unknown"),
42            security: Vec::new(),
43            web_enrollment: String::from("Unknown"),
44            subject_name: String::from("subject_name"),
45            serial_number: String::from("serial_number"),
46            validity_start: String::from("validity_start"),
47            validity_end: String::from("validity_end"),
48            enabled_templates: Vec::new(),
49        }
50    }
51}
52
53/// Function to parse and replace value in json template for Certificate Authority domain object.
54pub fn parse_adcs_ca(
55    result: SearchEntry,
56    domain: &String,
57    adcs_templates: &mut HashMap<String, Vec<String>>,
58    old_bloodhound: bool,
59) -> serde_json::value::Value  {
60
61    let result_dn: String;
62    result_dn = result.dn.to_uppercase();
63
64    let result_attrs: HashMap<String, Vec<String>>;
65    result_attrs = result.attrs;
66
67    let result_bin: HashMap<String, Vec<Vec<u8>>>;
68    result_bin = result.bin_attrs;
69
70    let mut ca_json = prepare_adcs_ca_json_template();
71
72    // Prepare struct for this CA
73    let mut ca = CA::new(domain);
74
75    // Debug for current object
76    debug!("Parse (CA) Certificate Authority: {}", result_dn);
77    //for (key, value) in &result_attrs {
78    //    trace!("  {:?}:{:?}", key, value);
79    //}
80    ////trace result bin
81    //for (key, value) in &result_bin {
82    //    trace!("  {:?}:{:?}", key, value);
83    //}
84
85    // With a check
86    for (key, value) in &result_attrs {
87        match key.as_str() {
88            "name" => {
89                ca.name = value[0].to_owned().to_uppercase();
90                ca_json["Properties"]["name"] = format!("{}@{}",ca.name,ca.domain).into();
91                ca_json["Properties"]["CA Name"] = value[0].to_owned().to_uppercase().into();
92                ca_json["Properties"]["domain"] = domain.to_owned().to_uppercase().into();
93            }
94            "cACertificateDN" => {
95                ca.subject_name = value[0].to_owned();
96                ca_json["Properties"]["Certificate Subject"] = ca.subject_name.to_owned().into();
97                trace!("cACertificateDN: {}",&ca.subject_name);
98            }
99            "dNSHostName" => {
100                ca.dnshostname = value[0].to_owned();
101                ca_json["Properties"]["DNS Name"] = ca.dnshostname.to_owned().into();
102            }
103            "certificateTemplates" => {
104                if value.len() <= 0 {
105                    error!("No certificate templates enabled for {}",ca.name);
106                } else {
107                    ca.enabled_templates = value.to_vec();
108                    info!("Found {} enabled certificate templates",value.len().to_string().bold());
109                    trace!("Enabled certificate templates: {:?}",value);
110                }
111            }
112            _ => {}
113        }
114    }
115    // For all, bins attributs
116    for (key, value) in &result_bin {
117        match key.as_str() {
118            "objectGUID" => {
119                // objectGUID raw to string
120                ca.object_id = decode_guid(&value[0]);
121                ca_json["ObjectIdentifier"] = ca.object_id.to_owned().into();
122            }
123            "nTSecurityDescriptor" => {
124                // Needed with acl
125                let entry_type = "ca".to_string();
126                // nTSecurityDescriptor raw to string
127                let relations_ace = parse_ntsecuritydescriptor(
128                    &mut ca_json,
129                    &value[0],
130                    entry_type,
131                    &result_attrs,
132                    &result_bin,
133                    &domain,
134                );
135                ca.security = relations_ace.to_owned();
136                ca_json["Aces"] = relations_ace.into();
137            }
138            "cACertificate" => {
139                //info!("{:?}:{:?}", key,value[0].to_owned());
140                // <https://docs.rs/x509-parser/latest/x509_parser/certificate/struct.X509Certificate.html>
141                let res = X509Certificate::from_der(&value[0]);
142                match res {
143                    Ok((_rem, cert)) => {
144                        //trace!("Certificate: {:?}",cert);
145                        ca.serial_number = cert.tbs_certificate.raw_serial_as_string().replace(":","").to_uppercase();
146                        ca_json["Properties"]["Certificate Serial Number"] = ca.serial_number.to_owned().to_uppercase().into();
147                        trace!("Certificate Serial Number: {:?}",&ca.serial_number);
148
149                        ca.validity_start = cert.validity().not_before.to_datetime().to_string();
150                        ca_json["Properties"]["Certificate Validity Start"] = ca.validity_start.to_owned().into();
151                        trace!("Certificate Validity Start: {:?}",&ca.validity_start);
152
153                        ca.validity_end = cert.validity().not_after.to_datetime().to_string();
154                        ca_json["Properties"]["Certificate Validity End"] = ca.validity_end.to_owned().into();
155                        trace!("Certificate Validity End: {:?}",&ca.validity_end);
156
157                    },
158                    _ => error!("CA x509 certificate parsing failed: {:?}", res),
159                }
160            }
161            _ => {}
162        }
163    }
164    
165    // Not @ly4k BloodHound version?
166    if old_bloodhound {
167        ca_json["Properties"]["type"] = "Enrollment Service".to_string().into();
168    }
169
170    // Push Certificate Template enable
171    adcs_templates.insert(
172            ca.object_id.to_owned(),
173            ca.enabled_templates.to_owned(),
174    );
175
176    //trace!("CA VALUE: {:?}",ca_json);
177    return ca_json
178}
179
180
181#[derive(Debug)]
182pub struct Template {
183    pub name: String,
184    pub object_id: String,
185    pub enrollment_agent: bool,
186    pub certificate_name_flag: Vec<String>,
187    pub enrollment_flag: Vec<String>,
188    pub private_key_flag: Vec<String>,
189    pub application_policies: Vec<String>,
190    pub extended_key_usage: Vec<String>,
191    pub any_purpose: bool,
192    pub client_authentication: bool,
193    pub requires_manager_approval: bool,
194    pub enrollee_supplies_subject: bool,
195    pub no_security_extension: bool,
196    pub requires_key_archival: bool,
197    pub authorized_signatures_required: u64,
198    pub validity_period: String,
199    pub renewal_period: String,
200    pub domain: String,
201}
202
203impl Template {
204    pub fn new(domain: &String) -> Template {
205        Template {
206            name: String::from("name"),
207            object_id: String::from("object_id"),
208            enrollment_agent: false,
209            certificate_name_flag: Vec::new(),
210            enrollment_flag: Vec::new(),
211            private_key_flag: Vec::new(),
212            application_policies: Vec::new(),
213            extended_key_usage: Vec::new(),
214            any_purpose: false,
215            client_authentication: false,
216            enrollee_supplies_subject: false,
217            requires_manager_approval: false,
218            no_security_extension: false,
219            requires_key_archival: false,
220            authorized_signatures_required: 0,
221            validity_period: String::from("validity_period"),
222            renewal_period: String::from("renewal_period"),
223            domain: String::from(domain.to_uppercase()),
224        }
225    }
226}
227
228/// Function to parse and replace value in json for Certificate template object.
229pub fn parse_adcs_template(
230    result: SearchEntry,
231    domain: &String,
232    old_bloodhound: bool,
233) -> serde_json::value::Value  {
234
235    let result_dn: String;
236    result_dn = result.dn.to_uppercase();
237
238    let result_attrs: HashMap<String, Vec<String>>;
239    result_attrs = result.attrs;
240
241    let result_bin: HashMap<String, Vec<Vec<u8>>>;
242    result_bin = result.bin_attrs;
243
244    let mut template_json = prepare_adcs_template_json_template();
245
246    // Debug for current object
247    debug!("Parse Certificate Template: {}", result_dn);
248    //for (key, value) in &result_attrs {
249    //    trace!("att  {:?}:{:?}", key, value);
250    //}
251    ////trace result bin
252    //for (key, value) in &result_bin {
253    //    trace!("bin  {:?}:{:?}", key, value);
254    //}
255
256    // Prepare struct for this Template
257    let mut template = Template::new(domain);
258
259    // With a check
260    for (key, value) in &result_attrs {
261        match key.as_str() {
262            "name" => {
263                template.name = value[0].to_owned();
264                template_json["Properties"]["name"] = format!("{}@{}",template.name.to_owned().to_uppercase(),template.domain.to_owned()).into();
265                template_json["Properties"]["Template Name"] = template.name.to_owned().into();
266                template_json["Properties"]["domain"] = domain.to_owned().to_uppercase().into();
267            }
268            "displayName" => {
269                template_json["Properties"]["Display Name"] = value[0].to_owned().into();
270            }
271            "msPKI-Certificate-Name-Flag" => {
272                if value.len() != 0 {
273                    template.certificate_name_flag = get_pki_cert_name_flags(
274                        &mut template,
275                        &mut template_json,
276                        value[0].parse::<i64>().unwrap_or(0) as u64
277                    );
278                    template_json["Properties"]["Certificate Name Flag"] = template.certificate_name_flag.to_owned().into();
279                } else {
280                    let mut res: Vec<String> = Vec::new();
281                    res.push("None".to_string());
282                    template.certificate_name_flag = res;
283                    template_json["Properties"]["Certificate Name Flag"] = template.certificate_name_flag.to_owned().into();
284                }
285            }
286            "msPKI-Enrollment-Flag" => {
287                if value.len() != 0 {
288                    template.enrollment_flag = get_pki_enrollment_flags(
289                        &mut template,
290                        &mut template_json,
291                        value[0].parse::<i64>().unwrap_or(0) as u64
292                    );
293                    template_json["Properties"]["Enrollment Flag"] = template.enrollment_flag.to_owned().into();
294                } else {
295                    let mut res: Vec<String> = Vec::new();
296                    res.push("None".to_string());
297                    template.enrollment_flag = res;
298                    template_json["Properties"]["Enrollment Flag"] = template.enrollment_flag.to_owned().into();
299                }
300            }
301            "msPKI-Private-Key-Flag" => {
302                if value.len() != 0 {
303                    template.private_key_flag = get_pki_private_flags(
304                        &mut template,
305                        &mut template_json,
306                        value[0].parse::<i64>().unwrap_or(0) as u64
307                    );
308                    template_json["Properties"]["Private Key Flag"] = template.private_key_flag.to_owned().into();
309                } else {
310                    let mut res: Vec<String> = Vec::new();
311                    res.push("None".to_string());
312                    template.private_key_flag = res;
313                    template_json["Properties"]["Private Key Flag"] = template.private_key_flag.to_owned().into();
314                }
315            }
316            "msPKI-RA-Signature" => {
317                if value.len() != 0 {
318                    template.authorized_signatures_required = value[0].parse::<i64>().unwrap_or(0) as u64;
319                    template_json["Properties"]["Authorized Signatures Required"] = template.authorized_signatures_required.to_owned().into();
320                } else {
321                    template.authorized_signatures_required = 0;
322                    template_json["Properties"]["Authorized Signatures Required"] = template.authorized_signatures_required.to_owned().into();
323                }
324            }
325            "msPKI-RA-Application-Policies" => {
326                // parsed but not use with ly4k BloodHound version
327                if value.len() != 0 {
328                    let application_policies = value;
329                    let mut values = Vec::new();
330                    for oid in application_policies {
331                        if OID_TO_STR_MAP.contains_key(oid){
332                            values.push(OID_TO_STR_MAP.get(oid).unwrap().to_string());
333                        }
334                        continue
335                    }
336                    template.application_policies = values;
337                }
338            }
339            "pKIExtendedKeyUsage" => {
340                if value.len() != 0 {
341                    let eku = value;
342                    let mut values = Vec::new();
343                    for oid in eku {
344                        if OID_TO_STR_MAP.contains_key(oid){
345                            values.push(OID_TO_STR_MAP.get(oid).unwrap().to_string());
346                        }
347                        continue
348                    }
349                    template.extended_key_usage = values;
350                    template_json["Properties"]["Extended Key Usage"] = template.extended_key_usage.to_owned().into();
351                } 
352            }
353            _ => {}
354        }
355    }
356    // For all, bins attributs
357    for (key, value) in &result_bin {
358        match key.as_str() {
359            "objectGUID" => {
360                // objectGUID raw to string
361                template_json["ObjectIdentifier"] = decode_guid(&value[0]).to_owned().into();
362            }
363            "pKIExpirationPeriod" => {
364                template.validity_period = span_to_string(filetime_to_span(value[0].to_owned()));
365                template_json["Properties"]["Validity Period"] = template.validity_period.to_owned().into();
366            }
367            "pKIOverlapPeriod" => {
368                template.renewal_period = span_to_string(filetime_to_span(value[0].to_owned()));
369                template_json["Properties"]["Renewal Period"] = template.renewal_period.to_owned().into();
370            }
371            "nTSecurityDescriptor" => {
372                // Needed with acl
373                let entry_type = "template".to_string();
374                // nTSecurityDescriptor raw to string
375                let relations_ace = parse_ntsecuritydescriptor(
376                    &mut template_json,
377                    &value[0],
378                    entry_type,
379                    &result_attrs,
380                    &result_bin,
381                    &domain,
382                );
383                template_json["Aces"] = relations_ace.into();
384            }
385            _ => {}
386        }
387    }
388
389    // Other values
390    // Any Purpose
391    if template.extended_key_usage.contains(&"Any Purpose".to_string()) || template.extended_key_usage.len() == 0 {
392        template.any_purpose = true;
393        template_json["Properties"]["Any purpose"] = template.any_purpose.to_owned().into();
394    }
395    
396    // Client Authentification
397    let mut isineku = false;
398    for eku in &template.extended_key_usage {
399        if vec!["Client Authentication","Smart Card Logon","PKINIT Client Authentication"].contains(&eku.as_str()) {
400            isineku = true;
401        }
402    }
403    template.client_authentication = template.any_purpose || isineku;
404    template_json["Properties"]["Client Authentication"] = template.client_authentication.to_owned().into();
405
406    // Enrollment Agent
407    let mut isineku = false;
408    for eku in &template.extended_key_usage {
409        if vec!["Certificate Request Agent"].contains(&eku.as_str()) {
410            isineku = true;
411        }
412    }
413    template.enrollment_agent = template.any_purpose || isineku;
414    template_json["Properties"]["Enrollment Agent"] = template.enrollment_agent.to_owned().into();
415
416    // highvalue
417    if template.enrollee_supplies_subject && !template.requires_manager_approval && template.client_authentication {
418        template_json["Properties"]["highvalue"] = true.into();
419    } else if template.enrollment_agent && !template.requires_manager_approval {
420        template_json["Properties"]["highvalue"] = true.into();
421    } else {
422        template_json["Properties"]["highvalue"] = false.into();
423    }
424
425        
426    // Not @ly4k BloodHound version?
427    if old_bloodhound {
428        template_json["Properties"]["type"] = "Certificate Template".to_string().into();
429    }
430    
431    //trace!("TEMPLATE VALUE: {:?}",template_json);
432    return template_json
433}
434
435// OID_TO_STR_MAP with all know guid
436// <https://www.pkisolutions.com/object-identifiers-oid-in-pki/>
437// <https://github.com/ly4k/Certipy/blob/main/certipy/lib/constants.py#L145>
438lazy_static! {
439    static ref OID_TO_STR_MAP: HashMap<String, String> = {
440        let mut map = HashMap::new();
441        map.insert(
442            "1.3.6.1.4.1.311.76.6.1".to_string(),
443            "Windows Update".to_string(),
444        );
445        map.insert(
446            "1.3.6.1.4.1.311.10.3.11".to_string(),
447            "Key Recovery".to_string(),
448        );
449        map.insert(
450            "1.3.6.1.4.1.311.10.3.25".to_string(),
451            "Windows Third Party Application Component".to_string(),
452        );
453        map.insert(
454            "1.3.6.1.4.1.311.21.6".to_string(),
455            "Key Recovery Agent".to_string(),
456        );
457        map.insert(
458            "1.3.6.1.4.1.311.10.3.6".to_string(),
459            "Windows System Component Verification".to_string(),
460        );
461        map.insert(
462            "1.3.6.1.4.1.311.61.4.1".to_string(),
463            "Early Launch Antimalware Drive".to_string(),
464        );
465        map.insert(
466            "1.3.6.1.4.1.311.10.3.23".to_string(),
467            "Windows TCB Component".to_string(),
468        );
469        map.insert(
470            "1.3.6.1.4.1.311.61.1.1".to_string(),
471            "Kernel Mode Code Signing".to_string(),
472        );
473        map.insert(
474            "1.3.6.1.4.1.311.10.3.26".to_string(),
475            "Windows Software Extension Verification".to_string(),
476        );
477        map.insert(
478            "2.23.133.8.3".to_string(),
479            "Attestation Identity Key Certificate".to_string(),
480        );
481        map.insert(
482            "1.3.6.1.4.1.311.76.3.1".to_string(),
483            "Windows Store".to_string(),
484        );
485        map.insert(
486            "1.3.6.1.4.1.311.10.6.1".to_string(),
487            "Key Pack Licenses".to_string(),
488        );
489        map.insert(
490            "1.3.6.1.4.1.311.20.2.2".to_string(),
491            "Smart Card Logon".to_string(),
492        );
493        map.insert(
494            "1.3.6.1.5.2.3.5".to_string(),
495            "KDC Authentication".to_string(),
496        );
497        map.insert(
498            "1.3.6.1.5.5.7.3.7".to_string(),
499            "IP security use".to_string(),
500        );
501        map.insert(
502            "1.3.6.1.4.1.311.10.3.8".to_string(),
503            "Embedded Windows System Component Verification".to_string(),
504        );
505        map.insert(
506            "1.3.6.1.4.1.311.10.3.20".to_string(),
507            "Windows Kits Component".to_string(),
508        );
509        map.insert(
510            "1.3.6.1.5.5.7.3.6".to_string(),
511            "IP security tunnel termination".to_string(),
512        );
513        map.insert(
514            "1.3.6.1.4.1.311.10.3.5".to_string(),
515            "Windows Hardware Driver Verification".to_string(),
516        );
517        map.insert(
518            "1.3.6.1.5.5.8.2.2".to_string(),
519            "IP security IKE intermediate".to_string(),
520        );
521        map.insert(
522            "1.3.6.1.4.1.311.10.3.39".to_string(),
523            "Windows Hardware Driver Extended Verification".to_string(),
524        );
525        map.insert(
526            "1.3.6.1.4.1.311.10.6.2".to_string(),
527            "License Server Verification".to_string(),
528        );
529        map.insert(
530            "1.3.6.1.4.1.311.10.3.5.1".to_string(),
531            "Windows Hardware Driver Attested Verification".to_string(),
532        );
533        map.insert(
534            "1.3.6.1.4.1.311.76.5.1".to_string(),
535            "Dynamic Code Generato".to_string(),
536        );
537        map.insert(
538            "1.3.6.1.5.5.7.3.8".to_string(),
539            "Time Stamping".to_string(),
540        );
541        map.insert(
542            "1.3.6.1.4.1.311.10.3.4.1".to_string(),
543            "File Recovery".to_string(),
544        );
545        map.insert(
546            "1.3.6.1.4.1.311.2.6.1".to_string(),
547            "SpcRelaxedPEMarkerCheck".to_string(),
548        );
549        map.insert(
550            "2.23.133.8.1".to_string(),
551            "Endorsement Key Certificate".to_string(),
552        );
553        map.insert(
554            "1.3.6.1.4.1.311.2.6.2".to_string(),
555            "SpcEncryptedDigestRetryCount".to_string(),
556        );
557        map.insert(
558            "1.3.6.1.4.1.311.10.3.4".to_string(),
559            "Encrypting File System".to_string(),
560        );
561        map.insert(
562            "1.3.6.1.5.5.7.3.1".to_string(),
563            "Server Authentication".to_string(),
564        );
565        map.insert(
566            "1.3.6.1.4.1.311.61.5.1".to_string(),
567            "HAL Extension".to_string(),
568        );
569        map.insert(
570            "1.3.6.1.5.5.7.3.4".to_string(),
571            "Secure Email".to_string(),
572        );
573        map.insert(
574            "1.3.6.1.5.5.7.3.5".to_string(),
575            "IP security end system".to_string(),
576        );
577        map.insert(
578            "1.3.6.1.4.1.311.10.3.9".to_string(),
579            "Root List Signe".to_string(),
580        );
581        map.insert(
582            "1.3.6.1.4.1.311.10.3.30".to_string(),
583            "Disallowed List".to_string(),
584        );
585        map.insert(
586            "1.3.6.1.4.1.311.10.3.19".to_string(),
587            "Revoked List Signe".to_string(),
588        );
589        map.insert(
590            "1.3.6.1.4.1.311.10.3.21".to_string(),
591            "Windows RT Verification".to_string(),
592        );
593        map.insert(
594            "1.3.6.1.4.1.311.10.3.10".to_string(),
595            "Qualified Subordination".to_string(),
596        );
597        map.insert(
598            "1.3.6.1.4.1.311.10.3.12".to_string(),
599            "Document Signing".to_string(),
600        );
601        map.insert(
602            "1.3.6.1.4.1.311.10.3.24".to_string(),
603            "Protected Process Verification".to_string(),
604        );
605        map.insert(
606            "1.3.6.1.4.1.311.80.1".to_string(),
607            "Document Encryption".to_string(),
608        );
609        map.insert(
610            "1.3.6.1.4.1.311.10.3.22".to_string(),
611            "Protected Process Light Verification".to_string(),
612        );
613        map.insert(
614            "1.3.6.1.4.1.311.21.19".to_string(),
615            "Directory Service Email Replication".to_string(),
616        );
617        map.insert(
618            "1.3.6.1.4.1.311.21.5".to_string(),
619            "Private Key Archival".to_string(),
620        );
621        map.insert(
622            "1.3.6.1.4.1.311.10.5.1".to_string(),
623            "Digital Rights".to_string(),
624        );
625        map.insert(
626            "1.3.6.1.4.1.311.10.3.27".to_string(),
627            "Preview Build Signing".to_string(),
628        );
629        map.insert(
630            "1.3.6.1.4.1.311.20.2.1".to_string(),
631            "Certificate Request Agent".to_string(),
632        );
633        map.insert(
634            "2.23.133.8.2".to_string(),
635            "Platform Certificate".to_string(),
636        );
637        map.insert(
638            "1.3.6.1.4.1.311.20.1".to_string(),
639            "CTL Usage".to_string(),
640        );
641        map.insert(
642            "1.3.6.1.5.5.7.3.9".to_string(),
643            "OCSP Signing".to_string(),
644        );
645        map.insert(
646            "1.3.6.1.5.5.7.3.3".to_string(),
647            "Code Signing".to_string(),
648        );
649        map.insert(
650            "1.3.6.1.4.1.311.10.3.1".to_string(),
651            "Microsoft Trust List Signing".to_string(),
652        );
653        map.insert(
654            "1.3.6.1.4.1.311.10.3.2".to_string(),
655            "Microsoft Time Stamping".to_string(),
656        );
657        map.insert(
658            "1.3.6.1.4.1.311.76.8.1".to_string(),
659            "Microsoft Publishe".to_string(),
660        );
661        map.insert(
662            "1.3.6.1.5.5.7.3.2".to_string(),
663            "Client Authentication".to_string(),
664        );
665        map.insert(
666            "1.3.6.1.5.2.3.4".to_string(),
667            "PKIINIT Client Authentication".to_string(),
668        );
669        map.insert(
670            "1.3.6.1.4.1.311.10.3.13".to_string(),
671            "Lifetime Signing".to_string(),
672        );
673        map.insert(
674            "2.5.29.37.0".to_string(),
675            "Any Purpose".to_string(),
676        );
677        map.insert(
678            "1.3.6.1.4.1.311.64.1.1".to_string(),
679            "Server Trust".to_string(),
680        );
681        map.insert(
682            "1.3.6.1.4.1.311.10.3.7".to_string(),
683            "OEM Windows System Component Verification".to_string(),
684        );
685        map
686    };
687}