PNG  IHDR;IDATxܻn0K )(pA 7LeG{ §㻢|ذaÆ 6lذaÆ 6lذaÆ 6lom$^yذag5bÆ 6lذaÆ 6lذa{ 6lذaÆ `}HFkm,mӪôô! x|'ܢ˟;E:9&ᶒ}{v]n&6 h_tڠ͵-ҫZ;Z$.Pkž)!o>}leQfJTu іچ\X=8Rن4`Vwl>nG^is"ms$ui?wbs[m6K4O.4%/bC%t Mז -lG6mrz2s%9s@-k9=)kB5\+͂Zsٲ Rn~GRC wIcIn7jJhۛNCS|j08yiHKֶۛkɈ+;SzL/F*\Ԕ#"5m2[S=gnaPeғL lذaÆ 6l^ḵaÆ 6lذaÆ 6lذa; _ذaÆ 6lذaÆ 6lذaÆ RIENDB`  #^c@@sdZddlmZmZddlZddlZddlZddlZddlZddl Z ddl Z ddl Z ddl Z ddl Z ddlZddlZddlZddlZddl mZmZddlmZddlmZddlmZddlZyddlmZWn!ek rMddlmZnXdd lm Z m!Z!dd l"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(dd l)m*Z*dd l+m,Z,dd l-m.Z.ddl/m0Z0m1Z1ddl2m3Z3ddl2m4Z4ddl5m6Z6e j7d|kr&ddl8Z8ndZ8ej:r>e;Z<ndZ=dZ>ej?e@ZAdZBdZCdZDdZEdZFdZGdZHdZIdZJdZKd ZLejMdddde'e(d!ZNeOeOd"ZPeOeOd#eOd$ZQd%ZRd&ZSeTeOeOd'ZUd(ZVd)ZWd*ZXd+ZYd,ZZd-Z[d.Z\ej]d/ej^Z_idd36dd46dd56dd76dd86dd:6dd;6dd<6dd=6dd>6dd?6dd@6ddA6ddB6d2dC6d2dD6d2dE6dFdG6dFdH6dFdI6dFdJ6Z`dKZaddOZbddQZcidRe3jd6dSe3je6ZfdTZgdUZhdVZidWZjdXekfdYYZldZelfd[YZmd\elfd]YZnd^elfd_YZod`elfdaYZpdbZqdeOeOeOdcddZrdcdeZsdcdfZtdcdgZudcdhZvdiZwdjZxdkZydlezfdmYZ{dnZ|doZ}ddpZ~dqZdrZdsZdtZdduZdvZdwZdFdxZdyZe8dk r dze8jfd{YZejZneZdS(s Various utility functions. i(tabsolute_importtprint_functionN(tresolvert rdatatype(t DNSException(tNXDOMAIN(tAddrFormatError(tHTTPSConnection(terrorstmessages(tDOMAIN_LEVEL_0t TLS_VERSIONStTLS_VERSION_MINIMALtTLS_HIGH_CIPHERStTLS_VERSION_DEFAULT_MINtTLS_VERSION_DEFAULT_MAX(t_(tpaths(t SSHPublicKey(tDNtRDN(tDNSName(tresolve_ip_addresses(t ScriptErroriis/var/lib/ipa-client/sysrestores/etc/ipa/default.confcC@st|ttfr2g|D]}t|^qSt|trUd|jDSt|tttt dt j fr|St|t r|jdSt|tjtfrt |Stt|ddsdSt|jS(NcS@s%i|]\}}t||qS((tjson_serialize(t.0tktv((s//usr/lib/python2.7/site-packages/ipalib/util.pys Xs sutf-8t__json__t(t isinstancetlistttupleRtdicttitemstbooltfloattunicodettypetNonetsixt integer_typeststrtdecodetdecimaltDecimalRtcallabletgetattrR(tobjto((s//usr/lib/python2.7/site-packages/ipalib/util.pyRTs'  cC@sWy%t|s$tjd|nWn+tjjk rR}tjd|nXdS(Nthostnamet exception(RRtDNSNotARecordErrortdnsR3RtDNSResolverError(tfqdntex((s//usr/lib/python2.7/site-packages/ipalib/util.pytverify_host_resolvablees  cC@sxytj|tjt}Wntk r6t}nXytj|tjt}Wntk rmt}nX|pw|S(sX Checks to see if given domain has SOA or NS record. Returns True or False. (RtqueryRtSOAtTrueRtFalsetNS(tdomaintsoa_record_foundtns_record_found((s//usr/lib/python2.7/site-packages/ipalib/util.pythas_soa_or_ns_recordns      cC@st}|jd}t|dkrat|dj|dscs@s|]}d|VqdS(s'%s'N((RR((s//usr/lib/python2.7/site-packages/ipalib/util.pys ss\only letters, numbers, %(chars)s are allowed. DNS label may not start or end with %(chars2)stcharstchars2( R!RMtcompilet IGNORECASEtVERBOSERyRRGRNRL( t dns_labeltallow_underscoret allow_slasht base_charst extra_charst middle_charst label_regextregexRR((s//usr/lib/python2.7/site-packages/ipalib/util.pytvalidate_dns_labelrs&    R?cC@s|jdr|d }n|jd}|rat|dkrattdj|nx|D]}t|||qhWdS(NRniis"single label {}s are not supported(tendswithRFRGRyRRzR(t domain_nameRRtentityt check_sldtlabel((s//usr/lib/python2.7/site-packages/ipalib/util.pytvalidate_domain_names  cC@sGt|tsttd|jDrCttdndS(Ncs@s|]}d|kVqdS(RCN((RR((s//usr/lib/python2.7/site-packages/ipalib/util.pys sstoo many '@' characters(RRtAssertionErrortanytlabelsRyR(Rr((s//usr/lib/python2.7/site-packages/ipalib/util.pytvalidate_zonemgrscC@s,t|}t|t|}t|S(N(Rttvalidate_idna_domainRR(Rr((s//usr/lib/python2.7/site-packages/ipalib/util.pytvalidate_zonemgr_strs   cC@st|dkr'ttdn|jdrC|d }nd|krdttdnd|kr|rttdnt|||nt|||dS( su See RFC 952, 1123 :param hostname Checked value :param check_fqdn Check if hostname is fully qualified is$cannot be longer that 255 charactersRnis..s0hostname contains empty label (consecutive dots)snot fully qualifiedN(RGRyRRRR(R2t check_fqdnRR((s//usr/lib/python2.7/site-packages/ipalib/util.pytvalidate_hostnames   cC@st|jS(N(Rtopenssh(tvalue((s//usr/lib/python2.7/site-packages/ipalib/util.pytnormalize_sshpubkeyscC@s7yt|Wnttfk r.tdSXdSdS(Nsinvalid SSH public key(RRytUnicodeDecodeErrorRR'(tugettextR((s//usr/lib/python2.7/site-packages/ipalib/util.pytvalidate_sshpubkeys  cC@sOyt|}Wnttfk r0tdSX|jrGtdSdSdS(Nsinvalid SSH public keysoptions are not allowed(RRyRRt has_optionsR'(RRtpubkey((s//usr/lib/python2.7/site-packages/ipalib/util.pytvalidate_sshpubkey_no_optionss   cC@s|jd}|sdSg}g}x|D]}yt|}Wnttfk r^q,nX|j}|j}|rd||f}nd||jf}|j|j|j|q,Wd|kr|pd|dtk r]}t|td|d|d|d|nXy#t||d|dtd|Wn>tk r}t|td|d|d|d|nXdS( s Validate if forwarder supports EDNS0 :raise UnresolvableRecordError: record cannot be resolved :raise EDNS0UnsupportedError: EDNS0 is not supported by forwarder RCRGRARBR RZRDN(RIRR7R1R<R2(RARBtip_addrRGRU((s//usr/lib/python2.7/site-packages/ipalib/util.pyt_validate_edns0_forwarders    c C@st|}d}d}t|||d|y%t||d|dtd|}Wn8tk r}t|td|d|d|nXy>|jj|jj t j j t j jt jjt jjWn,tk rtd|d|d|nXd S( sETest DNS forwarder properties. against root zone. Global forwarders should be able return signed root zone :raise UnresolvableRecordError: record cannot be resolved :raise EDNS0UnsupportedError: EDNS0 is not supported by forwarder :raise DNSSECSignatureMissingError: did not receive RRSIG for root zone RnR;RGRCRERARBR N(R*RKRIR<RR7R3R5t find_rrsettanswerR5RDtroott rdataclasstINRtRRSIGR;tKeyError(RJRGRARBtansRU((s//usr/lib/python2.7/site-packages/ipalib/util.pyt validate_dnssec_global_forwarder0s     cC@st|d|d|dS(s Only forwarders in forward zones can be validated in this way :raise UnresolvableRecordError: record cannot be resolved :raise EDNS0UnsupportedError: ENDS0 is not supported by forwarder R;RGN(RK(RJtfwzoneRG((s//usr/lib/python2.7/site-packages/ipalib/util.pyt$validate_dnssec_zone_forwarder_step1Qsc C@s\d}y1t||d|dtdtdtd|}Wnutk rq}t|td|d|d |n>tk r}t|td|d|d |d |nXy+t||d|dtdtd|}Wn8tk r}t|td|d|d |nDX|j|jkr=|j|jkr=d Std|d|d |d S( s This step must be executed after forwarders are added into LDAP, and only when we are sure the forwarders work. Query will be send to IPA DNS server, to verify if reply passed, or DNSSEC validation failed. Only forwarders in forward zones can be validated in this way :raise UnresolvableRecordError: record cannot be resolved :raise DNSSECValidationError: response from forwarder is not DNSSEC valid R;RCRDRERFRGRARBR RZN( RIR<RR7R4RR1tcanonical_nametrrset(t ipa_ip_addrRURGRBtans_cdRUtans_do((s//usr/lib/python2.7/site-packages/ipalib/util.pyt$validate_dnssec_zone_forwarder_step2Zs,     cC@sd}yt|Wntjjk r9td}n?tjjk r[td}ntjjk r}td}ntjjk rtd}ntj j k rtd}nXt j d|dt j }y"x|D]}|jdqWWnvtk rwtd |D}|rxtd i|d 6d jg|D]}tjj|^qKd 6}qxnX|rt|ndS(s Validate if value is valid IDNA domain. If domain is not valid, raises ValueError :param value: :return: s"invalid escape code in domain namesempty DNS labels0domain name cannot be longer than 255 characterss-DNS label cannot be longer than 63 characterssinvalid domain nameu [..。。]R<tasciics@s'|]}tjj||kVqdS(N(t encodingstidnatnameprep(Rtx((s//usr/lib/python2.7/site-packages/ipalib/util.pys ss@domain name '%(domain)s' should be normalized to: %(normalized)sR?Rnt normalizedN(R'RR5RDt BadEscapeRt EmptyLabelt NameTooLongt LabelTooLongR3t SyntaxErrorRMRFtUNICODEtencodet UnicodeErrorRRLR^R_R`Ry(RRZRRt is_nonnormRa((s//usr/lib/python2.7/site-packages/ipalib/util.pyRs6    1c C@std}t|}||}ytj|tj}|jj}t|dkrt|ddkr|djtjkr|dd}|j dj |j j krdSdSnWnt k rnXtd}||} ytj| tjWnt k rdSXdSd S( sP Detects the type of the realm that the given DNS zone belongs to. Note: This method is heuristic. Possible values: - 'current': For IPA domains belonging in the current realm. - 'foreign': For domains belonging in a foreing kerberos realm. - 'unknown': For domains whose allegiance could not be detected. t _kerberosiis"{0}"tcurrenttforeigns_ldap._tcp.gc._msdcstunknownN(RRR:RtTXTR5RMRGtrdtypetto_textRztenvRRtSRV( tapiR?tkerberos_prefixt domain_suffixtkerberos_record_nameRIRMtrecordt gc_prefixtad_specific_record_name((s//usr/lib/python2.7/site-packages/ipalib/util.pytdetect_dns_zone_realm_types,    !     cC@s&|jdjdt}|tkS(Ntdomainlevel_getRI(tCommandRR (Rut domainlevel((s//usr/lib/python2.7/site-packages/ipalib/util.pythas_managed_topologyst classpropertycB@sAeZdZdddZdZdZdZdZRS( t__doc__tfgetcC@s:|dkr$|dk r$|j}n||_||_dS(N(R'RR(R,Rtdoc((s//usr/lib/python2.7/site-packages/ipalib/util.pyR*s  cC@s5|jdk r%|jj||StddS(Nsunreadable attribute(RR't__get__tAttributeError(R,R0tobj_type((s//usr/lib/python2.7/site-packages/ipalib/util.pyRscC@stddS(Nscan't set attribute(R(R,R0R((s//usr/lib/python2.7/site-packages/ipalib/util.pyt__set__scC@stddS(Nscan't delete attribute(R(R,R0((s//usr/lib/python2.7/site-packages/ipalib/util.pyt __delete__scC@s ||_|S(N(R(R,R((s//usr/lib/python2.7/site-packages/ipalib/util.pytgetters (s__doc__sfgetN( R/R0t __slots__R'R*RRRR(((s//usr/lib/python2.7/site-packages/ipalib/util.pyRs    cC@s,|jdr|d }n|j}|S(s-Use common fqdn form without the trailing dotu.i(RRH(R2((s//usr/lib/python2.7/site-packages/ipalib/util.pytnormalize_hostnames  cC@s9yt|Wn$tk r4}tdt|SXdS(Nsinvalid domain-name: %s(RRyRR%R'(RRRU((s//usr/lib/python2.7/site-packages/ipalib/util.pythostname_validator s cC@sy`tjt|dtj}|dk r_|j|kr_tdtd|jd|SnWn!tjt fk rtdSXdS(NR<sFinvalid IP address version (is %(value)d, must be %(required_value)d)!Rtrequired_valuesinvalid IP address format( RRR*t INET_PTONR'RRR!RRy(RR\t ip_versionR ((s//usr/lib/python2.7/site-packages/ipalib/util.pytipaddr_validators   cC@s|jd\}}}t||}|dk r7|S|ry4t|}|dksd|dkrptnWqtk rtdtd|SXndS(Nu port iis%(port)s is not a valid portR(RpRR'tintRyRR!(Rt forwarderRtsepRtip_address_validation((s//usr/lib/python2.7/site-packages/ipalib/util.pytvalidate_bind_forwarder#s   cC@sWtd|dD}d|kr*dSd|krSd|krS|d|d7st objectclasstkrbprincipalauxtkrbprincipalnametkrbcanonicalname(tset(Rt objectclasses((s//usr/lib/python2.7/site-packages/ipalib/util.pytset_krbcanonicalname6s    cG@se|j|jddg}|jjdd}||dkratjdddtdndS(s  ensure that the LDAP entry has at least one value of krbprincipalname and that this value is equal to krbcanonicalname :param ldap: LDAP connection object :param entry_attrs: LDAP entry made prior to update :param options: command options RRiRDRZsHat least one value equal to the canonical principal name must be presentN(t get_entrytdnt single_valueRR'RtValidationErrorR(tldapRtkeystentryR((s//usr/lib/python2.7/site-packages/ipalib/util.pytensure_last_krbprincipalnameAs  cC@sx|j|jdddg}|jjdddk r=dSt||jdd|jdd|j|dS(NRRR(RRRRR'RRtupdate(RRt old_entry((s//usr/lib/python2.7/site-packages/ipalib/util.pytensure_krbcanonicalname_setWs cC@sw|dk r"tjj|j satjjtj satjjtj satj tj rst ddndS(so Check if IPA client is configured on the system. Hardcode return code to avoid recursive imports s+IPA client is not configured on this systemiN( R'RbRcRdt conf_defaultRtIPA_DEFAULT_CONFtisdirtIPA_CLIENT_SYSRESTOREtlistdirR(Rs((s//usr/lib/python2.7/site-packages/ipalib/util.pytcheck_client_configurationgs "c G@s|jjdddd}t}x|D]z}|jdg}|jtd|Dd|kr|j|ddjn|j|ddjq,Wxl|d D]`}|j}|jr|j nd}||ks||krt j d d d t d qqWdS(s7 Check that principal name's suffix does not overlap with UPNs and realm names of trusted forests. :param api_instance: API instance :param suffixes: principal suffixes :raises: ValidationError if the suffix coincides with realm name, UPN suffix or netbios name of trusted domains ut sizelimitiRItipantadditionalsuffixescs@s|]}|jVqdS(N(RH(Rtupn((s//usr/lib/python2.7/site-packages/ipalib/util.pys st ipantflatnametcniRDRRZs:realm or UPN suffix overlaps with trusted domain namespaceN(R~t trust_findRRRtaddRHRt is_enterpriset upn_suffixR'RRR( t api_instanceRt trust_objectsttrust_suffix_namespaceR0t nt_suffixest principalRR((s//usr/lib/python2.7/site-packages/ipalib/util.pyt(check_principal_realm_in_trust_namespaceus      cC@sPxI|D]A}|jstjd|tdj|dtjqqWdS(Ns.No network interface matches the IP address %ss7WARNING: No network interface matches the IP address {}R_(tget_matching_interfaceR{R|tprintRztsyststderr(t addr_listR ((s//usr/lib/python2.7/site-packages/ipalib/util.pyt,no_matching_interface_for_ip_address_warnings    cC@s^y*tjdtj|tjddSWn-tttjfk rYt j j ddSXdS(s Get current terminal height Args: fd (int): file descriptor. Default: 1 (stdout) Returns: int: Terminal height thht1234itLINESiN( tstructtunpacktfcntltioctlttermiost TIOCGWINSZRiRjRZRbtenvironR(tfd((s//usr/lib/python2.7/site-packages/ipalib/util.pytget_terminal_heights $cC@sftjjdd}tj|gdtj}y|jj||jWnt k ranXdS(ss Open text data in pager Args: data (bytes): data to view in pager Returns: None tPAGERtlesststdinN( RbRRt subprocesstPopentPIPERtwritet communicateRi(ROtpagert pager_process((s//usr/lib/python2.7/site-packages/ipalib/util.pyt open_in_pagers  tAPIReprc B@sPeZeeeeeeee e e e dh ZdZdZdZRS(cC@s\tt|jxB|jjD]1\}}t|tr#t||tj q#q#WdS(N( R)RR*t__dict__R"RRRRtmaxsize(R,RR((s//usr/lib/python2.7/site-packages/ipalib/util.pyR*scC@sdt|S(sOutput with u'' prefixtu(trepr(R,Ratlevel((s//usr/lib/python2.7/site-packages/ipalib/util.pytrepr_strscC@s=|tkrdS||jkr/dj|jSt|SdS(Nss (R*t builtin_typesRzR/R(R,RaR((s//usr/lib/python2.7/site-packages/ipalib/util.pyt repr_types  N(R/R0R#RR$R*tbytesR!R RRt frozensetR&R'RR*RR(((s//usr/lib/python2.7/site-packages/ipalib/util.pyRs   (iii8"i i3i8"i i3i8"i i3iii'iii'ii`'i: ii`'i: ii`'i: iiQiiQiiQiii(R R R (R(Rt __future__RRtloggingRbRWRMR,R5R^RRRRRRRRRt dns.exceptionRt dns.resolverRt netaddr.coreRR(thttplibRt ImportErrort http.clienttipalibRR tipalib.constantsR R R R RRt ipalib.textRtipaplatform.pathsRt ipapython.sshRt ipapython.dnRRtipapython.dnsutilRRtipapython.admintoolRt version_infotreprlibR'tPY3R*R%t_IPA_CLIENT_SYSRESTOREt_IPA_DEFAULT_CONFt getLoggerR/R{RR9RBRKRPRVR]RmRtRvRt default_portRR=RRRRR<RRRRRRRRRRRRR RRt ip4_rev_zonet ip6_rev_zonetREVERSE_DNS_ZONESRR!R#R&R"R'R1R2R3R4R7RIRKRTRVR\RR|RtobjectRRRRRRRRRRRRRtReprRRtapirepr(((s//usr/lib/python2.7/site-packages/ipalib/util.pyts                .           . U&        G         ! ( , 4        %