bac@s<dZddlZddlZddlZddlZddlZddlZddlZddlZddl m Z m Z m Z ej dejZdZdZdZd Zd Zdd Zd Zd ZdZdZdZdZidd6dd6dd6dd6dd6ZdZdS( s 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. iNi(tCFConsttCoreFoundationtSecuritys;-----BEGIN CERTIFICATE----- (.*?) -----END CERTIFICATE-----cCstjtj|t|S(sv Given a bytestring, create a CFData object from it. This CFData object must be CFReleased by the caller. (Rt CFDataCreatetkCFAllocatorDefaulttlen(t bytestring((sK/usr/lib/fence-agents/bundled/urllib3/contrib/_securetransport/low_level.pyt_cf_data_from_bytesscCswt|}d|D}d|D}tj||}tj||}tjtj|||tjtjS(sK Given a list of Python tuples, create an associated CFDictionary. css|]}|dVqdS(iN((t.0tt((sK/usr/lib/fence-agents/bundled/urllib3/contrib/_securetransport/low_level.pys ,scss|]}|dVqdS(iN((RR ((sK/usr/lib/fence-agents/bundled/urllib3/contrib/_securetransport/low_level.pys -s(RRt CFTypeReftCFDictionaryCreateRtkCFTypeDictionaryKeyCallBackstkCFTypeDictionaryValueCallBacks(ttuplestdictionary_sizetkeystvaluestcf_keyst cf_values((sK/usr/lib/fence-agents/bundled/urllib3/contrib/_securetransport/low_level.pyt_cf_dictionary_from_tuples%s cCs.tj|}tjtj|tj}|S(si Given a Python binary data, create a CFString. The string must be CFReleased by the caller. (tctypestc_char_pRtCFStringCreateWithCStringRRtkCFStringEncodingUTF8(tpy_bstrtc_strtcf_str((sK/usr/lib/fence-agents/bundled/urllib3/contrib/_securetransport/low_level.pyt_cfstr;s  cCsd}ytjtjdtjtj}|sBtdnxT|D]L}t|}|sptdnztj ||Wdtj |XqIWWn?t k r}|rtj |nt j d|fnX|S(s 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. isUnable to allocate memory!NsUnable to allocate array: %s(tNoneRtCFArrayCreateMutableRRtbyreftkCFTypeArrayCallBackst MemoryErrorRtCFArrayAppendValuet CFReleaset BaseExceptiontssltSSLError(tlsttcf_arrtitemRte((sK/usr/lib/fence-agents/bundled/urllib3/contrib/_securetransport/low_level.pyt_create_cfstring_arrayIs(  cCstj|tjtj}tj|tj}|dkrtj d}tj ||dtj}|s~t dn|j }n|dk r|j d}n|S(s 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. is'Error copying C string from CFStringRefsutf-8N(RtcasttPOINTERtc_void_pRtCFStringGetCStringPtrRRRtcreate_string_buffertCFStringGetCStringtOSErrortvaluetdecode(R3tvalue_as_void_ptstringtbuffertresult((sK/usr/lib/fence-agents/bundled/urllib3/contrib/_securetransport/low_level.pyt_cf_string_to_unicodehs   cCs|dkrdStj|d}t|}tj||dksS|dkr`d|}n|dkrxtj}n||dS(s[ Checks the return code and throws an exception if there is an error to report iNuu OSStatus %s(RtSecCopyErrorMessageStringRR9RR#R%R&(terrortexception_classtcf_error_stringtoutput((sK/usr/lib/fence-agents/bundled/urllib3/contrib/_securetransport/low_level.pyt_assert_no_errors      cCsR|jdd}gtj|D]}tj|jd^q"}|s^tjdntj tj dt j tj }|stjdnyx|D]}t|}|stjdntjtj |}tj||stjdntj||tj|qWWn!tk rMtj|nX|S(s 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 s isNo root certificates specifiedisUnable to allocate memory!sUnable to build cert object!(treplacet _PEM_CERTS_REtfinditertbase64t b64decodetgroupR%R&RRRRRR RRtSecCertificateCreateWithDataR#R"t Exception(t pem_bundletmatcht der_certst cert_arrayt der_bytestcertdatatcert((sK/usr/lib/fence-agents/bundled/urllib3/contrib/_securetransport/low_level.pyt_cert_array_from_pems44     cCstj}tj||kS(s= Returns True if a given CFTypeRef is a certificate. (RtSecCertificateGetTypeIDRt CFGetTypeID(R)texpected((sK/usr/lib/fence-agents/bundled/urllib3/contrib/_securetransport/low_level.pyt_is_certs cCstj}tj||kS(s; Returns True if a given CFTypeRef is an identity. (RtSecIdentityGetTypeIDRRQ(R)RR((sK/usr/lib/fence-agents/bundled/urllib3/contrib/_securetransport/low_level.pyt _is_identitys cCstjd}tj|d jd}tj|d}tj}tjj||j d}t j }t j |t ||tdtj|}t|||fS(s 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. i(isutf-8N(tosturandomRCt b16encodeR4ttempfiletmkdtemptpathtjointencodeRtSecKeychainReftSecKeychainCreateRtFalseRRRR?(t random_bytestfilenametpasswordt tempdirectoryt keychain_pathtkeychaintstatus((sK/usr/lib/fence-agents/bundled/urllib3/contrib/_securetransport/low_level.pyt_temporary_keychains  ' c Cskg}g}d}t|d}|j}WdQXztjtj|t|}tj}tj |ddddd|t j |}t |tj |} xt| D]} tj|| } t j| tj} t| r tj| |j| qt| rtj| |j| qqWWd|rStj|ntj|X||fS(s 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. trbNi(RtopentreadRRRRt CFArrayRefRt SecItemImportRRR?tCFArrayGetCounttrangetCFArrayGetValueAtIndexR,R RStCFRetaintappendRUR#( RfR[t certificatest identitiest result_arraytft raw_filedatatfiledataR8t result_counttindexR)((sK/usr/lib/fence-agents/bundled/urllib3/contrib/_securetransport/low_level.pyt_load_items_from_filesB      c GsKg}g}d|D}zx=|D]5}t||\}}|j||j|q&W|stj}tj||dtj|}t||j|t j |j dnt j t j dtjt j} x*tj||D]} t j| | qW| SWdx'tj||D]} t j | q/WXdS(s 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. css|]}|r|VqdS(N((RR[((sK/usr/lib/fence-agents/bundled/urllib3/contrib/_securetransport/low_level.pys RsiN(R{textendRtSecIdentityReft SecIdentityCreateWithCertificateRRR?RrRR#tpopRRR t itertoolstchainR"( RftpathsRsRtt file_pathtnew_identitiest new_certst new_identityRgt trust_chainR)tobj((sK/usr/lib/fence-agents/bundled/urllib3/contrib/_securetransport/low_level.pyt_load_client_cert_chain.s0      iitSSLv2itSSLv3tTLSv1sTLSv1.1sTLSv1.2c Csft|\}}d}d}tjd||}t|}d}tjd|||||}|S(s6 Builds a TLS alert record for an unknown CA. ii0s>BBis>BBBH(tTLS_PROTOCOL_VERSIONStstructtpackR( tversiontver_majtver_mintseverity_fataltdescription_unknown_catmsgtmsg_lentrecord_type_alerttrecord((sK/usr/lib/fence-agents/bundled/urllib3/contrib/_securetransport/low_level.pyt_build_tls_unknown_ca_alerts (ii(ii(ii(ii(ii(t__doc__RCRRRVtreR%RRYtbindingsRRRtcompiletDOTALLRARRRR+R9RR?RORSRURhR{RRR(((sK/usr/lib/fence-agents/bundled/urllib3/contrib/_securetransport/low_level.pyt s<              .   # 7 K