
    S9i\?                    t   d Z ddlmZ ddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlmZmZmZmZmZmZmZmZmZmZ  ej.                  dej0                        ZddZ	 	 	 	 ddZdd	Zdd
Zd dZ	 d!	 	 	 	 	 d"dZd#dZ d$dZ!d$dZ"d%dZ#	 	 	 	 	 	 d&dZ$d'dZ%ddddddZ&d(dZ' G d d      Z(y))a  
Low-level helpers for the SecureTransport bindings.

These are Python functions that are not directly related to the high-level APIs
but are necessary to get them to work. They include a whole bunch of low-level
CoreFoundation messing about and memory management. The concerns in this module
are almost entirely about trying to avoid memory leaks and providing
appropriate and useful assistance to the higher-level code.
    )annotationsN   )
CFArrayCFConstCFDataCFDictionaryCFMutableArrayCFString	CFTypeRefCoreFoundationSecKeychainRefSecuritys;   -----BEGIN CERTIFICATE-----
(.*?)
-----END CERTIFICATE-----c                ^    t        j                  t         j                  | t        |             S )zv
    Given a bytestring, create a CFData object from it. This CFData object must
    be CFReleased by the caller.
    )r   CFDataCreatekCFAllocatorDefaultlen)
bytestrings    L/usr/lib/python3/dist-packages/urllib3/contrib/_securetransport/low_level.py_cf_data_from_bytesr   )   s(    
 &&**JJ     c                   t        |       }d | D        }d | D        }t        j                  |z  | }t        j                  |z  | }t        j                  t        j                  |||t        j
                  t        j                        S )zK
    Given a list of Python tuples, create an associated CFDictionary.
    c              3  &   K   | ]	  }|d      yw)r   N .0ts     r   	<genexpr>z-_cf_dictionary_from_tuples.<locals>.<genexpr><   s     !QAaD!   c              3  &   K   | ]	  }|d      yw)r   Nr   r   s     r   r   z-_cf_dictionary_from_tuples.<locals>.<genexpr>=   s     #qad#r   )r   r   r   CFDictionaryCreater   kCFTypeDictionaryKeyCallBackskCFTypeDictionaryValueCallBacks)tuplesdictionary_sizekeysvaluescf_keys	cf_valuess         r   _cf_dictionary_from_tuplesr)   3   s     &kO "&!D#F#F''/9DAG))O;fEI,,**4466 r   c                    t        j                  |       }t        j                  t        j                  |t
        j                        }|S )zi
    Given a Python binary data, create a CFString.
    The string must be CFReleased by the caller.
    )ctypesc_char_pr   CFStringCreateWithCStringr   r   kCFStringEncodingUTF8)py_bstrc_strcf_strs      r   _cfstrr2   K   s>    
 OOG$E55**%%F
 Mr   c                    d}	 t        j                  t         j                  dt        j                  t         j
                              }|st        d      | D ]F  }t        |      }|st        d      	 t        j                  ||       t        j                  |       H 	 |S # t        j                  |       w xY w# t        $ r5}|rt        j                  |       t        j                  d|       dd}~ww xY w)z
    Given a list of Python binary data, create an associated CFMutableArray.
    The array must be CFReleased by the caller.

    Raises an ssl.SSLError on failure.
    Nr   Unable to allocate memory!zUnable to allocate array: )r   CFArrayCreateMutabler   r+   byrefkCFTypeArrayCallBacksMemoryErrorr2   CFArrayAppendValue	CFReleaseBaseExceptionsslSSLError)lstcf_arritemr1   es        r   _create_cfstring_arrayrB   Y   s     FG44..LL==>

 :;; 	1DD\F!">??111&&A((0	1 M ((0 G$$V,ll7s;<$FGs0   A0B? 5B%B? %B<<B? ?	C=0C88C=c                   t        j                  | t        j                  t         j                              }t	        j
                  |t        j                        }|Tt        j                  d      }t	        j                  ||dt        j                        }|st        d      |j                  }||j                  d      }|S )z
    Creates a Unicode string from a CFString object. Used entirely for error
    reporting.

    Yes, it annoys me quite a lot that this function is this complex.
    i   z'Error copying C string from CFStringRefutf-8)r+   castPOINTERc_void_pr   CFStringGetCStringPtrr   r.   create_string_bufferCFStringGetCStringOSErrorvaluedecode)rL   value_as_void_pstringbufferresults        r   _cf_string_to_unicoderR   x   s     kk%)HIO1166F ~,,T222VT7+H+H
 CDDw'Mr   c                    | dk(  ryt        j                  | d      }t        |      }t        j                  |       ||dk(  rd|  }|t
        j                  } ||      )z[
    Checks the return code and throws an exception if there is an error to
    report
    r   N z	OSStatus )r   SecCopyErrorMessageStringrR   r   r:   r<   r=   )errorexception_classcf_error_stringoutputs       r   _assert_no_errorrZ      si     z88EO"?3F_-~2UG$,,
