a ChJ @s4ddlZddlZddlZddlZddlZddlZddlmZmZe ddddiBZ ddd Z d Z d Zd d hhdhdddhhdhdhdhdhdhdddhd ZGdddZGdddejZdd Zed!d"Zd#d$Zd2d&d'ZGd(d)d)eZd*d+ZGd,d-d-Zd.d/ZGd0d1d1ZdS)3N) alg_lists validation)Zarbitrary_dh_groupsZ min_dh_sizeZ min_dsa_sizeZ min_rsa_sizeZ sha1_in_certsZ ssh_certsZ min_ec_size)ANYZ DISABLE_ETMZDISABLE_NON_ETM)ZDEFAULTZENFORCEZRELAX)ZetmZ__ems*)tlssslopensslnssgnutlsjava-tlssshopensshopenssh-serveropenssh-clientlibsshipsecike libreswankerberoskrb5dnssecbindrpm rpm-sequoiarr>r rr >r rr rr>rrr>rrr>r r r>rrr>rrr>r r rrr) rr r rrrr rrr rc@s(eZdZefddZddZddZdS) ScopeSelectorcCs||_}|d |_|jr&|n |dd}tjj||jdtjj||jd|drr|dddn|g|_ tjj |j t |jddS)a= Initialize a scope selector. An example would be `ssh` in `ciphers@ssh = -NULL`. When openssh backend will request the configuration, it'll offer (`{'ssh', 'openssh'}`) as scopes and the rule above will be taken into account. Both patterns and scopes are cast to lowercase. For more examples, refer to tests/unit/parsing/test_scope_selector.py >>> ss = ScopeSelector('!{SSH,IPsec}') >>> ss.matches({'ipsec', 'libreswan'}) False >>> ss.matches({'tls', 'openssl'}) True !rN)Zoriginal_pattern{,) lowerpattern startswith _positiverscopeZillegal_charactersZcurly_bracketssplit_globsZresulting_globs ALL_SCOPES)selfr"pr+B/usr/share/crypto-policies/python/cryptopolicies/cryptopolicies.py__init__As$ zScopeSelector.__init__cCsd|jdS)Nz)r"r)r+r+r,__str__\szScopeSelector.__str__csR|jtkrdSddD|jr:tfdd|jDStfdd|jDS)aE Checks whether ScopeSelector matches one of the scopes. For more examples, refer to tests/unit/parsing/test_scope_selector.py >>> ScopeSelector('{SSH,IPsec}').matches({'ipsec', 'libreswan'}) True >>> ScopeSelector('!{SSH,IPsec}').matches({'ipsec', 'libreswan'}) False TcSsg|] }|qSr+)r!).0sr+r+r, jz)ScopeSelector.matches..c3s|]}t|VqdSNfnmatchfilterr1gscopesr+r, mr4z(ScopeSelector.matches..c3s|]}t| VqdSr5r6r9r;r+r,r=nr4)r" SCOPE_ANYr$anyr'allr)r<r+r;r,matches_s zScopeSelector.matchesN)__name__ __module__ __qualname__r>r-r0rBr+r+r+r,r@s rc@s0eZdZdZdZdZdZdZdZdZ dd Z d S) OperationzCAn operation that comes with the right-hand value of the directive.rcCs d|jS)Nz Operation.)namer/r+r+r,__repr__}szOperation.__repr__N) rCrDrE__doc__RESETPREPENDAPPENDOMITSET_INTSET_ENUMrMr+r+r+r,rFssrFcsdd|rRtjvr2tvr2tjt|fgStjvsDtvrtj nHtvrftj tvr|tvrtj |ttj |fgS|}tfdd|Dsfdd|D}tjdfgdd|DStfd d|Drg}|D]}|d r:tjt|d dddd }nL|d rltjt|dd ddd }ntjt|d d}|fd d|Dq|Stj |dS)ae Parses right-hand parts of the directives into lists of operation/value pairs. For more examples, refer to tests/unit/test_parsing.py >>> parse_rhs('', 'cipher') [(Operation.RESET, None)] >>> parse_rhs('IDEA-CBC SEED-CBC', 'cipher') [(Operation.RESET, None), (Operation.APPEND, 'IDEA-CBC'), (Operation.APPEND, 'SEED-CBC')] >>> # 3DES-CBC gets prepended last for higher prio >>> parse_rhs('+*DES-CBC', 'cipher') [(Operation.PREPEND, 'DES-CBC'), (Operation.PREPEND, '3DES-CBC')] >>> parse_rhs('ENFORCE', '__ems') [(Operation.SET_ENUM, 'ENFORCE')] cSs|dp|dS)N)+-rU)r#endswith)vr+r+r, differentialszparse_rhs..differentialc3s|]}|VqdSr5r+r1rXrYr+r,r=r4zparse_rhs..cs"g|]}t|D]}|qqSr+)rglob)r1rXx prop_namer+r,r3r4zparse_rhs..NcSsg|]}tj|fqSr+)rFrQrZr+r+r,r3r4c3s|]}|VqdSr5r+rZr[r+r,r=r4rUrrcsg|] }|fqSr+r+rZ)opr+r,r3r4)isdigitrALL INT_DEFAULTSrFrSintENUMSrrulesZNonIntPropertyIntValueErrorZIntPropertyNonIntValueErrorZBadEnumValueErrorrTr&r?rOr@r#rPr\rWrQrRextendZ%MixedDifferentialNonDifferentialError)rhsr_valuesZ operationsvalueZunglobr+)rYr`r_r, parse_rhssF           rk Directiver_r% operationrjcs|s gStj||d\}}||}}tj||d|vrZ|ddn|tf\fddt|DS)aQ Parses configuration lines into tuples of directives. For more examples, refer to tests/unit/test_parsing.py >>> parse_line('cipher@TLS = RC4* NULL') [Directive(prop_name='cipher', scope='tls', operation=Operation.RESET, value=None), Directive(prop_name='cipher', scope='tls', operation=Operation.APPEND, value='RC4-40'), Directive(prop_name='cipher', scope='tls', operation=Operation.APPEND, value='RC4-128'), Directive(prop_name='cipher', scope='tls', operation=Operation.APPEND, value='NULL')] =@rcs$g|]\}}t||dqS)rm)rlr!)r1rnrjr_r%r+r,r3s zparse_line..)striprrfZcount_equals_signsr&Z empty_lhsr>rk)lineZlhsrhr+rqr, parse_lines   rtFc Cs\z t|}|D]}t|jqWn6tjyV}z|s8t|WYd}~n d}~00dSr5)rtrr%rZPolicySyntaxErrorwarningswarn)rsrvldexr+r+r,syntax_check_linesrzcseZdZdfdd ZZS)PolicySyntaxDeprecationWarningoptionFcsF|dd}|d|d}|d|7}|s6|d7}t|dS)N z and  z is deprecatedz", please rewrite your rules using z4; be advised that it is not always a 1-1 replacement)replacesuperr-)r)Z deprecatedZ replacementwhatonetoonemsg __class__r+r,r-s  z'PolicySyntaxDeprecationWarning.__init__)r|F)rCrDrEr- __classcell__r+r+rr,r{sr{c CsJtdd|}|dd}ddd|dD}|dd}dd d|dD}dd d|dD}td d|}td |rtt d dddddd}| D]`\}}d|d}t||}|rtt ||t|d|}|D]}|d|d|7}qqtd d|}ddddddd}| D]x\}}d|d}i}t ||D]} t||||| d<qj| D]\} } tt | | qt|||}qFd d!i} | D]\}}d|d}i}t ||D]$} t||| d|| d<q| D] \} } tt | | d"d#d$q"t|||}qt tjd%d%d&} | rd'd(d| d%d&D}td)| d&d|rd*|nd|}| qjtd+d|}t tjd%d%d&}|r>> preprocess_text('cipher = c1 \\ \nc2#x') 'cipher = c1 c2' >>> with warnings.catch_warnings(): ... warnings.simplefilter("ignore") ... preprocess_text('ike_protocol = IKEv2') 'protocol@IKE = IKEv2' >>> with warnings.catch_warnings(): ... warnings.simplefilter("ignore") ... preprocess_text('min_tls_version=TLS1.3') 'protocol@TLS = -SSL2.0 -SSL3.0 -TLS1.0 -TLS1.1 -TLS1.2' z#.*ro = r}css|]}|VqdSr5rrr1rwr+r+r,r= r4z"preprocess_text..z\ css|]}|VqdSr5rrr+r+r,r= r4css|]}tdd|VqdS)z\s+r~N)resubrr+r+r,r=r4z +z\bprotocol\s*=protocolz protocol@TLSz cipher@TLSz cipher@SSHz group@SSHz protocol@IKE)Z tls_cipherZ ssh_cipherZ ssh_groupZ ike_protocolz\bz\s*=(.*)z z =z7hash@DNSSec = -SHA1 sign@DNSSec = -RSA-SHA1 -ECDSA-SHA1z7hash@DNSSec = SHA1+ sign@DNSSec = RSA-SHA1+ ECDSA-SHA1+zetm@SSH = DISABLE_ETMz etm@SSH = ANYzetm@\1 = DISABLE_ETMz etm@\1 = ANY)zsha1_in_dnssec = 0zsha1_in_dnssec = 1z ssh_etm = 0z ssh_etm = 1zssh_etm@([^= ]+) = 0zssh_etm@([^= ]+) = 1rzX25519-MLKEM768zMLKEM768-X25519rjT)rrNrr~css|]}d|VqdSrVNr+rZr+r+r,r=Jr4z\bmin_dtls_version = zprotocol@TLS = z\bmin_dtls_version = 0\bcss|]}d|VqdSrr+rZr+r+r,r=Rr4z\bmin_tls_version = z\bmin_tls_version = 0\b)rrrjoinr&rrfindallrurvr{itemsfinditergrouplistrZDTLS_PROTOCOLSpopZ TLS_PROTOCOLS)textZPOSTFIX_REPLACEMENTSfrtoZregexmsmZPLAIN_REPLACEMENTSrBmatchZmatch_frZmatch_toZVALUE_REPLACEMENTSZ dtls_versionsnegZ tls_versionsr+r+r,preprocess_texts        "    rc@sJeZdZdZd ddZeddZeddZed d Zed d Z dS) ScopedPolicya An entity constructing lists of what's `.enabled` and what's `.disabled` when the given scopes are active. >>> sp = ScopedPolicy(parse_line('cipher@TLS = RC4* NULL'), {'tls'}) >>> 'AES-192-GCM' in sp.disabled['cipher'] True >>> sp.enabled['cipher'] ['RC4-40', 'RC4-128', 'NULL'] >>> ScopedPolicy(parse_line('min_dh_size=2048')).integers['min_dh_size'] 2048 Ncs^|pt}t_ddtD_ddtjD_ |D]t j }| |r>j tjkrrgj j<q>j tjkrj j}j|vr|jq>j tjkrj j}j|vr|j|djq>j tjkrfddj jDj j<q>j tjkr0jjj<q>jjj<q>fddtjD_dS)NcSsi|]\}}||dqS)rr+)r1krXr+r+r, kr4z)ScopedPolicy.__init__..cSsi|] }|gqSr+r+)r1r_r+r+r,rlr4rcsg|]}|jkr|qSr+)rjr1e) directiver+r,r3s z)ScopedPolicy.__init__..cs&i|]\}fdd|DqS)csg|]}|jvr|qSr+)enabledr)r_r)r+r,r3sz4ScopedPolicy.__init__...r+)r1Zalg_listr/r^r,rs)setrccopyintegersrerenumsrrbrrr%rBrnrFrOr_rQrjappendrPremoveinsertrRrSZdisabled)r) directivesZrelevant_scopesssrr+)rr)r,r-hs8                zScopedPolicy.__init__cCst|jdSNr)rmin_tls_versionrr/r+r+r,rszScopedPolicy.min_tls_versioncCst|jdSr)rmax_tls_versionrr/r+r+r,rszScopedPolicy.max_tls_versioncCst|jdSr)rmin_dtls_versionrr/r+r+r,rszScopedPolicy.min_dtls_versioncCst|jdSr)rmax_dtls_versionrr/r+r+r,rszScopedPolicy.max_dtls_version)N) rCrDrErNr-propertyrrrrr+r+r+r,r[s &   rcCs@|D](}tj||}t|tjr|Sqt|||dSr5)ospathraccessR_OKrZPolicyFileNotFoundError) policynamefnamepathsrxr*r+r+r, lookup_files  rc@sFeZdZdZdZddddZddZdd d Zdd d ZddZ dS)UnscopedCryptoPolicyz/etc/crypto-policiesz/usr/share/crypto-policiesN) policydircGsP||_d|g|R|_g|_||}|D]}||j|dd7}q.||_dS)N:T) subpolicy)rrrlinesread_policy_file _directives)r)Z policy_namerZsubpolicy_namesrZsubpolicy_namer+r+r,r-s zUnscopedCryptoPolicy.__init__cCs|j Sr5)rr/r+r+r,is_emptyszUnscopedCryptoPolicy.is_emptycCst|j|p iSr5)rrrAr+r+r,scopedszUnscopedCryptoPolicy.scopedFc Cs|jpd}|rtj|d}t|||s*dndtjj|tj|j|tj|j|f}t|dd}| }Wdn1s0Yt |}| d}|D]}t |dd q|D] }t |qd d |DS) NZpoliciesmodulesz.polz.pmodzutf-8)encodingr}T)rvcSsg|]}t|D]}|qqSr+)rt)r1rwr]r+r+r,r3r4z9UnscopedCryptoPolicy.read_policy_file..) rrrrrcurdir CONFIG_DIR SHARE_DIRopenreadrr&rz) r)rLrZpdirr*frrrwr+r+r,rs( &  z%UnscopedCryptoPolicy.read_policy_filec Cs dd}|}d|jd}|d7}|d7}|d7}|d7}|d7}i|j|j|j}|D]\}}||||7}qdd }tD]p\}} |j| d } i| j| j| j} | D]<\}}|||kr|s|d 7}d }|||d ||7}qq|s|d7}|S)NcSs2t|trd|nt|}|d|dS)Nr~rr}) isinstancerrstrrstrip)keyrjr2r+r+r,fmtsz)UnscopedCryptoPolicy.__str__..fmtz # Policy z dump z# z?# Do not parse the contents of this file with automated tools, z.# it is provided for review convenience only. z"# Baseline values for all scopes: Fr;z9# Scope-specific properties derived for select backends: Trpz&# No scope-specific properties found. )rrrrrrDUMPABLE_SCOPES) r)rZgeneric_scopedr2Z generic_allr_rjZanything_scope_specificZ scope_nameZ scope_setZspecific_scopedZ specific_allr+r+r,r0s@  zUnscopedCryptoPolicy.__str__)N)F) rCrDrErrr-rrrr0r+r+r+r,rs   r)F) collectionsenumr7rrrurrrdictfromkeysrcrer>r(rrEnumrFrk namedtuplerlrtrz FutureWarningr{rrrrr+r+r+r,sN  3B   aF