@@ -228,45 +228,6 @@ fn normalize_wildcard_hostname(hostname: &str) -> &str {
228228 hostname. strip_prefix ( "*." ) . unwrap_or ( hostname)
229229}
230230
231- /// Process Subject Alternative Name (SAN) general names into Python tuples
232- ///
233- /// Converts X.509 GeneralName entries into Python tuple format.
234- /// Returns a vector of PyObjectRef tuples in the format: (type, value)
235- fn process_san_general_names (
236- vm : & VirtualMachine ,
237- general_names : & [ GeneralName < ' _ > ] ,
238- ) -> Vec < PyObjectRef > {
239- general_names
240- . iter ( )
241- . filter_map ( |name| match name {
242- GeneralName :: DNSName ( dns) => Some ( vm. new_tuple ( ( "DNS" , * dns) ) . into ( ) ) ,
243- GeneralName :: IPAddress ( ip) => {
244- let ip_str = format_ip_address ( ip) ;
245- Some ( vm. new_tuple ( ( "IP Address" , ip_str) ) . into ( ) )
246- }
247- GeneralName :: RFC822Name ( email) => Some ( vm. new_tuple ( ( "email" , * email) ) . into ( ) ) ,
248- GeneralName :: URI ( uri) => Some ( vm. new_tuple ( ( "URI" , * uri) ) . into ( ) ) ,
249- GeneralName :: DirectoryName ( dn) => {
250- let dn_str = format ! ( "{dn}" ) ;
251- Some ( vm. new_tuple ( ( "DirName" , dn_str) ) . into ( ) )
252- }
253- GeneralName :: RegisteredID ( oid) => {
254- let oid_str = oid. to_string ( ) ;
255- Some ( vm. new_tuple ( ( "Registered ID" , oid_str) ) . into ( ) )
256- }
257- GeneralName :: OtherName ( oid, value) => {
258- let oid_str = oid. to_string ( ) ;
259- let value_str = format ! ( "{value:?}" ) ;
260- Some (
261- vm. new_tuple ( ( "othername" , format ! ( "{oid_str}:{value_str}" ) ) )
262- . into ( ) ,
263- )
264- }
265- _ => None ,
266- } )
267- . collect ( )
268- }
269-
270231// Certificate Validation and Parsing
271232
272233/// Check if a certificate is a CA certificate by examining the Basic Constraints extension
@@ -294,87 +255,10 @@ pub(super) fn is_ca_certificate(cert_der: &[u8]) -> bool {
294255 cert. version ( ) . 0 == 0 && cert. subject ( ) == cert. issuer ( )
295256}
296257
297- /// Convert an X509Name to Python nested tuple format for SSL certificate dicts
298- ///
299- /// Format: ((('CN', 'example.com'),), (('O', 'Example Org'),), ...)
300- fn name_to_py ( vm : & VirtualMachine , name : & x509_parser:: x509:: X509Name < ' _ > ) -> PyObjectRef {
301- let list = name
302- . iter ( )
303- . flat_map ( |rdn| {
304- // Each RDN can have multiple attributes
305- rdn. iter ( )
306- . map ( |attr| {
307- let oid_str = attr. attr_type ( ) . to_id_string ( ) ;
308- let value_str = attr. attr_value ( ) . as_str ( ) . unwrap_or ( "" ) . to_string ( ) ;
309- let key = oid_to_attribute_name ( & oid_str) ;
310-
311- vm. new_tuple ( ( vm. new_tuple ( ( vm. ctx . new_str ( key) , vm. ctx . new_str ( value_str) ) ) , ) )
312- . into ( )
313- } )
314- . collect :: < Vec < _ > > ( )
315- } )
316- . collect :: < Vec < PyObjectRef > > ( ) ;
317-
318- vm. ctx . new_tuple ( list) . into ( )
319- }
320-
321- /// Convert DER-encoded certificate to Python dict (for getpeercert with binary_form=False)
322- ///
323- /// Returns a dict with fields: subject, issuer, version, serialNumber,
324- /// notBefore, notAfter, subjectAltName (if present)
325- pub ( super ) fn cert_to_dict (
326- vm : & VirtualMachine ,
327- cert : & x509_parser:: certificate:: X509Certificate < ' _ > ,
328- ) -> PyResult {
329- let dict = vm. ctx . new_dict ( ) ;
330-
331- // Subject and Issuer
332- dict. set_item ( "subject" , name_to_py ( vm, cert. subject ( ) ) , vm) ?;
333- dict. set_item ( "issuer" , name_to_py ( vm, cert. issuer ( ) ) , vm) ?;
334-
335- // Version (X.509 v3 = version 2 in the cert, but Python uses 3)
336- dict. set_item (
337- "version" ,
338- vm. ctx . new_int ( cert. version ( ) . 0 as i32 + 1 ) . into ( ) ,
339- vm,
340- ) ?;
341-
342- // Serial number - hex format with even length
343- let serial = format_serial_number ( & cert. serial ) ;
344- dict. set_item ( "serialNumber" , vm. ctx . new_str ( serial) . into ( ) , vm) ?;
345-
346- // Validity dates - format with GMT using jiff
347- dict. set_item (
348- "notBefore" ,
349- vm. ctx
350- . new_str ( format_asn1_time ( & cert. validity ( ) . not_before ) )
351- . into ( ) ,
352- vm,
353- ) ?;
354- dict. set_item (
355- "notAfter" ,
356- vm. ctx
357- . new_str ( format_asn1_time ( & cert. validity ( ) . not_after ) )
358- . into ( ) ,
359- vm,
360- ) ?;
361-
362- // Subject Alternative Names (if present)
363- if let Ok ( Some ( san_ext) ) = cert. subject_alternative_name ( ) {
364- let san_list = process_san_general_names ( vm, & san_ext. value . general_names ) ;
365-
366- if !san_list. is_empty ( ) {
367- dict. set_item ( "subjectAltName" , vm. ctx . new_tuple ( san_list) . into ( ) , vm) ?;
368- }
369- }
370-
371- Ok ( dict. into ( ) )
372- }
373-
374- /// Convert DER-encoded certificate to Python dict (for get_ca_certs)
258+ /// Convert DER-encoded certificate to Python dict.
375259///
376- /// Similar to cert_to_dict but includes additional fields like crlDistributionPoints
377- /// and uses CPython's specific ordering : issuer, notAfter, notBefore, serialNumber, subject, version
260+ /// Includes OCSP, caIssuers, and crlDistributionPoints when present, and uses
261+ /// the field order : issuer, notAfter, notBefore, serialNumber, subject, version
378262pub ( super ) fn cert_der_to_dict_helper (
379263 vm : & VirtualMachine ,
380264 cert_der : & [ u8 ] ,
0 commit comments