&
!!r   c                6   | j                  dd      } t        j                  |       D cg c]&  }t        j                  |j                  d            ( }}|st        j                  d      t        j                  t        j                  dt        j                  t        j                              }|st        j                  d      	 |D ]  }t        |      }|st        j                  d      t        j                   t        j                  |      }t        j"                  |       |st        j                  d      t        j$                  ||       t        j"                  |        	 |S c c}w # t&        $ r t        j"                  |        w xY w)z
    Given a bundle of certs in PEM format, turns them into a CFArray of certs
    that can be used to validate a cert chain.
    s   
   
r   zNo root certificates specifiedr   r4   zUnable to build cert object!)replace_PEM_CERTS_REfinditerbase64	b64decodegroupr<   r=   r   r5   r   r+   r6   r7   r   r   SecCertificateCreateWithDatar:   r9   	Exception)
pem_bundlematch	der_certs
cert_array	der_bytescertdatacerts          r   _cert_array_from_pemrl      sh    ##GU3J 7D6L6LZ6X-2Q(I  ll;<<44**	^99:J
 ll788" 	+I*95Hll#?@@8822HD $$X.ll#ABB--j$?$$T*	+( G8   	  ,s   +E3B$E8 8 Fc                Z    t        j                         }t        j                  |       |k(  S )z=
    Returns True if a given CFTypeRef is a certificate.
    )r   SecCertificateGetTypeIDr   CFGetTypeIDr@   expecteds     r   _is_certrr      s(     //1H%%d+x77r   c                Z    t        j                         }t        j                  |       |k(  S )z;
    Returns True if a given CFTypeRef is an identity.
    )r   SecIdentityGetTypeIDr   ro   rp   s     r   _is_identityru      s(     ,,.H%%d+x77r   c            
        t        j                  d      } t        j                  | dd       j	                  d      }t        j                  | dd       }t        j                         }t         j                  j                  ||      j                  d      }t        j                         }t        j                  |t        |      |ddt        j                  |            }t!        |       ||fS )a  
    This function creates a temporary Mac keychain that we can use to work with
    credentials. This keychain uses a one-time password and a temporary file to
    store the data. We expect to have one keychain per socket. The returned
    SecKeychainRef must be freed by the caller, including calling
    SecKeychainDelete.

    Returns a tuple of the SecKeychainRef and the path to the temporary
    directory that contains it.
    (   N   rD   F)osurandomr`   	b16encoderM   tempfilemkdtemppathjoinencoder   r   SecKeychainCreater   r+   r6   rZ   )random_bytesfilenamepasswordtempdirectorykeychain_pathkeychainstatuss          r   _temporary_keychainr      s    " ::b>LRa 0188AHQR 01H$$&MGGLL9@@IM &&(H''s8}htV\\(=SF V ]""r   c                   g }g }d}t        |d      5 }|j                         }ddd       	 t        j                  t        j                  t        |            }t        j                         }t        j                  |ddddd| t        j                  |            }t        |       t        j                  |      }	t        |	      D ]  }
t        j                  ||
      }t        j                  |t        j                         }t#        |      r't        j$                  |       |j'                  |       ot)        |      s{t        j$                  |       |j'                  |        	 |rt        j*                  |       t        j*                  |       ||fS # 1 sw Y   {xY w# |rt        j*                  |       t        j*                         w xY w)z
    Given a single file, loads all the trust objects from it into arrays and
    the keychain.
    Returns a tuple of lists: the first list is a list of identities, the
    second a list of certs.
    Nrbr   )openreadr   r   r   r   
CFArrayRefr   SecItemImportr+   r6   rZ   CFArrayGetCountrangeCFArrayGetValueAtIndexrE   r   rr   CFRetainappendru   r:   )r   r~   certificates
identitiesresult_arrayfraw_filedatafiledatarQ   result_countindexr@   s               r   _load_items_from_filer   	  s    LJL	dD	  Qvvx $+!....c,>O
 &002''LL&	
 	  &55lC<( 		(E!88uMD;;t^%=%=>D~''-##D)d#''-!!$'		( $$\2  *%%S   H $$\2  *s   FDF* (F* F'*.Gc                P   g }g }d |D        }	 |D ]3  }t        | |      \  }}|j                  |       |j                  |       5 |st        j                         }t        j                  | |d   t        j                  |            }	t        |	       |j                  |       t        j                  |j                  d             t        j                  t        j                  dt        j                  t        j                              }
t        j                   ||      D ]  }t        j"                  |
|        |
t        j                   ||      D ]  }t        j                  |        S # t        j                   ||      D ]  }t        j                  |        w xY w)z
    Load certificates and maybe keys from a number of files. Has the end goal
    of returning a CFArray containing one SecIdentityRef, and then zero or more
    SecCertificateRef objects, suitable for use as a client certificate trust
    chain.
    c              3  &   K   | ]	  }|s|  y wNr   )r   r~   s     r   r   z*_load_client_cert_chain.<locals>.<genexpr>f  s     5td5s   r   )r   extendr   SecIdentityRef SecIdentityCreateWithCertificater+   r6   rZ   r   r   r:   popr5   r   r7   	itertoolschainr9   )r   pathsr   r   filtered_paths	file_pathnew_identities	new_certsnew_identityr   trust_chainr@   objs                r   _load_client_cert_chainr   B  s|   @ LJ 6u5N"*' 	+I(=h	(R%NIn-	*	+ #224L>>,q/6<<+EF V$l+ $$\%5%5a%89 %99..LL==>

 OOJ= 	AD --k4@	A
 ??:|< 	*C$$S)	*9??:|< 	*C$$S)	*s   D3E3 32F%)r      )   r   )r   r   )r   r   )r   r   )SSLv2SSLv3TLSv1zTLSv1.1zTLSv1.2c                    t         |    \  }}d}d}t        j                  d||      }t        |      }d}t        j                  d||||      |z   }|S )z6
    Builds a TLS alert record for an unknown CA.
    r   0   z>BB   z>BBBH)TLS_PROTOCOL_VERSIONSstructpackr   )	versionver_majver_minseverity_fataldescription_unknown_camsgmsg_lenrecord_type_alertrecords	            r   _build_tls_unknown_ca_alertr     sb     -W5GWN!
++e^-C
DC#hG[["3WgwORUUFMr   c                      e Zd ZdZdZdZdZdZdZdZ	dZ
d	ZdZdZdZdZdZd
ZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZ dZ!dZ"dZ#dZ$dZ%dZ&dZ'dZ(d Z)d!Z*d"Z+y#)$SecurityConstzU
    A class object that acts as essentially a namespace for Security constants.
    r   r   r         rx   
   i  r         iiiiiiiiiiiiiiiiiii iQi,iRN),__name__
__module____qualname____doc__"kSSLSessionOptionBreakOnServerAuthkSSLProtocol2kSSLProtocol3kTLSProtocol1kTLSProtocol11kTLSProtocol12kTLSProtocol13kTLSProtocolMaxSupportedkSSLClientSidekSSLStreamTypekSecFormatPEMSequencekSecTrustResultInvalidkSecTrustResultProceedkSecTrustResultDenykSecTrustResultUnspecified&kSecTrustResultRecoverableTrustFailure kSecTrustResultFatalTrustFailurekSecTrustResultOtherErrorerrSSLProtocolerrSSLWouldBlockerrSSLClosedGracefulerrSSLClosedNoNotifyerrSSLClosedAborterrSSLXCertChainInvaliderrSSLCryptoerrSSLInternalerrSSLCertExpirederrSSLCertNotYetValiderrSSLUnknownRootCerterrSSLNoRootCerterrSSLHostNameMismatcherrSSLPeerHandshakeFailerrSSLPeerUserCancellederrSSLWeakPeerEphemeralDHKeyerrSSLServerAuthCompletederrSSLRecordOverflowerrSecVerifyFailederrSecNoTrustSettingserrSecItemNotFounderrSecInvalidTrustSettingsr   r   r   r   r     s     *+&MMMNNN"NN !"-.*'($ !N  #LN!!"###(  % "!'r   r   )r   bytesreturnr   )r#   z#list[tuple[typing.Any, typing.Any]]r   r   )r/   r   r   r
   )r>   zlist[bytes]r   r	   )rL   r
   r   
str | Noner   )rV   intrW   ztype[BaseException] | Noner   None)re   r   r   r   )r@   r   r   bool)r   ztuple[SecKeychainRef, str])r   r   r~   strr   z'tuple[list[CFTypeRef], list[CFTypeRef]])r   r   r   r   r   r   )r   r   r   r   ))r   
__future__r   r`   r+   r   ry   rer<   r   r|   typingbindingsr   r   r   r   r	   r
   r   r   r   r   compileDOTALLr^   r   r)   r2   rB   rR   rZ   rl   rr   ru   r   r   r   r   r   r   r   r   r   <module>r     s   #    	 	 
      

Dbii
/0>4 ?C""!;"	".+\88 #F6&6&$'6&,6&rH*X  6( 6(r   