PK! &__pycache__/utils.cpython-36.opt-1.pycnu[3 f@sTddlZejdkr"ddlZddlZd ddZddZdZejdkrHd Zned ZdS) Nntc Cs tjdkrtjjd|Stj}d}tj}d}d}ytj||d|}Wnd}YnX|sd}|tj B}ytj||d|}Wnd}YnX|sd}|tj B}ytj||d|}Wnd}YnX|rytj |d\}} Wnd}YnXtj ||rtjj||Stjjtj |S)Nrz/usrzSoftware\ISC\BINDTrFZ InstallDir)osnamepathjoinwin32conHKEY_LOCAL_MACHINEZKEY_READwin32apiZ RegOpenKeyExZKEY_WOW64_64KEYZKEY_WOW64_32KEYZRegQueryValueExZ RegCloseKeyZGetSystemDirectory) ZbindirZhklmZ bind_subkeyZsamZh_keyZ key_foundZsam64Zsam32Z named_base_r /usr/lib/python3.6/utils.pyprefixsD        rcCs2tjdkrd|jdddSd|jdddS)Nr"z"\"'z'\'')rrreplace)sr r r shellquote=s rz"9.11.36-RedHat-9.11.36-16.el8_10.2z/etcZetc)r)rrrr rrversionZ sysconfdirr r r r  s  ) PK!  __pycache__/utils.cpython-36.pycnu[3 f@sTddlZejdkr"ddlZddlZd ddZddZdZejdkrHd Zned ZdS) Nntc Cs tjdkrtjjd|Stj}d}tj}d}d}ytj||d|}Wnd}YnX|sd}|tj B}ytj||d|}Wnd}YnX|sd}|tj B}ytj||d|}Wnd}YnX|rytj |d\}} Wnd}YnXtj ||rtjj||Stjjtj |S)Nrz/usrzSoftware\ISC\BINDTrFZ InstallDir)osnamepathjoinwin32conHKEY_LOCAL_MACHINEZKEY_READwin32apiZ RegOpenKeyExZKEY_WOW64_64KEYZKEY_WOW64_32KEYZRegQueryValueExZ RegCloseKeyZGetSystemDirectory) ZbindirZhklmZ bind_subkeyZsamZh_keyZ key_foundZsam64Zsam32Z named_base_r /usr/lib/python3.6/utils.pyprefixsD        rcCs2tjdkrd|jdddSd|jdddS)Nr"z"\"'z'\'')rrreplace)sr r r shellquote=s rz"9.11.36-RedHat-9.11.36-16.el8_10.2z/etcZetc)r)rrrr rrversionZ sysconfdirr r r r  s  ) PK!ņ)__pycache__/__init__.cpython-36.opt-1.pycnu[3 f @sjdddddddddd d d d g Zd dlTd dlTd dlTd dlTd dlTd dlTd dlTd dlTd dl TdS)ZcheckdsZcoverageZkeymgrZdnskeyZ eventlistZkeydictZkeyeventZ keyseriesZkeyzoneZpolicyZparsetabZrndcZutils)*N) __all__Z isc.dnskeyZ isc.eventlistZ isc.keydictZ isc.keyeventZ isc.keyseriesZ isc.keyzoneZ isc.policyZisc.rndcZ isc.utilsrr/usr/lib/python3.6/__init__.py s   PK!ņ#__pycache__/__init__.cpython-36.pycnu[3 f @sjdddddddddd d d d g Zd dlTd dlTd dlTd dlTd dlTd dlTd dlTd dlTd dl TdS)ZcheckdsZcoverageZkeymgrZdnskeyZ eventlistZkeydictZkeyeventZ keyseriesZkeyzoneZpolicyZparsetabZrndcZutils)*N) __all__Z isc.dnskeyZ isc.eventlistZ isc.keydictZ isc.keyeventZ isc.keyseriesZ isc.keyzoneZ isc.policyZisc.rndcZ isc.utilsrr/usr/lib/python3.6/__init__.py s   PK!\=(__pycache__/checkds.cpython-36.opt-1.pycnu[3 f&@shddlZddlZddlZddlmZmZddlmZmZdZ GdddZ d ddZ d d Z d d Z dS)N)PopenPIPE)prefixversionzdnssec-checkdsc@sPeZdZdddddZdZdZdZdZdZdZ d Z dd d Z d d Z ddZ dS)SECRRzSHA-1zSHA-256ZGOSTzSHA-384)INNrcCs|stt|tk r$|jdj}n|j}t|dkrWt | dkrt ddSd} xv| D]n} | |krt d| j| jjd| j| jt j| jfd} n,t d| j| jjd| j| jt j| jfqW| s"t d|rdnd| S)Nz+noallz+answerz-tr,Zdsz-qr)stdoutr cSs|j|j|jfS)N)r'r(r))rrr-r-r.mszcheck..)keyz-fz-lZdnskey-)stdinr7rz$No DNSKEY records found in zone apexFz,%s for KSK %s/%03d/%05d (%s) found in parentTz0%s for KSK %s/%03d/%05d (%s) missing from parentz'No %s records were found for any DNSKEYrr)digrrZ communicate splitlinesrrrappendrsorted dsfromkeyrprintrr!rr(r'r6r)) zoneargs masterfile lookasideZrrlistcmdfp_lineZklistZintodsfoundr8r-r-r.checkcsV           rLcCstjtdd}d}tjdkr"dnd}|jdtdd|jd d d td d |jdddtdd |jdddtjjt |dtdd|jdddtjjt |dtdd|jdddt d|j }|j j d |_ |jr|jj d |_|S)!Nz: checks DS coverage) descriptionbinntZsbinrCz zone to check)rhelpz-fz--filerEzzone master file)destrrPz-lz --lookasiderFzDLV lookaside zonez-dz--digr=z path to 'dig')rQdefaultrrPz-Dz --dsfromkeyrAzdnssec-dsfromkeyzpath to 'dnssec-dsfromkey'z-vz --versionr)actionrr)argparseArgumentParserprogosname add_argumentrpathrrr parse_argsrCrrF)parserZbindirZsbindirrDr-r-r.r[s,        r[cCs.t}t|j||j|j}t|r$dnddS)Nrr)r[rLrCrErFexit)rDrKr-r-r.mainsr^)NN)rTrWsys subprocessrrZ isc.utilsrrrVrrLr[r^r-r-r-r. sI ; PK!\="__pycache__/checkds.cpython-36.pycnu[3 f&@shddlZddlZddlZddlmZmZddlmZmZdZ GdddZ d ddZ d d Z d d Z dS)N)PopenPIPE)prefixversionzdnssec-checkdsc@sPeZdZdddddZdZdZdZdZdZdZ d Z dd d Z d d Z ddZ dS)SECRRzSHA-1zSHA-256ZGOSTzSHA-384)INNrcCs|stt|tk r$|jdj}n|j}t|dkrWt | dkrt ddSd} xv| D]n} | |krt d| j| jjd| j| jt j| jfd} n,t d| j| jjd| j| jt j| jfqW| s"t d|rdnd| S)Nz+noallz+answerz-tr,Zdsz-qr)stdoutr cSs|j|j|jfS)N)r'r(r))rrr-r-r.mszcheck..)keyz-fz-lZdnskey-)stdinr7rz$No DNSKEY records found in zone apexFz,%s for KSK %s/%03d/%05d (%s) found in parentTz0%s for KSK %s/%03d/%05d (%s) missing from parentz'No %s records were found for any DNSKEYrr)digrrZ communicate splitlinesrrrappendrsorted dsfromkeyrprintrr!rr(r'r6r)) zoneargs masterfile lookasideZrrlistcmdfp_lineZklistZintodsfoundr8r-r-r.checkcsV           rLcCstjtdd}d}tjdkr"dnd}|jdtdd|jd d d td d |jdddtdd |jdddtjjt |dtdd|jdddtjjt |dtdd|jdddt d|j }|j j d |_ |jr|jj d |_|S)!Nz: checks DS coverage) descriptionbinntZsbinrCz zone to check)rhelpz-fz--filerEzzone master file)destrrPz-lz --lookasiderFzDLV lookaside zonez-dz--digr=z path to 'dig')rQdefaultrrPz-Dz --dsfromkeyrAzdnssec-dsfromkeyzpath to 'dnssec-dsfromkey'z-vz --versionr)actionrr)argparseArgumentParserprogosname add_argumentrpathrrr parse_argsrCrrF)parserZbindirZsbindirrDr-r-r.r[s,        r[cCs.t}t|j||j|j}t|r$dnddS)Nrr)r[rLrCrErFexit)rDrKr-r-r.mainsr^)NN)rTrWsys subprocessrrZ isc.utilsrrrVrrLr[r^r-r-r-r. sI ; PK!l)__pycache__/coverage.cpython-36.opt-1.pycnu[3 f&@sddlmZddlZddlZddlZddlZddlZddlZddlZddl Z ddl m Z dZ ddl mZmZmZmZmZmZddZdad d Zd d Zd dZdddZddZddZdS))print_functionN) defaultdictzdnssec-coverage)dnskey eventlistkeydictkeyeventkeyzoneutilscOst||tjddS)N)printsysexit)argskwargsr/usr/lib/python3.6/coverage.pyfatals rTcOsJd|kr|d}|jddnd}tr,dan |r8td|rFt||dS)zuoutput text, adding a vertical space this is *not* the first first section being printed since a call to vreset()skipNTF)pop _firstliner )rrrrrroutput'srcCsdadS)zreset vertical spacingTN)rrrrrvreset8src Cs|j}yt|Stk r$YnXtjd}|j|}|sJtd||j\}}t|}|j}|jdrx|dS|jdr|dS|jdr|dS|jd r|d S|jd r|d S|jd r|dS|jdr|Std|dS)z convert a formatted time (e.g., 1y, 6mo, 15mi, etc) into seconds :param s: String with some text representing a time interval :return: Integer with the number of seconds in the time interval z([0-9][0-9]*)\s*([A-Za-z]*)zCannot parse %syi3moi'wi: diQhiZmi<szInvalid suffix %sN) stripint ValueErrorrecompilematchgroupslower startswith)rrmnZunitrrr parse_timeAs6           r,cCs|}| s(tjj| s(tj|tj rtjd}|s>tjj}xB|jtjD]2}tjj ||}tjj|rztj|tjrzPd}qLW|S)a1 find the location of a specified command. if a default is supplied and it works, we use it; otherwise we search PATH for a match. :param command: string with a command to look for in the path :param default: default location to use :return: detected location for the desired command PATHN) ospathisfileaccessX_OKenvirondefpathsplitpathsepjoin)ZcommanddefaultZfpathr/Z directoryrrrset_pathks$ r9c 0CsDtdtjjtjdd}tjtddd}|j dt dddFd |j d d dt ddd|j ddt ddd|j ddt ddd|j ddt ddd|j ddd t d!dd|j d"d#|t d$d d|j d%d&t d'd(dd)|j d*d+d,d-d.d/|j d0d1d,d-d2d/|j d3d4d5d,d-d6d/|j d7d8d9tj d:|j }|j rJ|jrJtd;n*|j sZ|jrn|j rfdkrtd?d@dA|jD|_y|jrt|j}||_Wntk rYnXy|jrt|j}||_Wntk r YnXy|jr(t|j}||_Wntk r@YnXy<|jr||j}t|j}|dBkrnd|_ntj||_Wntk rYnX|jr|jr|S|jr*|jr*y:t|jdB|j|j}|jp|j|_|jp|j|_Wn4tk r(}ztdC|j|WYdd}~XnX|js@tdDdE|_|S)Gz8Read command line arguments, set global 'args' structureznamed-compilezoneZsbinz: checks future zDNSKEY coverage for a zone) descriptionzone*Nzzone(s) to checkz%(default: all zones in the directory))typenargsr8helpz-Kr/.z&a directory containing keys to processdir)destr8r=r?metavarz-ffilenamezzone master filefile)rBr=r?rCz-mmaxttlzthe longest TTL in the zone(s)timez-dkeyttlzthe DNSKEY TTLz-rresignZ1944000z:the RRSIG refresh interval in seconds [default: 22.5 days]z-c compilezonezpath to 'named-compilezone'z-l checklimit0zDLength of time to check for DNSSEC coverage [default: 0 (unlimited)])rBr=r8r?rCz-zno_ksk store_trueFz#Only check zone-signing keys (ZSKs))rBactionr8r?z-kno_zskz"Only check key-signing keys (KSKs)z-Dz--debugZ debug_modezTurn on debugging outputz-vz --versionversion)rOrQz)ERROR: -z and -k cannot be used together.ZKSKZZSKr z)ERROR: -f can only be used with one zone.cSs4g|],}t|dkr,|ddkr,|ddn|qS)r r@NrR)len).0xrrr szparse_args..rz"Unable to load zone data from %s: zWARNING: Maximum TTL value was not specified. Using 1 week (604800 seconds); re-run with the -m option to get more accurate results.i: z5zone(s) to check(default: all zones in the directory)) r9r.r/r7r prefixargparseArgumentParserprog add_argumentstrrQ parse_argsrPrMrkeytyperDrSr;rFr,r"rHrIrKrGrrJ Exceptionr r) rJparserrr*kr)Zlimr;errrr]s                       "r]c(Cspt}tdyt|j|j|jd}Wn2tk rX}ztdt|WYdd}~XnXx<|D]4}|j t |j r|j t q`|j t |j |jq`Wt dty t|}Wn2tk r}ztdt|WYdd}~XnXd}|js|jd|j|jt sXd}nJxH|jD]>}y|j||j|jt s6d}Wnt d|YnXqWtj|rfd nd dS) Nz;PHASE 1--Loading keys to check for internal timing problems)r/ZzonesrHz'ERROR: Unable to build key dictionary: z9PHASE 2--Scanning future key events for coverage failuresz#ERROR: Unable to build event list: FTz&ERROR: Coverage check failed for zone r r)r]r rr/r;rHr_rr\Z check_prepubrsepZ check_postpubrFrIrrZcoverager^rKr r )rZkdrbkeyZelisterrorsr;rrrmains:"    "   rf)N)Z __future__rr.r rXZglobr#rGZcalendarpprint collectionsrrZZiscrrrrrr rrrrr,r9r]rfrrrr s&    * xPK!l#__pycache__/coverage.cpython-36.pycnu[3 f&@sddlmZddlZddlZddlZddlZddlZddlZddlZddl Z ddl m Z dZ ddl mZmZmZmZmZmZddZdad d Zd d Zd dZdddZddZddZdS))print_functionN) defaultdictzdnssec-coverage)dnskey eventlistkeydictkeyeventkeyzoneutilscOst||tjddS)N)printsysexit)argskwargsr/usr/lib/python3.6/coverage.pyfatals rTcOsJd|kr|d}|jddnd}tr,dan |r8td|rFt||dS)zuoutput text, adding a vertical space this is *not* the first first section being printed since a call to vreset()skipNTF)pop _firstliner )rrrrrroutput'srcCsdadS)zreset vertical spacingTN)rrrrrvreset8src Cs|j}yt|Stk r$YnXtjd}|j|}|sJtd||j\}}t|}|j}|jdrx|dS|jdr|dS|jdr|dS|jd r|d S|jd r|d S|jd r|dS|jdr|Std|dS)z convert a formatted time (e.g., 1y, 6mo, 15mi, etc) into seconds :param s: String with some text representing a time interval :return: Integer with the number of seconds in the time interval z([0-9][0-9]*)\s*([A-Za-z]*)zCannot parse %syi3moi'wi: diQhiZmi<szInvalid suffix %sN) stripint ValueErrorrecompilematchgroupslower startswith)rrmnZunitrrr parse_timeAs6           r,cCs|}| s(tjj| s(tj|tj rtjd}|s>tjj}xB|jtjD]2}tjj ||}tjj|rztj|tjrzPd}qLW|S)a1 find the location of a specified command. if a default is supplied and it works, we use it; otherwise we search PATH for a match. :param command: string with a command to look for in the path :param default: default location to use :return: detected location for the desired command PATHN) ospathisfileaccessX_OKenvirondefpathsplitpathsepjoin)ZcommanddefaultZfpathr/Z directoryrrrset_pathks$ r9c 0CsDtdtjjtjdd}tjtddd}|j dt dddFd |j d d dt ddd|j ddt ddd|j ddt ddd|j ddt ddd|j ddd t d!dd|j d"d#|t d$d d|j d%d&t d'd(dd)|j d*d+d,d-d.d/|j d0d1d,d-d2d/|j d3d4d5d,d-d6d/|j d7d8d9tj d:|j }|j rJ|jrJtd;n*|j sZ|jrn|j rfdkrtd?d@dA|jD|_y|jrt|j}||_Wntk rYnXy|jrt|j}||_Wntk r YnXy|jr(t|j}||_Wntk r@YnXy<|jr||j}t|j}|dBkrnd|_ntj||_Wntk rYnX|jr|jr|S|jr*|jr*y:t|jdB|j|j}|jp|j|_|jp|j|_Wn4tk r(}ztdC|j|WYdd}~XnX|js@tdDdE|_|S)Gz8Read command line arguments, set global 'args' structureznamed-compilezoneZsbinz: checks future zDNSKEY coverage for a zone) descriptionzone*Nzzone(s) to checkz%(default: all zones in the directory))typenargsr8helpz-Kr/.z&a directory containing keys to processdir)destr8r=r?metavarz-ffilenamezzone master filefile)rBr=r?rCz-mmaxttlzthe longest TTL in the zone(s)timez-dkeyttlzthe DNSKEY TTLz-rresignZ1944000z:the RRSIG refresh interval in seconds [default: 22.5 days]z-c compilezonezpath to 'named-compilezone'z-l checklimit0zDLength of time to check for DNSSEC coverage [default: 0 (unlimited)])rBr=r8r?rCz-zno_ksk store_trueFz#Only check zone-signing keys (ZSKs))rBactionr8r?z-kno_zskz"Only check key-signing keys (KSKs)z-Dz--debugZ debug_modezTurn on debugging outputz-vz --versionversion)rOrQz)ERROR: -z and -k cannot be used together.ZKSKZZSKr z)ERROR: -f can only be used with one zone.cSs4g|],}t|dkr,|ddkr,|ddn|qS)r r@NrR)len).0xrrr szparse_args..rz"Unable to load zone data from %s: zWARNING: Maximum TTL value was not specified. Using 1 week (604800 seconds); re-run with the -m option to get more accurate results.i: z5zone(s) to check(default: all zones in the directory)) r9r.r/r7r prefixargparseArgumentParserprog add_argumentstrrQ parse_argsrPrMrkeytyperDrSr;rFr,r"rHrIrKrGrrJ Exceptionr r) rJparserrr*kr)Zlimr;errrr]s                       "r]c(Cspt}tdyt|j|j|jd}Wn2tk rX}ztdt|WYdd}~XnXx<|D]4}|j t |j r|j t q`|j t |j |jq`Wt dty t|}Wn2tk r}ztdt|WYdd}~XnXd}|js|jd|j|jt sXd}nJxH|jD]>}y|j||j|jt s6d}Wnt d|YnXqWtj|rfd nd dS) Nz;PHASE 1--Loading keys to check for internal timing problems)r/ZzonesrHz'ERROR: Unable to build key dictionary: z9PHASE 2--Scanning future key events for coverage failuresz#ERROR: Unable to build event list: FTz&ERROR: Coverage check failed for zone r r)r]r rr/r;rHr_rr\Z check_prepubrsepZ check_postpubrFrIrrZcoverager^rKr r )rZkdrbkeyZelisterrorsr;rrrmains:"    "   rf)N)Z __future__rr.r rXZglobr#rGZcalendarpprint collectionsrrZZiscrrrrrr rrrrr,r9r]rfrrrr s&    * xPK!1X5X5'__pycache__/dnskey.cpython-36.opt-1.pycnu[3 f @@sJddlZddlZddlZddlmZmZGdddeZGdddZdS)N)PopenPIPEcseZdZfddZZS)TimePastcstt|jd|||fdS)Nz'%s time for key %s (%d) is already past)superr__init__)selfkeypropvalue) __class__/usr/lib/python3.6/dnskey.pyrs zTimePast.__init__)__name__ __module__ __qualname__r __classcell__r r )r r rsrc@seZdZdZdqZdrZdsZdtd!d"Zd#d$Zd%d&Z e dud'd(Z d)d*Z e d+d,Ze d-d.Zdvd/d0Ze d1d2Ze d3d4Ze d5d6Ze d7d8Zd9d:Zd;d<Zd=d>Zd?d@ZdAdBZdCdDZejfdEdFZdGdHZejfdIdJZdKdLZejfdMdNZ dOdPZ!ejfdQdRZ"dSdTZ#ejfdUdVZ$dWdXZ%ejfdYdZZ&d[d\Z'ejfd]d^Z(d_d`Z)dadbZ*dcddZ+dedfZ,dgdhZ-didjZ.dwdkdlZ/dxdmdnZ0e dodpZ1d S)ydnskeyztAn individual DNSSEC key. Identified by path, name, algorithm, keyid. Contains a dictionary of metadata events.CreatedPublishActivateInactiveDeleteRevoke DSPublish SyncPublish SyncDeleteN-P-A-I-D-R-Psync-DsyncRSAMD5DHDSAECCRSASHA1NSEC3DSA NSEC3RSASHA1 RSASHA256 RSASHA512ECCGOSTECDSAP256SHA256ECDSAP384SHA384ED25519ED448cCst|tr:t|dkr:|pd|_|\}}}|j|||||pLtjj|pLd|_tjj|}|j d\}}}|dd}t |}t |j dd}|j||||dS)N.+r) isinstancetuplelen_dir fromtupleospathdirnamebasenamesplitint)rrZ directorykeyttlnamealgkeyidr r r r&s    zdnskey.__init__cs|jdr|}|jd}n|d}d|||f}|j|jr@tjpBd|d}|j|jr^tjp`d|d}||_||_t||_t||_ ||_ t |d} x| D]zddkrqj } | sq| d j dkrd } ||_nd} |st| d n||_t| | d @d krd|_qd|_qW| jt |d} t|_t|_t|_t|_t|_t|_t|_d|_x| D]j svddkrqvfdddDtg} tdd| D}d|j}|djdj}||j|<qvWxtjD]}d|j|<||jkrn|j|j|}||j|<|j ||j|<|j!||j|<|j||j|<n(d|j|<d|j|<d|j|<d|j|<qW| jdS)Nr2z K%s+%03d+%05dz.keyz.privaterr;r4inchhsr1TFZrUz!#csg|]}j|qSr )find).0c)liner r lsz$dnskey.fromtuple..z:= cSsg|]}|dkr|qS)r4r5r )rMposr r r rPms)rHrIrJ)"endswithrstripr9r;sepkeystrrBr@rCrDfullnameopenr?lowerttlclosedictZmetadata_changed_delete_times_fmttime _timestamps _original_origttlstripr8minlstripr_PROPS parsetime formattime epochfromtime)rrBrCrDrArVrUZkey_fileZ private_fileZkfptokensZseptokenZpfpZ punctuationfoundr r tr )rOr r:5sv                 zdnskey.fromtuplecKsr|jdd}g}d}|jdk r0|dt|jg7}xlttjtjD]Z\}}| s@|j| r\q@d}||j krx|j |rxd}|rdn|j |} ||| g7}d}q@W|rn|d|j g||j g} |st ddj| y0t| ttd } | j\} } | rtt| Wn8tk r:}ztd |t|fWYdd}~XnXd|_x*tjD] }|j||j|<d|j|<qJWdS) NquietFTz-LZnonez-Kz#  )stdoutstderrzunable to run %s: %s)getrbstrrYziprrf_OPTSr\r]r_r9rUprintjoinrr communicate Exceptionr`ra)rZ settime_binkwargsrmcmdfirstr optdeleteZwhenZfullcmdprorper r r commits<    " z dnskey.commitc KsL| jdd} |dd|dt|g} |r0| d|g7} |r>| jd|rN| d|g7} |rb| d t|g7} | rtj| }| d tj|g7} | rtj| }| d tj| g7} | j|| std d j| t| t t d}|j \}}|rt dt|y"|j dj d}t|||}|St k rF}zt dt|WYdd}~XnXdS)NrmFz-qz-Kz-Lz-rz-fkz-az-bz-Pz-Az# rn)rorpzunable to generate key: rasciiz!unable to parse generated key: %s)rqrrappendr timefromepochrhrurvrrrwrx splitlinesdecode)cls keygen_bin randomdevZkeys_dirrBrCZkeysizerTrYpublishactivateryrm keygen_cmdrlr~rorprUnewkeyrr r r generates:         zdnskey.generatec Ks|jdd}|js td||dd|jd|jg}|jrL|dt|jg7}|r\|d|g7}|rp|d t|g7}|std d j|t |t t d }|j \}} | rtd | y&|j dj d} t| |j|j} | Std|YnXdS)NrmFz'predecessor key %s has no inactive datez-qz-Kz-Sz-Lz-rz-iz# rn)rorpzunable to generate key: rrz'unable to generate successor for key %s)rqinactiverxr9rUrYrrrurvrrrwrrr) rrrZ prepublishryrmrr~rorprUrr r r generate_successors,     zdnskey.generate_successorcCs0d}|tttjkr tj|}|r(|Sd|S)Nz%03d)ranger8r _ALGNAMES)rCrBr r r algstrs z dnskey.algstrc Cs6|sdS|j}y tjj|Stk r0dSXdS)N)upperrrindex ValueError)rCr r r algnums z dnskey.algnumcCs|j|p |jS)N)rrC)rrCr r r algnameszdnskey.algnamecCs tj|S)N)timeZgmtime)secsr r r rszdnskey.timefromepochcCs tj|dS)Nz %Y%m%d%H%M%S)rZstrptime)stringr r r rg szdnskey.parsetimecCs tj|S)N)calendarZtimegm)rlr r r riszdnskey.epochfromtimecCs tjd|S)Nz %Y%m%d%H%M%S)rZstrftime)rlr r r rhszdnskey.formattimecKs|jdd}|j||krdS|j|dk rR|j||krR| rRt|||j||dkr|j|dkrldnd|j|<d|j|<d|j|<d|j|<d|j|<dS|j|}||j|<||j|<|j ||j|<|j||j|krdnd|j|<dS)NforceFT) rqr`rarr\r]r^r_rrh)rr rnowryrrlr r r setmetas$        zdnskey.setmetacCs |j|S)N)r^)rr r r r gettime2szdnskey.gettimecCs |j|S)N)r_)rr r r r getfmttime5szdnskey.getfmttimecCs |j|S)N)r`)rr r r r gettimestamp8szdnskey.gettimestampcCs |jdS)Nr)r`)rr r r created;szdnskey.createdcCs |jdS)Nr)r`)rr r r syncpublish>szdnskey.syncpublishcKs|jd||f|dS)Nr)r)rrrryr r r setsyncpublishAszdnskey.setsyncpublishcCs |jdS)Nr)r`)rr r r rDszdnskey.publishcKs|jd||f|dS)Nr)r)rrrryr r r setpublishGszdnskey.setpublishcCs |jdS)Nr)r`)rr r r rJszdnskey.activatecKs|jd||f|dS)Nr)r)rrrryr r r setactivateMszdnskey.setactivatecCs |jdS)Nr)r`)rr r r revokePsz dnskey.revokecKs|jd||f|dS)Nr)r)rrrryr r r setrevokeSszdnskey.setrevokecCs |jdS)Nr)r`)rr r r rVszdnskey.inactivecKs|jd||f|dS)Nr)r)rrrryr r r setinactiveYszdnskey.setinactivecCs |jdS)Nr)r`)rr r r r}\sz dnskey.deletecKs|jd||f|dS)Nr)r)rrrryr r r setdelete_szdnskey.setdeletecCs |jdS)Nr)r`)rr r r syncdeletebszdnskey.syncdeletecKs|jd||f|dS)Nr)r)rrrryr r r setsyncdeleteeszdnskey.setsyncdeletecCsR|dks|j|krdS|jdkr0|j|_||_n|j|krHd|_||_n||_dS)N)rYrb)rrYr r r setttlhs  z dnskey.setttlcCs|jr dSdS)NKSKZSK)rT)rr r r keytypetszdnskey.keytypecCsd|j|j|jfS)Nz %s/%s/%05d)rBrrD)rr r r __str__wszdnskey.__str__cCs"d|j|j|j|jrdndfS)Nz%s/%s/%05d (%s)rr)rBrrDrT)rr r r __repr__{szdnskey.__repr__cCs|jp|jp|jS)N)rrr)rr r r datesz dnskey.datecCs@|j|jkr|j|jkS|j|jkr0|j|jkS|j|jkS)N)rBrCr)rotherr r r __lt__s     z dnskey.__lt__cCsdd}|s|}ttj}|j}|j}|s4dS|sT||krP|dt|dS||krh||krhdS||kr|dt|tj|jpdfdS||kr|dt|dS|jdk r|||jkr|d t|tj|jpdfdSdS) Nc_sdS)Nr )argsryr r r noopsz!dnskey.check_prepub..noopFzFWARNING: Key %s is scheduled for activation but not for publication.TzWARNING: %s is scheduled to be published and activated at the same time. This could result in a coverage gap if the zone was previously signed. Activation should be at least %s after publication.zone DNSKEY TTLz0WARNING: Key %s is active before it is publishedzWARNING: Key %s is activated too soon after publication; this could result in coverage gaps due to resolver caches containing old data. Activation should be at least %s after publication.)r@rrrreprrdurationrY)routputrrar~r r r check_prepubs<   zdnskey.check_prepubcCsdd}|dkr|}|dkr"|j}|dkr>|dt|d }tj}|j}|j}|s^dS|s~||krz|dt|dS||kr||krdS||kr|d t|dS|||kr|d t|tj|fdSdS) Nc_sdS)Nr )rryr r r rsz"dnskey.check_postpub..noopz"WARNING: Key %s using default TTL.<FzEWARNING: Key %s is scheduled for deletion but not for inactivation.Tz@WARNING: Key %s is scheduled for deletion before inactivation.zWARNING: Key %s scheduled for deletion too soon after deactivation; this may result in coverage gaps due to resolver caches containing old data. Deletion should be at least %s after inactivation.iiQ)rYrrr}rrr)rrZtimespanrrdir r r check_postpubs:   zdnskey.check_postpubcCsz|sdSddddddg}g}xR|D]J}||d ||d }}|d kr"|jd ||d |d krbdndfq"Wdj|S) Nyearrrimmonthdayhourminutesecondr4rz%d %s%ssrEz, iiQ3)rriiQ')rriQ)rr)rr)rr)rr4)rrv)rZunitsrZunitvr r r rs (zdnskey.duration) rrrrrrrrr) Nrrrrr Nr!r")Nr#r$r%r&r'r(r)r*Nr+Nr,r-r.r/r0)NN)NN)N)N)NN)2rrr__doc__rfrtrrr:r classmethodrr staticmethodrrrrrgrirhrrrrrrrrrrrrrrrrr}rrrrrrrrrrrrr r r r rsb M% *        1 -r) r;rr subprocessrrrxrrr r r r  s PK!1X5X5!__pycache__/dnskey.cpython-36.pycnu[3 f @@sJddlZddlZddlZddlmZmZGdddeZGdddZdS)N)PopenPIPEcseZdZfddZZS)TimePastcstt|jd|||fdS)Nz'%s time for key %s (%d) is already past)superr__init__)selfkeypropvalue) __class__/usr/lib/python3.6/dnskey.pyrs zTimePast.__init__)__name__ __module__ __qualname__r __classcell__r r )r r rsrc@seZdZdZdqZdrZdsZdtd!d"Zd#d$Zd%d&Z e dud'd(Z d)d*Z e d+d,Ze d-d.Zdvd/d0Ze d1d2Ze d3d4Ze d5d6Ze d7d8Zd9d:Zd;d<Zd=d>Zd?d@ZdAdBZdCdDZejfdEdFZdGdHZejfdIdJZdKdLZejfdMdNZ dOdPZ!ejfdQdRZ"dSdTZ#ejfdUdVZ$dWdXZ%ejfdYdZZ&d[d\Z'ejfd]d^Z(d_d`Z)dadbZ*dcddZ+dedfZ,dgdhZ-didjZ.dwdkdlZ/dxdmdnZ0e dodpZ1d S)ydnskeyztAn individual DNSSEC key. Identified by path, name, algorithm, keyid. Contains a dictionary of metadata events.CreatedPublishActivateInactiveDeleteRevoke DSPublish SyncPublish SyncDeleteN-P-A-I-D-R-Psync-DsyncRSAMD5DHDSAECCRSASHA1NSEC3DSA NSEC3RSASHA1 RSASHA256 RSASHA512ECCGOSTECDSAP256SHA256ECDSAP384SHA384ED25519ED448cCst|tr:t|dkr:|pd|_|\}}}|j|||||pLtjj|pLd|_tjj|}|j d\}}}|dd}t |}t |j dd}|j||||dS)N.+r) isinstancetuplelen_dir fromtupleospathdirnamebasenamesplitint)rrZ directorykeyttlnamealgkeyidr r r r&s    zdnskey.__init__cs|jdr|}|jd}n|d}d|||f}|j|jr@tjpBd|d}|j|jr^tjp`d|d}||_||_t||_t||_ ||_ t |d} x| D]zddkrqj } | sq| d j dkrd } ||_nd} |st| d n||_t| | d @d krd|_qd|_qW| jt |d} t|_t|_t|_t|_t|_t|_t|_d|_x| D]j svddkrqvfdddDtg} tdd| D}d|j}|djdj}||j|<qvWxtjD]}d|j|<||jkrn|j|j|}||j|<|j ||j|<|j!||j|<|j||j|<n(d|j|<d|j|<d|j|<d|j|<qW| jdS)Nr2z K%s+%03d+%05dz.keyz.privaterr;r4inchhsr1TFZrUz!#csg|]}j|qSr )find).0c)liner r lsz$dnskey.fromtuple..z:= cSsg|]}|dkr|qS)r4r5r )rMposr r r rPms)rHrIrJ)"endswithrstripr9r;sepkeystrrBr@rCrDfullnameopenr?lowerttlclosedictZmetadata_changed_delete_times_fmttime _timestamps _original_origttlstripr8minlstripr_PROPS parsetime formattime epochfromtime)rrBrCrDrArVrUZkey_fileZ private_fileZkfptokensZseptokenZpfpZ punctuationfoundr r tr )rOr r:5sv                 zdnskey.fromtuplecKsr|jdd}g}d}|jdk r0|dt|jg7}xlttjtjD]Z\}}| s@|j| r\q@d}||j krx|j |rxd}|rdn|j |} ||| g7}d}q@W|rn|d|j g||j g} |st ddj| y0t| ttd } | j\} } | rtt| Wn8tk r:}ztd |t|fWYdd}~XnXd|_x*tjD] }|j||j|<d|j|<qJWdS) NquietFTz-LZnonez-Kz#  )stdoutstderrzunable to run %s: %s)getrbstrrYziprrf_OPTSr\r]r_r9rUprintjoinrr communicate Exceptionr`ra)rZ settime_binkwargsrmcmdfirstr optdeleteZwhenZfullcmdprorper r r commits<    " z dnskey.commitc KsL| jdd} |dd|dt|g} |r0| d|g7} |r>| jd|rN| d|g7} |rb| d t|g7} | rtj| }| d tj|g7} | rtj| }| d tj| g7} | j|| std d j| t| t t d}|j \}}|rt dt|y"|j dj d}t|||}|St k rF}zt dt|WYdd}~XnXdS)NrmFz-qz-Kz-Lz-rz-fkz-az-bz-Pz-Az# rn)rorpzunable to generate key: rasciiz!unable to parse generated key: %s)rqrrappendr timefromepochrhrurvrrrwrx splitlinesdecode)cls keygen_bin randomdevZkeys_dirrBrCZkeysizerTrYpublishactivateryrm keygen_cmdrlr~rorprUnewkeyrr r r generates:         zdnskey.generatec Ks|jdd}|js td||dd|jd|jg}|jrL|dt|jg7}|r\|d|g7}|rp|d t|g7}|std d j|t |t t d }|j \}} | rtd | y&|j dj d} t| |j|j} | Std|YnXdS)NrmFz'predecessor key %s has no inactive datez-qz-Kz-Sz-Lz-rz-iz# rn)rorpzunable to generate key: rrz'unable to generate successor for key %s)rqinactiverxr9rUrYrrrurvrrrwrrr) rrrZ prepublishryrmrr~rorprUrr r r generate_successors,     zdnskey.generate_successorcCs0d}|tttjkr tj|}|r(|Sd|S)Nz%03d)ranger8r _ALGNAMES)rCrBr r r algstrs z dnskey.algstrc Cs6|sdS|j}y tjj|Stk r0dSXdS)N)upperrrindex ValueError)rCr r r algnums z dnskey.algnumcCs|j|p |jS)N)rrC)rrCr r r algnameszdnskey.algnamecCs tj|S)N)timeZgmtime)secsr r r rszdnskey.timefromepochcCs tj|dS)Nz %Y%m%d%H%M%S)rZstrptime)stringr r r rg szdnskey.parsetimecCs tj|S)N)calendarZtimegm)rlr r r riszdnskey.epochfromtimecCs tjd|S)Nz %Y%m%d%H%M%S)rZstrftime)rlr r r rhszdnskey.formattimecKs|jdd}|j||krdS|j|dk rR|j||krR| rRt|||j||dkr|j|dkrldnd|j|<d|j|<d|j|<d|j|<d|j|<dS|j|}||j|<||j|<|j ||j|<|j||j|krdnd|j|<dS)NforceFT) rqr`rarr\r]r^r_rrh)rr rnowryrrlr r r setmetas$        zdnskey.setmetacCs |j|S)N)r^)rr r r r gettime2szdnskey.gettimecCs |j|S)N)r_)rr r r r getfmttime5szdnskey.getfmttimecCs |j|S)N)r`)rr r r r gettimestamp8szdnskey.gettimestampcCs |jdS)Nr)r`)rr r r created;szdnskey.createdcCs |jdS)Nr)r`)rr r r syncpublish>szdnskey.syncpublishcKs|jd||f|dS)Nr)r)rrrryr r r setsyncpublishAszdnskey.setsyncpublishcCs |jdS)Nr)r`)rr r r rDszdnskey.publishcKs|jd||f|dS)Nr)r)rrrryr r r setpublishGszdnskey.setpublishcCs |jdS)Nr)r`)rr r r rJszdnskey.activatecKs|jd||f|dS)Nr)r)rrrryr r r setactivateMszdnskey.setactivatecCs |jdS)Nr)r`)rr r r revokePsz dnskey.revokecKs|jd||f|dS)Nr)r)rrrryr r r setrevokeSszdnskey.setrevokecCs |jdS)Nr)r`)rr r r rVszdnskey.inactivecKs|jd||f|dS)Nr)r)rrrryr r r setinactiveYszdnskey.setinactivecCs |jdS)Nr)r`)rr r r r}\sz dnskey.deletecKs|jd||f|dS)Nr)r)rrrryr r r setdelete_szdnskey.setdeletecCs |jdS)Nr)r`)rr r r syncdeletebszdnskey.syncdeletecKs|jd||f|dS)Nr)r)rrrryr r r setsyncdeleteeszdnskey.setsyncdeletecCsR|dks|j|krdS|jdkr0|j|_||_n|j|krHd|_||_n||_dS)N)rYrb)rrYr r r setttlhs  z dnskey.setttlcCs|jr dSdS)NKSKZSK)rT)rr r r keytypetszdnskey.keytypecCsd|j|j|jfS)Nz %s/%s/%05d)rBrrD)rr r r __str__wszdnskey.__str__cCs"d|j|j|j|jrdndfS)Nz%s/%s/%05d (%s)rr)rBrrDrT)rr r r __repr__{szdnskey.__repr__cCs|jp|jp|jS)N)rrr)rr r r datesz dnskey.datecCs@|j|jkr|j|jkS|j|jkr0|j|jkS|j|jkS)N)rBrCr)rotherr r r __lt__s     z dnskey.__lt__cCsdd}|s|}ttj}|j}|j}|s4dS|sT||krP|dt|dS||krh||krhdS||kr|dt|tj|jpdfdS||kr|dt|dS|jdk r|||jkr|d t|tj|jpdfdSdS) Nc_sdS)Nr )argsryr r r noopsz!dnskey.check_prepub..noopFzFWARNING: Key %s is scheduled for activation but not for publication.TzWARNING: %s is scheduled to be published and activated at the same time. This could result in a coverage gap if the zone was previously signed. Activation should be at least %s after publication.zone DNSKEY TTLz0WARNING: Key %s is active before it is publishedzWARNING: Key %s is activated too soon after publication; this could result in coverage gaps due to resolver caches containing old data. Activation should be at least %s after publication.)r@rrrreprrdurationrY)routputrrar~r r r check_prepubs<   zdnskey.check_prepubcCsdd}|dkr|}|dkr"|j}|dkr>|dt|d }tj}|j}|j}|s^dS|s~||krz|dt|dS||kr||krdS||kr|d t|dS|||kr|d t|tj|fdSdS) Nc_sdS)Nr )rryr r r rsz"dnskey.check_postpub..noopz"WARNING: Key %s using default TTL.<FzEWARNING: Key %s is scheduled for deletion but not for inactivation.Tz@WARNING: Key %s is scheduled for deletion before inactivation.zWARNING: Key %s scheduled for deletion too soon after deactivation; this may result in coverage gaps due to resolver caches containing old data. Deletion should be at least %s after inactivation.iiQ)rYrrr}rrr)rrZtimespanrrdir r r check_postpubs:   zdnskey.check_postpubcCsz|sdSddddddg}g}xR|D]J}||d ||d }}|d kr"|jd ||d |d krbdndfq"Wdj|S) Nyearrrimmonthdayhourminutesecondr4rz%d %s%ssrEz, iiQ3)rriiQ')rriQ)rr)rr)rr)rr4)rrv)rZunitsrZunitvr r r rs (zdnskey.duration) rrrrrrrrr) Nrrrrr Nr!r")Nr#r$r%r&r'r(r)r*Nr+Nr,r-r.r/r0)NN)NN)N)N)NN)2rrr__doc__rfrtrrr:r classmethodrr staticmethodrrrrrgrirhrrrrrrrrrrrrrrrrr}rrrrrrrrrrrrr r r r rsb M% *        1 -r) r;rr subprocessrrrxrrr r r r  s PK!*__pycache__/eventlist.cpython-36.opt-1.pycnu[3 f@s6ddlmZddlTddlTddlTGdddZdS)) defaultdict)*c@s`eZdZeddZeddZeZdZddZ dddZ d d Z e d d Z e d dZdS) eventlistcCsttS)N)rlistrr/usr/lib/python3.6/eventlist.pyszeventlist.cCsttS)N)rrrrrrr sNc Csddddddg}||_x|jD]}|jj|x||jD]\}}xj|jD]^}xX|D]P}|j|}|snqZt|||} |jr|j ||j | qZ|j ||j | qZWqPWt |j ||ddd |j ||<t |j ||d dd |j ||<q>Wq WdS) NZ SyncPublishZPublishZ SyncDeleteZActivateZInactiveZDeletecSs|jS)N)when)eventrrrr +sz$eventlist.__init__..)keycSs|jS)N)r )r rrrr -s) _kdictZzones_zonesadditemsvaluesZgettimekeyeventsep_Kappend_Zsorted) selfZkdictZ propertieszonealgkeyskZpropterrr__init__s&     zeventlist.__init__c Csdd}|s|}|r |dkr dnd}|r4|dkr4dnd}d}} d} |rb||jkrb|d|dS|rd} |s~|j|d||}|s|j|d||} n`x^|jD]T} | r| |jjkrd} |j| d||}| r| |jjkrd} |j| d||} qW| s|ddS|o| S) Nc_sdS)Nr)argskwargsrrrnoop2sz eventlist.coverage..noopKSKTFZZSKz!ERROR: No key events found for %szERROR: No key events found)r checkzonerrr) rrkeytypeuntiloutputr"Zno_zskZno_kskZkokZzokfoundzrrrcoverage1s6  zeventlist.coveragec Csxd}|dkr|j|}n |j|}xP|jD]D}|d||tj|ftj|||||}|rh|d|on|}q,W|S)NTr#z9Checking scheduled %s events for zone %s, algorithm %s...zNo errors found)rrrdnskeyZalgstrrcheckset) rrr%r&r'ZallokZkzrokrrrr$Ts   zeventlist.checkzonecCsR|sdS|d|djdddx(|D] }|d|jt|jfddq*WdS)Nz r:F)skipz %s: %s)ZshowtimeZwhatreprr )eventsetr'r rrrshowsetfs  zeventlist.showsetc CsNt}t}d}xZ|D]R}d}| s4|dj|jkr>|j||dj|jkr|j|t}|j|qW|rz|j||s|d|dSd}} x|D]}|rtj|dj|kr|dtjdtj|dSx|D]}|j|| \}} qWt j |||s|d|dS| s,|d|dS| j |s|d |dSqWdS) NFTrzERROR: No %s events foundzIgnoring events after %sz%a %b %d %H:%M:%S UTC %Yz*ERROR: No %s's are active after this eventz-ERROR: No %s's are published after this eventz=ERROR: No %s's are both active and published after this event) rr rZcalendarZtimegmZtimeZstrftimeZgmtimeZstatusrr2 intersection) r1r%r&r'groupsgroupZ eventsfoundr ZactiveZ publishedrrrr,nsL          zeventlist.checkset)N)__name__ __module__ __qualname__rrrsetrr rr*r$ staticmethodr2r,rrrrrs   # rN) collectionsrr+Zkeydictrrrrrr s PK!$__pycache__/eventlist.cpython-36.pycnu[3 f@s6ddlmZddlTddlTddlTGdddZdS)) defaultdict)*c@s`eZdZeddZeddZeZdZddZ dddZ d d Z e d d Z e d dZdS) eventlistcCsttS)N)rlistrr/usr/lib/python3.6/eventlist.pyszeventlist.cCsttS)N)rrrrrrr sNc Csddddddg}||_x|jD]}|jj|x||jD]\}}xj|jD]^}xX|D]P}|j|}|snqZt|||} |jr|j ||j | qZ|j ||j | qZWqPWt |j ||ddd |j ||<t |j ||d dd |j ||<q>Wq WdS) NZ SyncPublishZPublishZ SyncDeleteZActivateZInactiveZDeletecSs|jS)N)when)eventrrrr +sz$eventlist.__init__..)keycSs|jS)N)r )r rrrr -s) _kdictZzones_zonesadditemsvaluesZgettimekeyeventsep_Kappend_Zsorted) selfZkdictZ propertieszonealgkeyskZpropterrr__init__s&     zeventlist.__init__c Csdd}|s|}|r |dkr dnd}|r4|dkr4dnd}d}} d} |rb||jkrb|d|dS|rd} |s~|j|d||}|s|j|d||} n`x^|jD]T} | r| |jjkrd} |j| d||}| r| |jjkrd} |j| d||} qW| s|ddS|o| S) Nc_sdS)Nr)argskwargsrrrnoop2sz eventlist.coverage..noopKSKTFZZSKz!ERROR: No key events found for %szERROR: No key events found)r checkzonerrr) rrkeytypeuntiloutputr"Zno_zskZno_kskZkokZzokfoundzrrrcoverage1s6  zeventlist.coveragec Csxd}|dkr|j|}n |j|}xP|jD]D}|d||tj|ftj|||||}|rh|d|on|}q,W|S)NTr#z9Checking scheduled %s events for zone %s, algorithm %s...zNo errors found)rrrdnskeyZalgstrrcheckset) rrr%r&r'ZallokZkzrokrrrr$Ts   zeventlist.checkzonecCsR|sdS|d|djdddx(|D] }|d|jt|jfddq*WdS)Nz r:F)skipz %s: %s)ZshowtimeZwhatreprr )eventsetr'r rrrshowsetfs  zeventlist.showsetc CsNt}t}d}xZ|D]R}d}| s4|dj|jkr>|j||dj|jkr|j|t}|j|qW|rz|j||s|d|dSd}} x|D]}|rtj|dj|kr|dtjdtj|dSx|D]}|j|| \}} qWt j |||s|d|dS| s,|d|dS| j |s|d |dSqWdS) NFTrzERROR: No %s events foundzIgnoring events after %sz%a %b %d %H:%M:%S UTC %Yz*ERROR: No %s's are active after this eventz-ERROR: No %s's are published after this eventz=ERROR: No %s's are both active and published after this event) rr rZcalendarZtimegmZtimeZstrftimeZgmtimeZstatusrr2 intersection) r1r%r&r'groupsgroupZ eventsfoundr ZactiveZ publishedrrrr,nsL          zeventlist.checkset)N)__name__ __module__ __qualname__rrrsetrr rr*r$ staticmethodr2r,rrrrrs   # rN) collectionsrr+Zkeydictrrrrrr s PK!FN7 (__pycache__/keydict.cpython-36.opt-1.pycnu[3 f! @s:ddlmZddlmZddlZddlZGdddZdS)) defaultdict)dnskeyNc@sneZdZdZeddZdZgZdddZddZ d d Z d d Z d dZ ddZ ddZddZddZdS)keydictz> A dictionary of keys, indexed by name, algorithm, and key id cCsttS)N)rdictrr/usr/lib/python3.6/keydict.pyszkeydict.NcKs|jdd|_|jdd}|s:|jddp,d}|j|nXxV|D]N}d|krb|ddk rb|d}n|rr|j|jptd}|j||s@|jj|q@WdS)NZkeyttlzonespath.)get_defttlreadallZpolicyZ directoryreadone_missingappend)selfZdpkwargsr r zonerrr__init__s     zkeydict.__init__cCsLtjtjj|d}x2|D]*}t|||j}||j|j|j|j <qWdS)Nz *.private) globosr joinrr_keydictnamealgkeyid)rr filesinfilekeyrrrr,s zkeydict.readallc Cs|jds|d7}d|d}tjtjj||}d}xR|D]J}t|||j}|j|krZq<|dkrh|jnd}||j ||j |j <d}q s  PK!FN7 "__pycache__/keydict.cpython-36.pycnu[3 f! @s:ddlmZddlmZddlZddlZGdddZdS)) defaultdict)dnskeyNc@sneZdZdZeddZdZgZdddZddZ d d Z d d Z d dZ ddZ ddZddZddZdS)keydictz> A dictionary of keys, indexed by name, algorithm, and key id cCsttS)N)rdictrr/usr/lib/python3.6/keydict.pyszkeydict.NcKs|jdd|_|jdd}|s:|jddp,d}|j|nXxV|D]N}d|krb|ddk rb|d}n|rr|j|jptd}|j||s@|jj|q@WdS)NZkeyttlzonespath.)get_defttlreadallZpolicyZ directoryreadone_missingappend)selfZdpkwargsr r zonerrr__init__s     zkeydict.__init__cCsLtjtjj|d}x2|D]*}t|||j}||j|j|j|j <qWdS)Nz *.private) globosr joinrr_keydictnamealgkeyid)rr filesinfilekeyrrrr,s zkeydict.readallc Cs|jds|d7}d|d}tjtjj||}d}xR|D]J}t|||j}|j|krZq<|dkrh|jnd}||j ||j |j <d}q s  PK!N@@)__pycache__/keyevent.cpython-36.opt-1.pycnu[3 f @sddlZGdddZdS)Nc@s4eZdZdZd ddZddZddZd d d ZdS) keyeventz A discrete key event, e.g., Publish, Activate, Inactive, Delete, etc. Stores the date of the event, and identifying information about the key to which the event will occur.NcCs@||_|p|j||_||_|j|_|j|_|j|_|j|_dS)N) whatZgettimewhenkeysepnamezonealgkeyid)selfrrrr /usr/lib/python3.6/keyevent.py__init__szkeyevent.__init__cCs t|j|j|j|j|j|jfS)N)reprrrr rrr )r r r r __repr__ szkeyevent.__repr__cCstjd|jS)Nz%a %b %d %H:%M:%S UTC %Y)timeZstrftimer)r r r r showtime$szkeyevent.showtimecCsdd}|s|}|st}|s$t}|jdkr<|j|jn|jdkrT|j|jn|jdkr|j|kr||dt|jq|j|jnl|jdkr|j|kr|j|jq|dt|jn6|jd kr|j|kr|j|j|j|kr|j|j||fS) Nc_sdS)Nr )argskwargsr r r noop*szkeyevent.status..noopZActivateZPublishZInactivez= WARNING: %s scheduled to become inactive before it is activeZDeletez@WARNING: key %s is scheduled for deletion before it is publishedZRevoke)setraddr rrremove)r ZactiveZ publishedoutputrr r r status)s6           zkeyevent.status)N)N)__name__ __module__ __qualname____doc__rrrrr r r r rs  r)rrr r r r  sPK!N@@#__pycache__/keyevent.cpython-36.pycnu[3 f @sddlZGdddZdS)Nc@s4eZdZdZd ddZddZddZd d d ZdS) keyeventz A discrete key event, e.g., Publish, Activate, Inactive, Delete, etc. Stores the date of the event, and identifying information about the key to which the event will occur.NcCs@||_|p|j||_||_|j|_|j|_|j|_|j|_dS)N) whatZgettimewhenkeysepnamezonealgkeyid)selfrrrr /usr/lib/python3.6/keyevent.py__init__szkeyevent.__init__cCs t|j|j|j|j|j|jfS)N)reprrrr rrr )r r r r __repr__ szkeyevent.__repr__cCstjd|jS)Nz%a %b %d %H:%M:%S UTC %Y)timeZstrftimer)r r r r showtime$szkeyevent.showtimecCsdd}|s|}|st}|s$t}|jdkr<|j|jn|jdkrT|j|jn|jdkr|j|kr||dt|jq|j|jnl|jdkr|j|kr|j|jq|dt|jn6|jd kr|j|kr|j|j|j|kr|j|j||fS) Nc_sdS)Nr )argskwargsr r r noop*szkeyevent.status..noopZActivateZPublishZInactivez= WARNING: %s scheduled to become inactive before it is activeZDeletez@WARNING: key %s is scheduled for deletion before it is publishedZRevoke)setraddr rrremove)r ZactiveZ publishedoutputrr r r status)s6           zkeyevent.status)N)N)__name__ __module__ __qualname____doc__rrrrr r r r rs  r)rrr r r r  sPK!@ uu'__pycache__/keymgr.cpython-36.opt-1.pycnu[3 fk@sddlmZddlZddlZddlZddlZddlZddlZddlZddl Z ddl m Z dZ ddl mZmZmZmZmZmZddZddd Zd d Zd d ZdS))print_functionN) defaultdictz dnssec-keymgr)dnskeykeydict keyseriespolicyparsetabutilscOst||tjddS)N)printsysexit)argskwargsr/usr/lib/python3.6/keymgr.pyfatals rcCs|}| s(tjj| s(tj|tj rtjd}|s>tjj}xB|jtjD]2}|tj |}tjj|rztj|tjrzPd}qLW|S)a2 find the location of a specified command. If a default is supplied, exists and it's an executable, we use it; otherwise we search PATH for an alternative. :param command: command to look for :param default: default value to use :return: PATH with the location of a suitable binary PATHN) ospathisfileaccessX_OKenvirondefpathsplitpathsepsep)ZcommanddefaultZfpathrZ directoryrrrset_paths$ rcCstdtjjtjdd}tdtjjtjdd}tjtdd}|j dt ddd;d |j d d t ddd|j ddt ddd|j dd|t dd d|j ddt ddd d|j dd|t dd d|j d d!d"d#d$d%|j d&d'd"d#d(d%|j d)d*d+d"d#d s @   GPK!@ uu!__pycache__/keymgr.cpython-36.pycnu[3 fk@sddlmZddlZddlZddlZddlZddlZddlZddlZddl Z ddl m Z dZ ddl mZmZmZmZmZmZddZddd Zd d Zd d ZdS))print_functionN) defaultdictz dnssec-keymgr)dnskeykeydict keyseriespolicyparsetabutilscOst||tjddS)N)printsysexit)argskwargsr/usr/lib/python3.6/keymgr.pyfatals rcCs|}| s(tjj| s(tj|tj rtjd}|s>tjj}xB|jtjD]2}|tj |}tjj|rztj|tjrzPd}qLW|S)a2 find the location of a specified command. If a default is supplied, exists and it's an executable, we use it; otherwise we search PATH for an alternative. :param command: command to look for :param default: default value to use :return: PATH with the location of a suitable binary PATHN) ospathisfileaccessX_OKenvirondefpathsplitpathsepsep)ZcommanddefaultZfpathrZ directoryrrrset_paths$ rcCstdtjjtjdd}tdtjjtjdd}tjtdd}|j dt ddd;d |j d d t ddd|j ddt ddd|j dd|t dd d|j ddt ddd d|j dd|t dd d|j d d!d"d#d$d%|j d&d'd"d#d(d%|j d)d*d+d"d#d s @   GPK!1}n*__pycache__/keyseries.cpython-36.opt-1.pycnu[3 f"@sFddlmZddlTddlTddlTddlTddlZGdddZdS)) defaultdict)*Nc@sleZdZeddZeddZeZdZdZ e j dfddZ ddZ d d Z d d Ze j fd dZdS) keyseriescCsttS)N)rlistrr/usr/lib/python3.6/keyseries.pyszkeyseries.cCsttS)N)rrrrrrr sNcCs||_||_t|j|_x|jD]}|jj|x||jD]\}}xh|jD]\}|j r|j op|j |ks|j ||j |qT|j o|j |ksT|j ||j |qTW|j ||j|j ||jqBWq$WdS)N)_kdict_contextsetZmissing_zoneszonesadditemsvaluessepdelete_Kappend_Zsort)selfZkdictnowcontextzonealgkeyskrrr__init__s zkeyseries.__init__ccsbx\|jD]R}xL|j|jgD]<}||kr(qx,||jD]\}}x|D] }|VqDWq6WqWqWdS)N)r rrr)rr collectionrrkeyrrr__iter__.s  zkeyseries.__iter__cCs"x|D]}tdt|qWdS)Nz%s)printrepr)rrrrrdump7s zkeyseries.dumpcKs|jdd}|sdS|d}|jr>|j}|jp0d }|jp:d } n|j}|jpLd }|jpVd} |j} |j } | sv| |kr|j ||} | s| |kr|j ||} |j } d} |s|j d||jd|n| s| || kr| r(| |||| kr(|j | |f||j| || f|n| s`|j ||| f||j||| | f|n| |krln| || kr|j | |f||j| || f|np| |||| kr|j | |f||j| || f|n0|j ||| f||j||| | f|n|j}| s8| | || krL|j| | f|nN|sj|j|| | f|n0||| krzn || | kr|j| | f||j|jkr|j|j|}x|ddD]}|s|j d||j d||j d||jd||j|jkr|j|jq|j } | |} |j | f||j | f||j | |f||j| || f||j| | f||j|jkr|j|j|}qWx|r>|j r>|j ||jkr>|j|jdf||j|jd |jd |f|}|j |j |f||j|j | f||j||}qW|j d||jd|x"|D]}|j|jdf|q^WdS)NforceFriQi,rZ settime_path keygen_path randomdevi'i'i'i')N)N)N)N)N)N)N)N)getrZksk_rollperiodZksk_prepublishZksk_postpublishZzsk_rollperiodZzsk_prepublishZzsk_postpublishZpublishZactivateZ setpublishZ setactivateZinactiveZ setinactiveZ setdeleterkeyttlZttlZsetttlZcoverageZcommitr Zgenerate_successorr)rrpolicyrkwargsr&r!ZrpZprepubZpostpubpaiZfudgedprevrrr fixseries;s                        zkeyseries.fixseriescKs|jd|j}|jd|jjdd}|jdd}x|D]}g}|j|} |pX| jpXd}| j} tj| } d|ks||d rt|j || dkrtj |jd |jd ||| | j d| j pd f|} |j || j | |j |j |d |ks|d  rht|j|| dkrXtj |jd |jd ||| | jd | j prrrrrs   vr)r<rr7ZkeydictZkeyeventr,rBrrrrr s PK!1}n$__pycache__/keyseries.cpython-36.pycnu[3 f"@sFddlmZddlTddlTddlTddlTddlZGdddZdS)) defaultdict)*Nc@sleZdZeddZeddZeZdZdZ e j dfddZ ddZ d d Z d d Ze j fd dZdS) keyseriescCsttS)N)rlistrr/usr/lib/python3.6/keyseries.pyszkeyseries.cCsttS)N)rrrrrrr sNcCs||_||_t|j|_x|jD]}|jj|x||jD]\}}xh|jD]\}|j r|j op|j |ks|j ||j |qT|j o|j |ksT|j ||j |qTW|j ||j|j ||jqBWq$WdS)N)_kdict_contextsetZmissing_zoneszonesadditemsvaluessepdelete_Kappend_Zsort)selfZkdictnowcontextzonealgkeyskrrr__init__s zkeyseries.__init__ccsbx\|jD]R}xL|j|jgD]<}||kr(qx,||jD]\}}x|D] }|VqDWq6WqWqWdS)N)r rrr)rr collectionrrkeyrrr__iter__.s  zkeyseries.__iter__cCs"x|D]}tdt|qWdS)Nz%s)printrepr)rrrrrdump7s zkeyseries.dumpcKs|jdd}|sdS|d}|jr>|j}|jp0d }|jp:d } n|j}|jpLd }|jpVd} |j} |j } | sv| |kr|j ||} | s| |kr|j ||} |j } d} |s|j d||jd|n| s| || kr| r(| |||| kr(|j | |f||j| || f|n| s`|j ||| f||j||| | f|n| |krln| || kr|j | |f||j| || f|np| |||| kr|j | |f||j| || f|n0|j ||| f||j||| | f|n|j}| s8| | || krL|j| | f|nN|sj|j|| | f|n0||| krzn || | kr|j| | f||j|jkr|j|j|}x|ddD]}|s|j d||j d||j d||jd||j|jkr|j|jq|j } | |} |j | f||j | f||j | |f||j| || f||j| | f||j|jkr|j|j|}qWx|r>|j r>|j ||jkr>|j|jdf||j|jd |jd |f|}|j |j |f||j|j | f||j||}qW|j d||jd|x"|D]}|j|jdf|q^WdS)NforceFriQi,rZ settime_path keygen_path randomdevi'i'i'i')N)N)N)N)N)N)N)N)getrZksk_rollperiodZksk_prepublishZksk_postpublishZzsk_rollperiodZzsk_prepublishZzsk_postpublishZpublishZactivateZ setpublishZ setactivateZinactiveZ setinactiveZ setdeleterkeyttlZttlZsetttlZcoverageZcommitr Zgenerate_successorr)rrpolicyrkwargsr&r!ZrpZprepubZpostpubpaiZfudgedprevrrr fixseries;s                        zkeyseries.fixseriescKs|jd|j}|jd|jjdd}|jdd}x|D]}g}|j|} |pX| jpXd}| j} tj| } d|ks||d rt|j || dkrtj |jd |jd ||| | j d| j pd f|} |j || j | |j |j |d |ks|d  rht|j|| dkrXtj |jd |jd ||| | jd | j prrrrrs   vr)r<rr7ZkeydictZkeyeventr,rBrrrrr s PK!S (__pycache__/keyzone.cpython-36.opt-1.pycnu[3 f@sJddlZddlZddlZddlmZmZGdddeZGdddZdS)N)PopenPIPEc@s eZdZdS)KeyZoneExceptionN)__name__ __module__ __qualname__rr/usr/lib/python3.6/keyzone.pyrsrc@seZdZdZddZdS)keyzonez/reads a zone file to find data relevant to keysc Csd|_d|_|sdS| s8tjj| s8tj|tj rDtddSd}}t|dd||gt t dj \}}xv|j D]j}t |t k r|jd}tjd|rqv|j} | st| d|krt| d}| dd krvt| d}qvW||_||_dS) Nz"named-compilezone" not foundz-o-)stdoutstderrasciiz ^[:space:]*;ZDNSKEY)maxttlkeyttlospathisfileaccessX_OKrrrZ communicate splitlinestypestrdecoderesearchsplitint) selfnamefilenameZczpathrrfp_lineZfieldsrrr __init__s.     zkeyzone.__init__N)rrr__doc__r&rrrr r sr ) rsysr subprocessrr Exceptionrr rrrr  s PK!S "__pycache__/keyzone.cpython-36.pycnu[3 f@sJddlZddlZddlZddlmZmZGdddeZGdddZdS)N)PopenPIPEc@s eZdZdS)KeyZoneExceptionN)__name__ __module__ __qualname__rr/usr/lib/python3.6/keyzone.pyrsrc@seZdZdZddZdS)keyzonez/reads a zone file to find data relevant to keysc Csd|_d|_|sdS| s8tjj| s8tj|tj rDtddSd}}t|dd||gt t dj \}}xv|j D]j}t |t k r|jd}tjd|rqv|j} | st| d|krt| d}| dd krvt| d}qvW||_||_dS) Nz"named-compilezone" not foundz-o-)stdoutstderrasciiz ^[:space:]*;ZDNSKEY)maxttlkeyttlospathisfileaccessX_OKrrrZ communicate splitlinestypestrdecoderesearchsplitint) selfnamefilenameZczpathrrfp_lineZfieldsrrr __init__s.     zkeyzone.__init__N)rrr__doc__r&rrrr r sr ) rsysr subprocessrr Exceptionrr rrrr  s PK!ܴ@)__pycache__/parsetab.cpython-36.opt-1.pycnu[3 f};@s dZdZdZddddddd d d d d g d ddd d d d d d d d g fddddddd d d d d g d ddd d d d d d d d g fddddddd d dd d dd ddgd ddd d d d d dd d dd d d gfddddd d d d d g dd d d d d d d d g fddgddgfdddgdddgfdd gd!d"gfddd#d$d%d&d'dgdd(d)d*d+d,d-d(gfdddd.gdd/d/d0gfdd1dd!ddddd(d/d2ddg d! d! d d d1 d d! d d d d3ddg fdd(d/d4d5d6d7d8d9d:d;dd?d@dAdBdCdDdEdFdGdHdIdJdKdLd.dMdNdOdPdQd"dd0dRdSdTdUdVg*d d d d d d dWd= d> dX d# d$ d% dY dd4 d3 d5 d d6 d dZ d7 d8 d9 d: d[d d d( dC d2 dd& d' dD d/ d d? d@ dA dB g*fd3ddZddWdd[dgdXdXdXdXd; d d< d gfd3ddZddWdd[dgd#d#d#d#d; d d< d gfd3ddZddWdd[dgd$d$d$d$d; d d< d gfd3ddZddWdd[dgd%d%d%d%d; d d< d gfd3ddZddWdd[dgdYdYdYdYd; d d< d gfd3ddZddWdd[dgd&d&d&d&d; d d< d gfd3ddZddWdd[dgd'd'd'd'd; d d< d gfddddgd d d d gfddddgddd d gfdZddWdd[dgdJdOd; d d< d gfdXdYd)d*d+d,d-gd.d.d.d.d.dUdVgfdXdYd)d*d+gdMdMdMdMdMgfd\ZiZxXejD]L\ZZx@eededD]*\Z Z e ek riee <e ee e<qWqW[dgdgfdgdgfddgdd gfddgddgfddgddgfddgd d gfdgd1gfddgddQgfdd1dgd2ddgfd2gd4gfddgd5d6gfd3gdZgfd3dZgd7dKgfd3ddZdgd8dBd8dBgfd3ddZdgd9dCd9dCgfd3ddZdgd:dDd:dDgfd3ddZdgd;dEd;dEgfd3ddZdgddId>dIgfdgdgfddgd?dPgfddgd@d@gfddgdAdAgfddgdGdGgfdXdYd)d*d+gdLdNdRdSdTgfd]Z iZ xXe jD]L\ZZx@eededD]*\Z Z e e k rie e <e e e e<qWqW[ d^d_dd`d`d`fdadbddcdddefdfdbddcdddgfdhdiddjdddkfdldmddndddofdpdmddndddqfdrdmddndddsfdtduddvdddwfdxduddvdddyfdzduddvddd{fd|d}dd~dddfdd}dd~dddfdd}dd~dddfdd}dd~dddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfg6Z d`S(z3.8ZLALRZ C2FE91AF256AF1CCEB499107DA2CFE7E .>/MX ;= P <O()*,-EFGIJCR  !"#$%&0123456789:?@BDHKLNSTUVWA'+Q)ZALGORITHM_POLICYZZONEZPOLICYz$endZALGNAMEZSTRZQSTRINGZKEYTYPEZ DATESUFFIXLBRACESEMIZCOVERAGEZ ROLL_PERIODZ PRE_PUBLISHZ POST_PUBLISHZKEYTTLZKEY_SIZEZSTANDBYZ DIRECTORYZ ALGORITHMRBRACENUMBERZNONE) policylistinitpolicy alg_policy zone_policy named_policydomainname new_policyalg_option_grouppolicy_option_groupalg_option_list alg_optioncoverage_optionrollperiod_optionprepublish_optionpostpublish_option keyttl_optionkeysize_optionstandby_optionpolicy_option_list policy_option parent_optiondirectory_optionalgorithm_optiondurationzS' -> policylistzS'Nzpolicylist -> init policyr^Z p_policylistz policy.pyi zpolicylist -> policylist policyi zinit -> r_Zp_initizpolicy -> alg_policyr`Zp_policyizpolicy -> zone_policyizpolicy -> named_policyiz name -> STRreZp_nameizname -> KEYTYPEizname -> DATESUFFIXiz domain -> STRrdZp_domaini!zdomain -> QSTRINGi"zdomain -> KEYTYPEi#zdomain -> DATESUFFIXi$znew_policy -> rfZ p_new_policyi+zGalg_policy -> ALGORITHM_POLICY ALGNAME new_policy alg_option_group SEMIraZ p_alg_policyi/z>zone_policy -> ZONE domain new_policy policy_option_group SEMIrbZ p_zone_policyi6z?named_policy -> POLICY name new_policy policy_option_group SEMIrcZp_named_policyi=zduration -> NUMBERrwZ p_duration_1iCzduration -> NONEZ p_duration_2iHzduration -> NUMBER DATESUFFIXZ p_duration_3iMz7policy_option_group -> LBRACE policy_option_list RBRACErhZp_policy_option_groupi`z(policy_option_list -> policy_option SEMIrrZp_policy_option_listidz;policy_option_list -> policy_option_list policy_option SEMIiezpolicy_option -> parent_optionrsZp_policy_optioniiz!policy_option -> directory_optionijz policy_option -> coverage_optionikz"policy_option -> rollperiod_optionilz"policy_option -> prepublish_optionimz#policy_option -> postpublish_optioninzpolicy_option -> keysize_optionioz!policy_option -> algorithm_optionipzpolicy_option -> keyttl_optioniqzpolicy_option -> standby_optionirz1alg_option_group -> LBRACE alg_option_list RBRACErgZp_alg_option_groupivz"alg_option_list -> alg_option SEMIriZp_alg_option_listizz2alg_option_list -> alg_option_list alg_option SEMIi{zalg_option -> coverage_optionrjZ p_alg_optionizalg_option -> rollperiod_optionizalg_option -> prepublish_optioniz alg_option -> postpublish_optionizalg_option -> keyttl_optionizalg_option -> keysize_optionizalg_option -> standby_optionizparent_option -> POLICY namertZp_parent_optioniz%directory_option -> DIRECTORY QSTRINGruZp_directory_optioniz$coverage_option -> COVERAGE durationrkZp_coverage_optioniz1rollperiod_option -> ROLL_PERIOD KEYTYPE durationrlZp_rollperiod_optioniz1prepublish_option -> PRE_PUBLISH KEYTYPE durationrmZp_prepublish_optioniz3postpublish_option -> POST_PUBLISH KEYTYPE durationrnZp_postpublish_optioniz)keysize_option -> KEY_SIZE KEYTYPE NUMBERrpZp_keysize_optioniz(standby_option -> STANDBY KEYTYPE NUMBERrqZp_standby_optioniz keyttl_option -> KEYTTL durationroZp_keyttl_optioniz%algorithm_option -> ALGORITHM ALGNAMErvZp_algorithm_optioni)Z _tabversionZ _lr_methodZ _lr_signatureZ_lr_action_itemsZ _lr_actionitemsZ_kZ_vzipZ_xZ_yZ_lr_goto_itemsZ_lr_gotoZ_lr_productionsrzrz/usr/lib/python3.6/parsetab.pys  PK!ܴ@#__pycache__/parsetab.cpython-36.pycnu[3 f};@s dZdZdZddddddd d d d d g d ddd d d d d d d d g fddddddd d d d d g d ddd d d d d d d d g fddddddd d dd d dd ddgd ddd d d d d dd d dd d d gfddddd d d d d g dd d d d d d d d g fddgddgfdddgdddgfdd gd!d"gfddd#d$d%d&d'dgdd(d)d*d+d,d-d(gfdddd.gdd/d/d0gfdd1dd!ddddd(d/d2ddg d! d! d d d1 d d! d d d d3ddg fdd(d/d4d5d6d7d8d9d:d;dd?d@dAdBdCdDdEdFdGdHdIdJdKdLd.dMdNdOdPdQd"dd0dRdSdTdUdVg*d d d d d d dWd= d> dX d# d$ d% dY dd4 d3 d5 d d6 d dZ d7 d8 d9 d: d[d d d( dC d2 dd& d' dD d/ d d? d@ dA dB g*fd3ddZddWdd[dgdXdXdXdXd; d d< d gfd3ddZddWdd[dgd#d#d#d#d; d d< d gfd3ddZddWdd[dgd$d$d$d$d; d d< d gfd3ddZddWdd[dgd%d%d%d%d; d d< d gfd3ddZddWdd[dgdYdYdYdYd; d d< d gfd3ddZddWdd[dgd&d&d&d&d; d d< d gfd3ddZddWdd[dgd'd'd'd'd; d d< d gfddddgd d d d gfddddgddd d gfdZddWdd[dgdJdOd; d d< d gfdXdYd)d*d+d,d-gd.d.d.d.d.dUdVgfdXdYd)d*d+gdMdMdMdMdMgfd\ZiZxXejD]L\ZZx@eededD]*\Z Z e ek riee <e ee e<qWqW[dgdgfdgdgfddgdd gfddgddgfddgddgfddgd d gfdgd1gfddgddQgfdd1dgd2ddgfd2gd4gfddgd5d6gfd3gdZgfd3dZgd7dKgfd3ddZdgd8dBd8dBgfd3ddZdgd9dCd9dCgfd3ddZdgd:dDd:dDgfd3ddZdgd;dEd;dEgfd3ddZdgddId>dIgfdgdgfddgd?dPgfddgd@d@gfddgdAdAgfddgdGdGgfdXdYd)d*d+gdLdNdRdSdTgfd]Z iZ xXe jD]L\ZZx@eededD]*\Z Z e e k rie e <e e e e<qWqW[ d^d_dd`d`d`fdadbddcdddefdfdbddcdddgfdhdiddjdddkfdldmddndddofdpdmddndddqfdrdmddndddsfdtduddvdddwfdxduddvdddyfdzduddvddd{fd|d}dd~dddfdd}dd~dddfdd}dd~dddfdd}dd~dddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfdddddddfg6Z d`S(z3.8ZLALRZ C2FE91AF256AF1CCEB499107DA2CFE7E .>/MX ;= P <O()*,-EFGIJCR  !"#$%&0123456789:?@BDHKLNSTUVWA'+Q)ZALGORITHM_POLICYZZONEZPOLICYz$endZALGNAMEZSTRZQSTRINGZKEYTYPEZ DATESUFFIXLBRACESEMIZCOVERAGEZ ROLL_PERIODZ PRE_PUBLISHZ POST_PUBLISHZKEYTTLZKEY_SIZEZSTANDBYZ DIRECTORYZ ALGORITHMRBRACENUMBERZNONE) policylistinitpolicy alg_policy zone_policy named_policydomainname new_policyalg_option_grouppolicy_option_groupalg_option_list alg_optioncoverage_optionrollperiod_optionprepublish_optionpostpublish_option keyttl_optionkeysize_optionstandby_optionpolicy_option_list policy_option parent_optiondirectory_optionalgorithm_optiondurationzS' -> policylistzS'Nzpolicylist -> init policyr^Z p_policylistz policy.pyi zpolicylist -> policylist policyi zinit -> r_Zp_initizpolicy -> alg_policyr`Zp_policyizpolicy -> zone_policyizpolicy -> named_policyiz name -> STRreZp_nameizname -> KEYTYPEizname -> DATESUFFIXiz domain -> STRrdZp_domaini!zdomain -> QSTRINGi"zdomain -> KEYTYPEi#zdomain -> DATESUFFIXi$znew_policy -> rfZ p_new_policyi+zGalg_policy -> ALGORITHM_POLICY ALGNAME new_policy alg_option_group SEMIraZ p_alg_policyi/z>zone_policy -> ZONE domain new_policy policy_option_group SEMIrbZ p_zone_policyi6z?named_policy -> POLICY name new_policy policy_option_group SEMIrcZp_named_policyi=zduration -> NUMBERrwZ p_duration_1iCzduration -> NONEZ p_duration_2iHzduration -> NUMBER DATESUFFIXZ p_duration_3iMz7policy_option_group -> LBRACE policy_option_list RBRACErhZp_policy_option_groupi`z(policy_option_list -> policy_option SEMIrrZp_policy_option_listidz;policy_option_list -> policy_option_list policy_option SEMIiezpolicy_option -> parent_optionrsZp_policy_optioniiz!policy_option -> directory_optionijz policy_option -> coverage_optionikz"policy_option -> rollperiod_optionilz"policy_option -> prepublish_optionimz#policy_option -> postpublish_optioninzpolicy_option -> keysize_optionioz!policy_option -> algorithm_optionipzpolicy_option -> keyttl_optioniqzpolicy_option -> standby_optionirz1alg_option_group -> LBRACE alg_option_list RBRACErgZp_alg_option_groupivz"alg_option_list -> alg_option SEMIriZp_alg_option_listizz2alg_option_list -> alg_option_list alg_option SEMIi{zalg_option -> coverage_optionrjZ p_alg_optionizalg_option -> rollperiod_optionizalg_option -> prepublish_optioniz alg_option -> postpublish_optionizalg_option -> keyttl_optionizalg_option -> keysize_optionizalg_option -> standby_optionizparent_option -> POLICY namertZp_parent_optioniz%directory_option -> DIRECTORY QSTRINGruZp_directory_optioniz$coverage_option -> COVERAGE durationrkZp_coverage_optioniz1rollperiod_option -> ROLL_PERIOD KEYTYPE durationrlZp_rollperiod_optioniz1prepublish_option -> PRE_PUBLISH KEYTYPE durationrmZp_prepublish_optioniz3postpublish_option -> POST_PUBLISH KEYTYPE durationrnZp_postpublish_optioniz)keysize_option -> KEY_SIZE KEYTYPE NUMBERrpZp_keysize_optioniz(standby_option -> STANDBY KEYTYPE NUMBERrqZp_standby_optioniz keyttl_option -> KEYTTL durationroZp_keyttl_optioniz%algorithm_option -> ALGORITHM ALGNAMErvZp_algorithm_optioni)Z _tabversionZ _lr_methodZ _lr_signatureZ_lr_action_itemsZ _lr_actionitemsZ_kZ_vzipZ_xZ_yZ_lr_goto_itemsZ_lr_gotoZ_lr_productionsrzrz/usr/lib/python3.6/parsetab.pys  PK!LLL'__pycache__/policy.cpython-36.opt-1.pycnu[3 f2g@s:ddlZddljZddljZddlTddlmZGdddZGdddZGdd d e Z Gd d d Z e d kr6ddl Z e jd dkree jdZejZejed dZejenxe jd dkr6y4e e jddddZeejdeejdWn2e k r4ZzeejdWYddZ[XnXdS)N)*)copyc @seZdZd3Zed4ZiZdZdZdZdZ dZ ddZ ddZ d d!Z d"d#Zd$d%Zd&d'Zd(d)Zd*d+Zd,d-Zd.d/Zd0d1Zd2S)5 PolicyLexPOLICYALGORITHM_POLICYZONE ALGORITHM DIRECTORYKEYTTLKEY_SIZE ROLL_PERIOD PRE_PUBLISH POST_PUBLISHCOVERAGESTANDBYNONE DATESUFFIXKEYTYPEALGNAMESTRQSTRINGNUMBERLBRACERBRACESEMIz z (//|\#).*z\{z\};cCs|jj|jjd7_dS)z\n+ N)lexerlinenovaluecount)selftr#/usr/lib/python3.6/policy.py t_newline7szPolicyLex.t_newlinecCs|jj|jjd7_dS)z/\*(.|\n)*?\*/rN)rrrr )r!r"r#r#r$ t_comment;szPolicyLex.t_commentcCstjd|jjdj|_|S)z(?i)(?<=[0-9 \t])(y(?:ears|ear|ea|e)?|mo(?:nths|nth|nt|n)?|w(?:eeks|eek|ee|e)?|d(?:ays|ay|a)?|h(?:ours|our|ou|o)?|mi(?:nutes|nute|nut|nu|n)?|s(?:econds|econd|econ|eco|ec|e)?)\bz(?i)(y|mo|w|d|h|mi|s)([a-z]*))rematchrgrouplower)r!r"r#r#r$ t_DATESUFFIX?szPolicyLex.t_DATESUFFIXcCs|jj|_|S)z(?i)\b(KSK|ZSK)\b)rupper)r!r"r#r#r$ t_KEYTYPEDs zPolicyLex.t_KEYTYPEcCs|jj|_|S)z(?i)\b(RSAMD5|DH|DSA|NSEC3DSA|ECC|RSASHA1|NSEC3RSASHA1|RSASHA256|RSASHA512|ECCGOST|ECDSAP256SHA256|ECDSAP384SHA384|ED25519|ED448)\b)rr-)r!r"r#r#r$ t_ALGNAMEIs zPolicyLex.t_ALGNAMEcCs|jj|jd|_|S)z[A-Za-z._-][\w._-]*r) reserved_mapgetrtype)r!r"r#r#r$t_STRNszPolicyLex.t_STRcCs&|jj|jd|_|jdd|_|S)z"([^"\n]|(\\"))*"rr')r0r1rr2)r!r"r#r#r$ t_QSTRINGSszPolicyLex.t_QSTRINGcCst|j|_|S)z\d+)intr)r!r"r#r#r$t_NUMBERYs zPolicyLex.t_NUMBERcCs"td|jd|jjddS)NzIllegal character '%s'rr')printrrskip)r!r"r#r#r$t_error^szPolicyLex.t_errorcKsbdttkrtjdd}n tdd}x"|jD]}||j|jj|<q,Wtjfd|i||_dS)N maketrans_-object) dirstrr;reservedr0r+ translatelexr)r!kwargsZtransrr#r#r$__init__bs    zPolicyLex.__init__cCs.|jj|x|jj}|sPt|qWdS)N)rinputtokenr8)r!textr"r#r#r$testks   zPolicyLex.testN) rrrrr r r r r rrrr) rrrrrrrrr)__name__ __module__ __qualname__rAtokensr0Zt_ignoreZt_ignore_olcommentZt_LBRACEZt_RBRACEZt_SEMIr%r&r,r.r/r3r5r7r:rFrJr#r#r#r$rsN rc @seZdZdZdZdZdZdZdZdZ dZ dZ dZ dZ dZdZdZdZdZddgddgddgddgddgddgddgdddddd ZdddZd d Zd d Zd dZddZddZdS)PolicyFNiii) DSANSEC3DSARSAMD5RSASHA1 NSEC3RSASHA1 RSASHA256 RSASHA512ECCGOSTECDSAP256SHA256ECDSAP384SHA384ED25519ED448cCs||_||_||_dS)N)name algorithmparent)r!r\r]r^r#r#r$rFszPolicy.__init__cCsFd|jr dp"|jrdp"|jr dp"d|jp*d|jr8|jjp:d|jrRdt|jdpTd|jp\d|jrlt|jpnd|j r~t|j pd|j rt|j pd|j rt|j pd|j rt|j pd|j rt|j pd|jrt|jpd|jrt|jpd|jrt|jpd|jrt|jpd|jr(t|jp*d|jr>t|jp@dfS) Na%spolicy %s: inherits %s directory %s algorithm %s coverage %s ksk_keysize %s zsk_keysize %s ksk_rollperiod %s zsk_rollperiod %s ksk_prepublish %s ksk_postpublish %s zsk_prepublish %s zsk_postpublish %s ksk_standby %s zsk_standby %s keyttl %s z constructed zzone z algorithm ZUNKNOWNNone")is_constructedis_zoneis_algr\r^ directoryr@r]coverage ksk_keysize zsk_keysizeksk_rollperiodzsk_rollperiodksk_prepublishksk_postpublishzsk_prepublishzsk_postpublish ksk_standby zsk_standbykeyttl)r!r#r#r$__repr__s(   zPolicy.__repr__cCs |d|ko|dkSS)Nrr'r#)r!Zkey_sizeZ size_ranger#r#r$Z __verify_sizeszPolicy.__verify_sizecCs|jS)N)r\)r!r#r#r$get_nameszPolicy.get_namecCs|jS)N)rb)r!r#r#r$ constructedszPolicy.constructedcCs$|jr:|jdk r:|j|jkr:t|jdd|j|jffS|jrj|jdk rj|j|jkrjdd|j|jffS|jr|jdk r|j|jkrdd|j|jffS|jr|jdk r|j|jkrdd|j|jffS|jo|jo|jo|j|j|jkrdd|j|j|jffS|jrL|jrL|jrL|j|j|jkrLdd|j|j|jffS|jdk r |jj |j}|dk r|j |j |sdd |j |ffS|j |j |sdd |j |ffS|jdkr|j ddkrdd|j fS|jdkr|j ddkrdd|j fS|jd kr d|_ d|_ d!S)"zr Check if the values in the policy make sense :return: True/False if the policy passes validation NFz6KSK pre-publish period (%d) exceeds rollover period %dz7KSK post-publish period (%d) exceeds rollover period %dz6ZSK pre-publish period (%d) exceeds rollover period %dz7ZSK post-publish period (%d) exceeds rollover period %dz%KSK pre/post-publish periods (%d/%d) z"combined exceed rollover period %dz%ZSK pre/post-publish periods (%d/%d) z&KSK key size %d outside valid range %sz&ZSK key size %d outside valid range %srPrQ@rz$KSK key size %d not divisible by 64 zas required for DSAz$ZSK key size %d not divisible by 64 rWrXrYrZr[Tr_zGKSK pre/post-publish periods (%d/%d) combined exceed rollover period %dzGZSK pre/post-publish periods (%d/%d) combined exceed rollover period %d)rPrQz7KSK key size %d not divisible by 64 as required for DSA)rPrQz7ZSK key size %d not divisible by 64 as required for DSA)rWrXrYrZr[)Tr_) rirkr8rlrjrmrnr]valid_key_sz_per_algor1_Policy__verify_sizergrh)r!Z key_sz_ranger#r#r$validates                  zPolicy.validate)NNN)rKrLrMrcrdrbrirjrkrmrlrnrgrhrorprqrfrervrFrrrwrsrtrxr#r#r#r$rOvsD &rOc@s eZdZdS)PolicyExceptionN)rKrLrMr#r#r#r$ry)sryc@s.eZdZiZiZiZdZdZdZdEddZ ddZ ddZ d d Z d d Z d dZddZddZddZddZddZddZddZddZdd Zd!d"Zd#d$Zd%d&Zd'd(Zd)d*Zd+d,Zd-d.Zd/d0Zd1d2Z d3d4Z!d5d6Z"d7d8Z#d9d:Z$d;d<Z%d=d>Z&d?d@Z'dAdBZ(dCdDZ)dS)F dnssec_policyNTcKst|_|jj|_d|kr"d|d<d|kr2d|d<tjfd|i||_|jdt}d|_d|_d|_ d|_ t ||j d<d|j d_d|j d_ d |j d_ t ||j d <d |j d _d |j d _ d |j d _ t ||j d <d |j d _d |j d _ t ||j d <d |j d _d |j d _ t ||j d <d |j d _d |j d _ t ||j d<d|j d_d|j d_ t ||j d<d|j d_d|j d_ t ||j d<d|j d_d|j d_ t ||j d<d|j d_d|j d_ d|j d_ d|j d_ t ||j d<d|j d_d|j d_ d|j d_ d|j d_ t ||j d<d|j d_d|j d_ d|j d_ d|j d_ t ||j d<d|j d_d|j d_ d|j d_ d|j d_ |r|j|dS)NdebugF write_tablesmoduleapolicy global { algorithm rsasha256; key-size ksk 2048; key-size zsk 2048; roll-period ksk 0; roll-period zsk 1y; pre-publish ksk 1mo; pre-publish zsk 1mo; post-publish ksk 1mo; post-publish zsk 1mo; standby ksk 0; standby zsk 0; keyttl 1h; coverage 6mo; }; policy default { policy global; };TirPirQrRrSrTrUrVrWrXrYrZr[)rplexrNyaccparsersetuprOr]rdrgrhr alg_policyr\load)r!filenamerDpr#r#r$rF4s|                                    zdnssec_policy.__init__c CsH||_d|_t|$}|j}d|jj_|jj|WdQRXd|_dS)NTr) rinitialopenreadr~rrrparse)r!rfrIr#r#r$rs  zdnssec_policy.loadcCs d|_d|jj_|jj|dS)NTr)rr~rrrr)r!rIr#r#r$rs zdnssec_policy.setupc Ks`|j}d}||jkr |j|}|dkrBt|jd}||_d|_|jdkr|jpZ|jd}x|rr|j rr|j}q^W|r~|jpd|_|j|jkr|j|j}nt d|j dkr|jp|jd}x|dk r|j r|j}qW|o|j |_ |j dkr:|jp|jd}x|r"|j r"|j}qW|r2|j p6|j |_ |j dkr|jpV|jd}x|jrv|j rv|j}qZW|r|j p|j |_ |j dkr|jp|jd}x|jr|j r|j}qW|r|j p|j |_ |jdkr6|jp|jd}x|jr|j r|j}qW|r.|jp2|j|_|jdkr|jpR|jd}x|jrr|j rr|j}qVW|r|jp|j|_|jdkr|jp|jd}x|jr|j r|j}qW|r|jp|j|_|jdkr2|jp|jd}x|jr|j r|j}qW|r*|jp.|j|_|jdkr|jpN|jd}x|jrn|j rn|j}qRW|r~|jp|j|_|jdkr|jp|jd}x|jr|j r|j}qW|r|jp|j|_|jdkr(|jp|jd}x |dk r|j r|j}qW|o$|j|_d|ks>|d r\|j\}}|s\t |dS|S)NdefaultTzalgorithm not foundZ novalidate)r+ zone_policyr named_policyr\rbr]r^rryrerfrgrhrirjrkrmrlrnrqrx) r!ZzonerDzrr^ZapZvalidmsgr#r#r$policys                             zdnssec_policy.policycCsdS)zBpolicylist : init policy | policylist policyNr#)r!rr#r#r$ p_policylist szdnssec_policy.p_policylistcCs d|_dS)zinit :FN)r)r!rr#r#r$p_initszdnssec_policy.p_initcCsdS)zTpolicy : alg_policy | zone_policy | named_policyNr#)r!rr#r#r$p_policyszdnssec_policy.p_policycCs|d|d<dS)zAname : STR | KEYTYPE | DATESUFFIXr'rNr#)r!rr#r#r$p_names zdnssec_policy.p_namecCs,|dj|d<tjd|ds(tddS)zcdomain : STR | QSTRING | KEYTYPE | DATESUFFIXr'rz^[\w.-][\w.-]*$zinvalid domainN)stripr(r)ry)r!rr#r#r$p_domain szdnssec_policy.p_domaincCs t|_dS)z new_policy :N)rOcurrent)r!rr#r#r$ p_new_policy*szdnssec_policy.p_new_policycCs(|d|j_d|j_|j|j|d<dS)zFalg_policy : ALGORITHM_POLICY ALGNAME new_policy alg_option_group SEMITN)rr\rdr)r!rr#r#r$ p_alg_policy.s zdnssec_policy.p_alg_policycCs8|djd|j_d|j_|j|j|djdj<dS)z=zone_policy : ZONE domain new_policy policy_option_group SEMIr.TN)rstriprr\rcrr+)r!rr#r#r$ p_zone_policy5szdnssec_policy.p_zone_policycCs$|d|j_|j|j|dj<dS)z>named_policy : POLICY name new_policy policy_option_group SEMIrN)rr\rr+)r!rr#r#r$p_named_policy<s zdnssec_policy.p_named_policycCs|d|d<dS)zduration : NUMBERr'rNr#)r!rr#r#r$ p_duration_1Bs zdnssec_policy.p_duration_1cCs d|d<dS)zduration : NONENrr#)r!rr#r#r$ p_duration_2Gszdnssec_policy.p_duration_2cCs|ddkr|dd|d<n|ddkr<|dd|d<n|ddkrZ|dd |d<n||dd krx|dd |d<n^|dd kr|dd |d<n@|ddkr|dd|d<n"|ddkr|d|d<ntddS)zduration : NUMBER DATESUFFIXryr'i3rmoi'wi: diQhiZmi<szinvalid durationN)ry)r!rr#r#r$ p_duration_3Ls       zdnssec_policy.p_duration_3cCsdS)z6policy_option_group : LBRACE policy_option_list RBRACENr#)r!rr#r#r$p_policy_option_group_sz#dnssec_policy.p_policy_option_groupcCsdS)zmpolicy_option_list : policy_option SEMI | policy_option_list policy_option SEMINr#)r!rr#r#r$p_policy_option_listcsz"dnssec_policy.p_policy_option_listcCsdS)apolicy_option : parent_option | directory_option | coverage_option | rollperiod_option | prepublish_option | postpublish_option | keysize_option | algorithm_option | keyttl_option | standby_optionNr#)r!rr#r#r$p_policy_optionhs zdnssec_policy.p_policy_optioncCsdS)z0alg_option_group : LBRACE alg_option_list RBRACENr#)r!rr#r#r$p_alg_option_groupusz dnssec_policy.p_alg_option_groupcCsdS)z^alg_option_list : alg_option SEMI | alg_option_list alg_option SEMINr#)r!rr#r#r$p_alg_option_listyszdnssec_policy.p_alg_option_listcCsdS)aalg_option : coverage_option | rollperiod_option | prepublish_option | postpublish_option | keyttl_option | keysize_option | standby_optionNr#)r!rr#r#r$ p_alg_option~szdnssec_policy.p_alg_optioncCs|j|dj|j_dS)zparent_option : POLICY namerN)rr+rr^)r!rr#r#r$p_parent_optionszdnssec_policy.p_parent_optioncCs|d|j_dS)z$directory_option : DIRECTORY QSTRINGrN)rre)r!rr#r#r$p_directory_optionsz dnssec_policy.p_directory_optioncCs|d|j_dS)z#coverage_option : COVERAGE durationrN)rrf)r!rr#r#r$p_coverage_optionszdnssec_policy.p_coverage_optioncCs*|ddkr|d|j_n |d|j_dS)z0rollperiod_option : ROLL_PERIOD KEYTYPE durationrKSKN)rrirj)r!rr#r#r$p_rollperiod_options z!dnssec_policy.p_rollperiod_optioncCs*|ddkr|d|j_n |d|j_dS)z0prepublish_option : PRE_PUBLISH KEYTYPE durationrrrN)rrkrm)r!rr#r#r$p_prepublish_options z!dnssec_policy.p_prepublish_optioncCs*|ddkr|d|j_n |d|j_dS)z2postpublish_option : POST_PUBLISH KEYTYPE durationrrrN)rrlrn)r!rr#r#r$p_postpublish_options z"dnssec_policy.p_postpublish_optioncCs*|ddkr|d|j_n |d|j_dS)z(keysize_option : KEY_SIZE KEYTYPE NUMBERrrrN)rrgrh)r!rr#r#r$p_keysize_options zdnssec_policy.p_keysize_optioncCs*|ddkr|d|j_n |d|j_dS)z'standby_option : STANDBY KEYTYPE NUMBERrrrN)rrorp)r!rr#r#r$p_standby_options zdnssec_policy.p_standby_optioncCs|d|j_dS)zkeyttl_option : KEYTTL durationrN)rrq)r!rr#r#r$p_keyttl_optionszdnssec_policy.p_keyttl_optioncCs|d|j_dS)z$algorithm_option : ALGORITHM ALGNAMErN)rr])r!rr#r#r$p_algorithm_optionsz dnssec_policy.p_algorithm_optioncCsd|r.td|jpd|jrdnd|j|jfn2|js`td|jp@d|jrJdnd|rV|jpXdfdS)Nz%s%s%d:syntax error near '%s'r_:z%s%s%d:unexpected end of inputr)r8rrrrry)r!rr#r#r$p_errorszdnssec_policy.p_error)N)*rKrLrMrrrrrrrFrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr#r#r#r$rz,sN _ h   rz__main__r'rCr)r{rT)r|r{rznonexistent.zone)r(Zply.lexrCZply.yaccrstringrrrO ExceptionryrzrKsysargvrfilerrIcloser~rJZppr8rreargsr#r#r#r$ s6   `4!   PK!LLL!__pycache__/policy.cpython-36.pycnu[3 f2g@s:ddlZddljZddljZddlTddlmZGdddZGdddZGdd d e Z Gd d d Z e d kr6ddl Z e jd dkree jdZejZejed dZejenxe jd dkr6y4e e jddddZeejdeejdWn2e k r4ZzeejdWYddZ[XnXdS)N)*)copyc @seZdZd3Zed4ZiZdZdZdZdZ dZ ddZ ddZ d d!Z d"d#Zd$d%Zd&d'Zd(d)Zd*d+Zd,d-Zd.d/Zd0d1Zd2S)5 PolicyLexPOLICYALGORITHM_POLICYZONE ALGORITHM DIRECTORYKEYTTLKEY_SIZE ROLL_PERIOD PRE_PUBLISH POST_PUBLISHCOVERAGESTANDBYNONE DATESUFFIXKEYTYPEALGNAMESTRQSTRINGNUMBERLBRACERBRACESEMIz z (//|\#).*z\{z\};cCs|jj|jjd7_dS)z\n+ N)lexerlinenovaluecount)selftr#/usr/lib/python3.6/policy.py t_newline7szPolicyLex.t_newlinecCs|jj|jjd7_dS)z/\*(.|\n)*?\*/rN)rrrr )r!r"r#r#r$ t_comment;szPolicyLex.t_commentcCstjd|jjdj|_|S)z(?i)(?<=[0-9 \t])(y(?:ears|ear|ea|e)?|mo(?:nths|nth|nt|n)?|w(?:eeks|eek|ee|e)?|d(?:ays|ay|a)?|h(?:ours|our|ou|o)?|mi(?:nutes|nute|nut|nu|n)?|s(?:econds|econd|econ|eco|ec|e)?)\bz(?i)(y|mo|w|d|h|mi|s)([a-z]*))rematchrgrouplower)r!r"r#r#r$ t_DATESUFFIX?szPolicyLex.t_DATESUFFIXcCs|jj|_|S)z(?i)\b(KSK|ZSK)\b)rupper)r!r"r#r#r$ t_KEYTYPEDs zPolicyLex.t_KEYTYPEcCs|jj|_|S)z(?i)\b(RSAMD5|DH|DSA|NSEC3DSA|ECC|RSASHA1|NSEC3RSASHA1|RSASHA256|RSASHA512|ECCGOST|ECDSAP256SHA256|ECDSAP384SHA384|ED25519|ED448)\b)rr-)r!r"r#r#r$ t_ALGNAMEIs zPolicyLex.t_ALGNAMEcCs|jj|jd|_|S)z[A-Za-z._-][\w._-]*r) reserved_mapgetrtype)r!r"r#r#r$t_STRNszPolicyLex.t_STRcCs&|jj|jd|_|jdd|_|S)z"([^"\n]|(\\"))*"rr')r0r1rr2)r!r"r#r#r$ t_QSTRINGSszPolicyLex.t_QSTRINGcCst|j|_|S)z\d+)intr)r!r"r#r#r$t_NUMBERYs zPolicyLex.t_NUMBERcCs"td|jd|jjddS)NzIllegal character '%s'rr')printrrskip)r!r"r#r#r$t_error^szPolicyLex.t_errorcKsbdttkrtjdd}n tdd}x"|jD]}||j|jj|<q,Wtjfd|i||_dS)N maketrans_-object) dirstrr;reservedr0r+ translatelexr)r!kwargsZtransrr#r#r$__init__bs    zPolicyLex.__init__cCs.|jj|x|jj}|sPt|qWdS)N)rinputtokenr8)r!textr"r#r#r$testks   zPolicyLex.testN) rrrrr r r r r rrrr) rrrrrrrrr)__name__ __module__ __qualname__rAtokensr0Zt_ignoreZt_ignore_olcommentZt_LBRACEZt_RBRACEZt_SEMIr%r&r,r.r/r3r5r7r:rFrJr#r#r#r$rsN rc @seZdZdZdZdZdZdZdZdZ dZ dZ dZ dZ dZdZdZdZdZddgddgddgddgddgddgddgdddddd ZdddZd d Zd d Zd dZddZddZdS)PolicyFNiii) DSANSEC3DSARSAMD5RSASHA1 NSEC3RSASHA1 RSASHA256 RSASHA512ECCGOSTECDSAP256SHA256ECDSAP384SHA384ED25519ED448cCs||_||_||_dS)N)name algorithmparent)r!r\r]r^r#r#r$rFszPolicy.__init__cCsFd|jr dp"|jrdp"|jr dp"d|jp*d|jr8|jjp:d|jrRdt|jdpTd|jp\d|jrlt|jpnd|j r~t|j pd|j rt|j pd|j rt|j pd|j rt|j pd|j rt|j pd|jrt|jpd|jrt|jpd|jrt|jpd|jrt|jpd|jr(t|jp*d|jr>t|jp@dfS) Na%spolicy %s: inherits %s directory %s algorithm %s coverage %s ksk_keysize %s zsk_keysize %s ksk_rollperiod %s zsk_rollperiod %s ksk_prepublish %s ksk_postpublish %s zsk_prepublish %s zsk_postpublish %s ksk_standby %s zsk_standby %s keyttl %s z constructed zzone z algorithm ZUNKNOWNNone")is_constructedis_zoneis_algr\r^ directoryr@r]coverage ksk_keysize zsk_keysizeksk_rollperiodzsk_rollperiodksk_prepublishksk_postpublishzsk_prepublishzsk_postpublish ksk_standby zsk_standbykeyttl)r!r#r#r$__repr__s(   zPolicy.__repr__cCs |d|ko|dkSS)Nrr'r#)r!Zkey_sizeZ size_ranger#r#r$Z __verify_sizeszPolicy.__verify_sizecCs|jS)N)r\)r!r#r#r$get_nameszPolicy.get_namecCs|jS)N)rb)r!r#r#r$ constructedszPolicy.constructedcCs$|jr:|jdk r:|j|jkr:t|jdd|j|jffS|jrj|jdk rj|j|jkrjdd|j|jffS|jr|jdk r|j|jkrdd|j|jffS|jr|jdk r|j|jkrdd|j|jffS|jo|jo|jo|j|j|jkrdd|j|j|jffS|jrL|jrL|jrL|j|j|jkrLdd|j|j|jffS|jdk r |jj |j}|dk r|j |j |sdd |j |ffS|j |j |sdd |j |ffS|jdkr|j ddkrdd|j fS|jdkr|j ddkrdd|j fS|jd kr d|_ d|_ d!S)"zr Check if the values in the policy make sense :return: True/False if the policy passes validation NFz6KSK pre-publish period (%d) exceeds rollover period %dz7KSK post-publish period (%d) exceeds rollover period %dz6ZSK pre-publish period (%d) exceeds rollover period %dz7ZSK post-publish period (%d) exceeds rollover period %dz%KSK pre/post-publish periods (%d/%d) z"combined exceed rollover period %dz%ZSK pre/post-publish periods (%d/%d) z&KSK key size %d outside valid range %sz&ZSK key size %d outside valid range %srPrQ@rz$KSK key size %d not divisible by 64 zas required for DSAz$ZSK key size %d not divisible by 64 rWrXrYrZr[Tr_zGKSK pre/post-publish periods (%d/%d) combined exceed rollover period %dzGZSK pre/post-publish periods (%d/%d) combined exceed rollover period %d)rPrQz7KSK key size %d not divisible by 64 as required for DSA)rPrQz7ZSK key size %d not divisible by 64 as required for DSA)rWrXrYrZr[)Tr_) rirkr8rlrjrmrnr]valid_key_sz_per_algor1_Policy__verify_sizergrh)r!Z key_sz_ranger#r#r$validates                  zPolicy.validate)NNN)rKrLrMrcrdrbrirjrkrmrlrnrgrhrorprqrfrervrFrrrwrsrtrxr#r#r#r$rOvsD &rOc@s eZdZdS)PolicyExceptionN)rKrLrMr#r#r#r$ry)sryc@s.eZdZiZiZiZdZdZdZdEddZ ddZ ddZ d d Z d d Z d dZddZddZddZddZddZddZddZddZdd Zd!d"Zd#d$Zd%d&Zd'd(Zd)d*Zd+d,Zd-d.Zd/d0Zd1d2Z d3d4Z!d5d6Z"d7d8Z#d9d:Z$d;d<Z%d=d>Z&d?d@Z'dAdBZ(dCdDZ)dS)F dnssec_policyNTcKst|_|jj|_d|kr"d|d<d|kr2d|d<tjfd|i||_|jdt}d|_d|_d|_ d|_ t ||j d<d|j d_d|j d_ d |j d_ t ||j d <d |j d _d |j d _ d |j d _ t ||j d <d |j d _d |j d _ t ||j d <d |j d _d |j d _ t ||j d <d |j d _d |j d _ t ||j d<d|j d_d|j d_ t ||j d<d|j d_d|j d_ t ||j d<d|j d_d|j d_ t ||j d<d|j d_d|j d_ d|j d_ d|j d_ t ||j d<d|j d_d|j d_ d|j d_ d|j d_ t ||j d<d|j d_d|j d_ d|j d_ d|j d_ t ||j d<d|j d_d|j d_ d|j d_ d|j d_ |r|j|dS)NdebugF write_tablesmoduleapolicy global { algorithm rsasha256; key-size ksk 2048; key-size zsk 2048; roll-period ksk 0; roll-period zsk 1y; pre-publish ksk 1mo; pre-publish zsk 1mo; post-publish ksk 1mo; post-publish zsk 1mo; standby ksk 0; standby zsk 0; keyttl 1h; coverage 6mo; }; policy default { policy global; };TirPirQrRrSrTrUrVrWrXrYrZr[)rplexrNyaccparsersetuprOr]rdrgrhr alg_policyr\load)r!filenamerDpr#r#r$rF4s|                                    zdnssec_policy.__init__c CsH||_d|_t|$}|j}d|jj_|jj|WdQRXd|_dS)NTr) rinitialopenreadr~rrrparse)r!rfrIr#r#r$rs  zdnssec_policy.loadcCs d|_d|jj_|jj|dS)NTr)rr~rrrr)r!rIr#r#r$rs zdnssec_policy.setupc Ks`|j}d}||jkr |j|}|dkrBt|jd}||_d|_|jdkr|jpZ|jd}x|rr|j rr|j}q^W|r~|jpd|_|j|jkr|j|j}nt d|j dkr|jp|jd}x|dk r|j r|j}qW|o|j |_ |j dkr:|jp|jd}x|r"|j r"|j}qW|r2|j p6|j |_ |j dkr|jpV|jd}x|jrv|j rv|j}qZW|r|j p|j |_ |j dkr|jp|jd}x|jr|j r|j}qW|r|j p|j |_ |jdkr6|jp|jd}x|jr|j r|j}qW|r.|jp2|j|_|jdkr|jpR|jd}x|jrr|j rr|j}qVW|r|jp|j|_|jdkr|jp|jd}x|jr|j r|j}qW|r|jp|j|_|jdkr2|jp|jd}x|jr|j r|j}qW|r*|jp.|j|_|jdkr|jpN|jd}x|jrn|j rn|j}qRW|r~|jp|j|_|jdkr|jp|jd}x|jr|j r|j}qW|r|jp|j|_|jdkr(|jp|jd}x |dk r|j r|j}qW|o$|j|_d|ks>|d r\|j\}}|s\t |dS|S)NdefaultTzalgorithm not foundZ novalidate)r+ zone_policyr named_policyr\rbr]r^rryrerfrgrhrirjrkrmrlrnrqrx) r!ZzonerDzrr^ZapZvalidmsgr#r#r$policys                             zdnssec_policy.policycCsdS)zBpolicylist : init policy | policylist policyNr#)r!rr#r#r$ p_policylist szdnssec_policy.p_policylistcCs d|_dS)zinit :FN)r)r!rr#r#r$p_initszdnssec_policy.p_initcCsdS)zTpolicy : alg_policy | zone_policy | named_policyNr#)r!rr#r#r$p_policyszdnssec_policy.p_policycCs|d|d<dS)zAname : STR | KEYTYPE | DATESUFFIXr'rNr#)r!rr#r#r$p_names zdnssec_policy.p_namecCs,|dj|d<tjd|ds(tddS)zcdomain : STR | QSTRING | KEYTYPE | DATESUFFIXr'rz^[\w.-][\w.-]*$zinvalid domainN)stripr(r)ry)r!rr#r#r$p_domain szdnssec_policy.p_domaincCs t|_dS)z new_policy :N)rOcurrent)r!rr#r#r$ p_new_policy*szdnssec_policy.p_new_policycCs(|d|j_d|j_|j|j|d<dS)zFalg_policy : ALGORITHM_POLICY ALGNAME new_policy alg_option_group SEMITN)rr\rdr)r!rr#r#r$ p_alg_policy.s zdnssec_policy.p_alg_policycCs8|djd|j_d|j_|j|j|djdj<dS)z=zone_policy : ZONE domain new_policy policy_option_group SEMIr.TN)rstriprr\rcrr+)r!rr#r#r$ p_zone_policy5szdnssec_policy.p_zone_policycCs$|d|j_|j|j|dj<dS)z>named_policy : POLICY name new_policy policy_option_group SEMIrN)rr\rr+)r!rr#r#r$p_named_policy<s zdnssec_policy.p_named_policycCs|d|d<dS)zduration : NUMBERr'rNr#)r!rr#r#r$ p_duration_1Bs zdnssec_policy.p_duration_1cCs d|d<dS)zduration : NONENrr#)r!rr#r#r$ p_duration_2Gszdnssec_policy.p_duration_2cCs|ddkr|dd|d<n|ddkr<|dd|d<n|ddkrZ|dd |d<n||dd krx|dd |d<n^|dd kr|dd |d<n@|ddkr|dd|d<n"|ddkr|d|d<ntddS)zduration : NUMBER DATESUFFIXryr'i3rmoi'wi: diQhiZmi<szinvalid durationN)ry)r!rr#r#r$ p_duration_3Ls       zdnssec_policy.p_duration_3cCsdS)z6policy_option_group : LBRACE policy_option_list RBRACENr#)r!rr#r#r$p_policy_option_group_sz#dnssec_policy.p_policy_option_groupcCsdS)zmpolicy_option_list : policy_option SEMI | policy_option_list policy_option SEMINr#)r!rr#r#r$p_policy_option_listcsz"dnssec_policy.p_policy_option_listcCsdS)apolicy_option : parent_option | directory_option | coverage_option | rollperiod_option | prepublish_option | postpublish_option | keysize_option | algorithm_option | keyttl_option | standby_optionNr#)r!rr#r#r$p_policy_optionhs zdnssec_policy.p_policy_optioncCsdS)z0alg_option_group : LBRACE alg_option_list RBRACENr#)r!rr#r#r$p_alg_option_groupusz dnssec_policy.p_alg_option_groupcCsdS)z^alg_option_list : alg_option SEMI | alg_option_list alg_option SEMINr#)r!rr#r#r$p_alg_option_listyszdnssec_policy.p_alg_option_listcCsdS)aalg_option : coverage_option | rollperiod_option | prepublish_option | postpublish_option | keyttl_option | keysize_option | standby_optionNr#)r!rr#r#r$ p_alg_option~szdnssec_policy.p_alg_optioncCs|j|dj|j_dS)zparent_option : POLICY namerN)rr+rr^)r!rr#r#r$p_parent_optionszdnssec_policy.p_parent_optioncCs|d|j_dS)z$directory_option : DIRECTORY QSTRINGrN)rre)r!rr#r#r$p_directory_optionsz dnssec_policy.p_directory_optioncCs|d|j_dS)z#coverage_option : COVERAGE durationrN)rrf)r!rr#r#r$p_coverage_optionszdnssec_policy.p_coverage_optioncCs*|ddkr|d|j_n |d|j_dS)z0rollperiod_option : ROLL_PERIOD KEYTYPE durationrKSKN)rrirj)r!rr#r#r$p_rollperiod_options z!dnssec_policy.p_rollperiod_optioncCs*|ddkr|d|j_n |d|j_dS)z0prepublish_option : PRE_PUBLISH KEYTYPE durationrrrN)rrkrm)r!rr#r#r$p_prepublish_options z!dnssec_policy.p_prepublish_optioncCs*|ddkr|d|j_n |d|j_dS)z2postpublish_option : POST_PUBLISH KEYTYPE durationrrrN)rrlrn)r!rr#r#r$p_postpublish_options z"dnssec_policy.p_postpublish_optioncCs*|ddkr|d|j_n |d|j_dS)z(keysize_option : KEY_SIZE KEYTYPE NUMBERrrrN)rrgrh)r!rr#r#r$p_keysize_options zdnssec_policy.p_keysize_optioncCs*|ddkr|d|j_n |d|j_dS)z'standby_option : STANDBY KEYTYPE NUMBERrrrN)rrorp)r!rr#r#r$p_standby_options zdnssec_policy.p_standby_optioncCs|d|j_dS)zkeyttl_option : KEYTTL durationrN)rrq)r!rr#r#r$p_keyttl_optionszdnssec_policy.p_keyttl_optioncCs|d|j_dS)z$algorithm_option : ALGORITHM ALGNAMErN)rr])r!rr#r#r$p_algorithm_optionsz dnssec_policy.p_algorithm_optioncCsd|r.td|jpd|jrdnd|j|jfn2|js`td|jp@d|jrJdnd|rV|jpXdfdS)Nz%s%s%d:syntax error near '%s'r_:z%s%s%d:unexpected end of inputr)r8rrrrry)r!rr#r#r$p_errorszdnssec_policy.p_error)N)*rKrLrMrrrrrrrFrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr#r#r#r$rz,sN _ h   rz__main__r'rCr)r{rT)r|r{rznonexistent.zone)r(Zply.lexrCZply.yaccrstringrrrO ExceptionryrzrKsysargvrfilerrIcloser~rJZppr8rreargsr#r#r#r$ s6   `4!   PK!S%__pycache__/rndc.cpython-36.opt-1.pycnu[3 f+@sXddlmZddlZddlZddlZddlZddlZddlZddlZGddde Z dS)) OrderedDictNc@sleZdZdZdddddddZd d Zd d ZdddZddZddZ ddZ ddZ ddZ ddZ dS)rndczRNDC protocol client library)md5Zsha1Zsha224Zsha256Zsha384Zsha512cCsb||_|j}|jdr$|dd}||_tt||_tj||_ t j dd|_ d|_ |jdS)zCreates a persistent connection to RNDC and logs in host - (ip, port) tuple algo - HMAC algorithm: one of md5, sha1, sha224, sha256, sha384, sha512 (with optional prefix 'hmac-') secret - HMAC secret, base64 encodedzhmac-Nri)hostlower startswithalgogetattrhashlibhlalgobase64 b64decodesecretrandomZrandintsernonce_rndc__connect_login)selfrrrr/usr/lib/python3.6/rndc.py__init__$s    z rndc.__init__cCst|j|ddS)zCall a RNDC command, all parsing is done on the server side cmd - a complete string with a command (eg 'reload zone example.com') )type_data)dict_rndc__command)rcmdrrrcall5sz rndc.callFcCst}x|jD]\}}|r(|dkr(q|tjdt||jd7}t|tkrt|tjddt||jd7}qt|tkr|tjddt||7}qt|tkr|tjddt||7}qt|t kr|j |}|tjddt||7}qt dt|qW|S)N_authBasciiz>BIr z#Cannot serialize element of type %s) bytearrayitemsstructpacklenencoder strbytesr_rndc__serialize_dictNotImplementedError)rdata ignore_authrvkvZsdrrrZ__serialize_dict;s"  "    zrndc.__serialize_dictc Os,|jd7_ttj}t||}t}t|d<t|d<t|j|dd<t||dd<t|d|dd<|jdk r|j|dd<||d <|j|d d }tj|j ||j j }t j |}|jd krtjd ||dd<n"ttjd|j|j||dd<|j|}tjdt|dd|}|S)Nr r&_ctrlZ_serZ_tim<Z_exp_noncer!T)r5r Z22shmd5ZB88shshaz>II)rinttimerr0rr2hmacnewrrdigestrZ b64encoderr,r-r* _rndc__algosr.) rargskwargsZnowr4dmsghashbhashrrrZ__prep_messageOs,        zrndc.__prep_messagecCs|jdk r |dd|jkr dS|jdkr8|dd}n|dddd}t|tkrb|jd }|d d t|d 7}tj|}|j|d d }t j |j ||j j }||kS)Nr9r;Fr r&r<r=r r(=r>T)r5)rrr r1decoder.rrr2rArBrrrC)rrHrJZ remote_hashZmy_msgZmy_hashrrrZ __verify_msgjs    zrndc.__verify_msgc Os|j||}|jj|}|t|kr,td|jjd}t|dkrLtdtjd|\}}|dkrptd||d8}|jj|tj }t||krtdt |t krt |}|j |}|j|std |S) NzCannot send the messagezCan't read response headerz>IIr zWrong message version %dr>zCan't read response datazAuthentication failure)_rndc__prep_messagesocketsendr.IOErrorZrecvr,unpackr3Z MSG_WAITALLr r0r*_rndc__parse_message_rndc__verify_msg) rrErFrHZsentheaderZlengthversionr4rrrZ __commandys(          zrndc.__commandcCs2tj|j|_d|_|jdd}|dd|_dS)NZnull)r r9r;)rOZcreate_connectionrrr#)rrHrrrZ__connect_logins zrndc.__connect_loginc Csd}||}|d7}||||jd}||7}||}|d7}tjd|||dd}|d7}||||}||7}||d}|dkr|||fS|dkrt} x(t|dkr|j|\} } }| | | <qW|| |fStd|dS)Nrr r(z>Ir>r)zUnknown element type %d)rLr,rRrr._rndc__parse_elementr3) rinputposZlabellenlabelr Zdatalenr4restrGZilabelvaluerrrZ__parse_elements*    zrndc.__parse_elementcCs8t}d}x(t|dkr2|j|\}}}|||<q W|S)Nr)rr.rW)rrXr6ZhdatarZr\rrrZ__parse_messages  zrndc.__parse_messageN)F)__name__ __module__ __qualname____doc__rDrr%r2rNrTr#rrWrSrrrrrs  r) collectionsrr@r,rrArrrOobjectrrrrrs PK!S__pycache__/rndc.cpython-36.pycnu[3 f+@sXddlmZddlZddlZddlZddlZddlZddlZddlZGddde Z dS)) OrderedDictNc@sleZdZdZdddddddZd d Zd d ZdddZddZddZ ddZ ddZ ddZ ddZ dS)rndczRNDC protocol client library)md5Zsha1Zsha224Zsha256Zsha384Zsha512cCsb||_|j}|jdr$|dd}||_tt||_tj||_ t j dd|_ d|_ |jdS)zCreates a persistent connection to RNDC and logs in host - (ip, port) tuple algo - HMAC algorithm: one of md5, sha1, sha224, sha256, sha384, sha512 (with optional prefix 'hmac-') secret - HMAC secret, base64 encodedzhmac-Nri)hostlower startswithalgogetattrhashlibhlalgobase64 b64decodesecretrandomZrandintsernonce_rndc__connect_login)selfrrrr/usr/lib/python3.6/rndc.py__init__$s    z rndc.__init__cCst|j|ddS)zCall a RNDC command, all parsing is done on the server side cmd - a complete string with a command (eg 'reload zone example.com') )type_data)dict_rndc__command)rcmdrrrcall5sz rndc.callFcCst}x|jD]\}}|r(|dkr(q|tjdt||jd7}t|tkrt|tjddt||jd7}qt|tkr|tjddt||7}qt|tkr|tjddt||7}qt|t kr|j |}|tjddt||7}qt dt|qW|S)N_authBasciiz>BIr z#Cannot serialize element of type %s) bytearrayitemsstructpacklenencoder strbytesr_rndc__serialize_dictNotImplementedError)rdata ignore_authrvkvZsdrrrZ__serialize_dict;s"  "    zrndc.__serialize_dictc Os,|jd7_ttj}t||}t}t|d<t|d<t|j|dd<t||dd<t|d|dd<|jdk r|j|dd<||d <|j|d d }tj|j ||j j }t j |}|jd krtjd ||dd<n"ttjd|j|j||dd<|j|}tjdt|dd|}|S)Nr r&_ctrlZ_serZ_tim<Z_exp_noncer!T)r5r Z22shmd5ZB88shshaz>II)rinttimerr0rr2hmacnewrrdigestrZ b64encoderr,r-r* _rndc__algosr.) rargskwargsZnowr4dmsghashbhashrrrZ__prep_messageOs,        zrndc.__prep_messagecCs|jdk r |dd|jkr dS|jdkr8|dd}n|dddd}t|tkrb|jd }|d d t|d 7}tj|}|j|d d }t j |j ||j j }||kS)Nr9r;Fr r&r<r=r r(=r>T)r5)rrr r1decoder.rrr2rArBrrrC)rrHrJZ remote_hashZmy_msgZmy_hashrrrZ __verify_msgjs    zrndc.__verify_msgc Os|j||}|jj|}|t|kr,td|jjd}t|dkrLtdtjd|\}}|dkrptd||d8}|jj|tj }t||krtdt |t krt |}|j |}|j|std |S) NzCannot send the messagezCan't read response headerz>IIr zWrong message version %dr>zCan't read response datazAuthentication failure)_rndc__prep_messagesocketsendr.IOErrorZrecvr,unpackr3Z MSG_WAITALLr r0r*_rndc__parse_message_rndc__verify_msg) rrErFrHZsentheaderZlengthversionr4rrrZ __commandys(          zrndc.__commandcCs2tj|j|_d|_|jdd}|dd|_dS)NZnull)r r9r;)rOZcreate_connectionrrr#)rrHrrrZ__connect_logins zrndc.__connect_loginc Csd}||}|d7}||||jd}||7}||}|d7}tjd|||dd}|d7}||||}||7}||d}|dkr|||fS|dkrt} x(t|dkr|j|\} } }| | | <qW|| |fStd|dS)Nrr r(z>Ir>r)zUnknown element type %d)rLr,rRrr._rndc__parse_elementr3) rinputposZlabellenlabelr Zdatalenr4restrGZilabelvaluerrrZ__parse_elements*    zrndc.__parse_elementcCs8t}d}x(t|dkr2|j|\}}}|||<q W|S)Nr)rr.rW)rrXr6ZhdatarZr\rrrZ__parse_messages  zrndc.__parse_messageN)F)__name__ __module__ __qualname____doc__rDrr%r2rNrTr#rrWrSrrrrrs  r) collectionsrr@r,rrArrrOobjectrrrrrs PK!`J __init__.pynu[############################################################################ # Copyright (C) Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, you can obtain one at https://mozilla.org/MPL/2.0/. # # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. ############################################################################ __all__ = ['checkds', 'coverage', 'keymgr', 'dnskey', 'eventlist', 'keydict', 'keyevent', 'keyseries', 'keyzone', 'policy', 'parsetab', 'rndc', 'utils'] from isc.dnskey import * from isc.eventlist import * from isc.keydict import * from isc.keyevent import * from isc.keyseries import * from isc.keyzone import * from isc.policy import * from isc.rndc import * from isc.utils import * PK!'ס&& checkds.pynu[############################################################################ # Copyright (C) Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, you can obtain one at https://mozilla.org/MPL/2.0/. # # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. ############################################################################ import argparse import os import sys from subprocess import Popen, PIPE from isc.utils import prefix,version prog = 'dnssec-checkds' ############################################################################ # SECRR class: # Class for DS/DLV resource record ############################################################################ class SECRR: hashalgs = {1: 'SHA-1', 2: 'SHA-256', 3: 'GOST', 4: 'SHA-384'} rrname = '' rrclass = 'IN' keyid = None keyalg = None hashalg = None digest = '' ttl = 0 def __init__(self, rrtext, dlvname = None): if not rrtext: raise Exception # 'str' does not have decode method in python3 if type(rrtext) is not str: fields = rrtext.decode('ascii').split() else: fields = rrtext.split() if len(fields) < 7: raise Exception if dlvname: self.rrtype = "DLV" self.dlvname = dlvname.lower() parent = fields[0].lower().strip('.').split('.') parent.reverse() dlv = dlvname.split('.') dlv.reverse() while len(dlv) != 0 and len(parent) != 0 and parent[0] == dlv[0]: parent = parent[1:] dlv = dlv[1:] if dlv: raise Exception parent.reverse() self.parent = '.'.join(parent) self.rrname = self.parent + '.' + self.dlvname + '.' else: self.rrtype = "DS" self.rrname = fields[0].lower() fields = fields[1:] if fields[0].upper() in ['IN', 'CH', 'HS']: self.rrclass = fields[0].upper() fields = fields[1:] else: self.ttl = int(fields[0]) self.rrclass = fields[1].upper() fields = fields[2:] if fields[0].upper() != self.rrtype: raise Exception('%s does not match %s' % (fields[0].upper(), self.rrtype)) self.keyid, self.keyalg, self.hashalg = map(int, fields[1:4]) self.digest = ''.join(fields[4:]).upper() def __repr__(self): return '%s %s %s %d %d %d %s' % \ (self.rrname, self.rrclass, self.rrtype, self.keyid, self.keyalg, self.hashalg, self.digest) def __eq__(self, other): return self.__repr__() == other.__repr__() ############################################################################ # check: # Fetch DS/DLV RRset for the given zone from the DNS; fetch DNSKEY # RRset from the masterfile if specified, or from DNS if not. # Generate a set of expected DS/DLV records from the DNSKEY RRset, # and report on congruency. ############################################################################ def check(zone, args, masterfile=None, lookaside=None): rrlist = [] cmd = [args.dig, "+noall", "+answer", "-t", "dlv" if lookaside else "ds", "-q", zone + "." + lookaside if lookaside else zone] fp, _ = Popen(cmd, stdout=PIPE).communicate() for line in fp.splitlines(): if type(line) is not str: line = line.decode('ascii') rrlist.append(SECRR(line, lookaside)) rrlist = sorted(rrlist, key=lambda rr: (rr.keyid, rr.keyalg, rr.hashalg)) klist = [] if masterfile: cmd = [args.dsfromkey, "-f", masterfile] if lookaside: cmd += ["-l", lookaside] cmd.append(zone) fp, _ = Popen(cmd, stdout=PIPE).communicate() else: intods, _ = Popen([args.dig, "+noall", "+answer", "-t", "dnskey", "-q", zone], stdout=PIPE).communicate() cmd = [args.dsfromkey, "-f", "-"] if lookaside: cmd += ["-l", lookaside] cmd.append(zone) fp, _ = Popen(cmd, stdin=PIPE, stdout=PIPE).communicate(intods) for line in fp.splitlines(): if type(line) is not str: line = line.decode('ascii') klist.append(SECRR(line, lookaside)) if len(klist) < 1: print("No DNSKEY records found in zone apex") return False found = False for rr in klist: if rr in rrlist: print("%s for KSK %s/%03d/%05d (%s) found in parent" % (rr.rrtype, rr.rrname.strip('.'), rr.keyalg, rr.keyid, SECRR.hashalgs[rr.hashalg])) found = True else: print("%s for KSK %s/%03d/%05d (%s) missing from parent" % (rr.rrtype, rr.rrname.strip('.'), rr.keyalg, rr.keyid, SECRR.hashalgs[rr.hashalg])) if not found: print("No %s records were found for any DNSKEY" % ("DLV" if lookaside else "DS")) return found ############################################################################ # parse_args: # Read command line arguments, set global 'args' structure ############################################################################ def parse_args(): parser = argparse.ArgumentParser(description=prog + ': checks DS coverage') bindir = 'bin' sbindir = 'bin' if os.name == 'nt' else 'sbin' parser.add_argument('zone', type=str, help='zone to check') parser.add_argument('-f', '--file', dest='masterfile', type=str, help='zone master file') parser.add_argument('-l', '--lookaside', dest='lookaside', type=str, help='DLV lookaside zone') parser.add_argument('-d', '--dig', dest='dig', default=os.path.join(prefix(bindir), 'dig'), type=str, help='path to \'dig\'') parser.add_argument('-D', '--dsfromkey', dest='dsfromkey', default=os.path.join(prefix(sbindir), 'dnssec-dsfromkey'), type=str, help='path to \'dnssec-dsfromkey\'') parser.add_argument('-v', '--version', action='version', version=version) args = parser.parse_args() args.zone = args.zone.strip('.') if args.lookaside: args.lookaside = args.lookaside.strip('.') return args ############################################################################ # Main ############################################################################ def main(): args = parse_args() found = check(args.zone, args, args.masterfile, args.lookaside) exit(0 if found else 1) PK!5&& coverage.pynu[############################################################################ # Copyright (C) Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, you can obtain one at https://mozilla.org/MPL/2.0/. # # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. ############################################################################ from __future__ import print_function import os import sys import argparse import glob import re import time import calendar import pprint from collections import defaultdict prog = 'dnssec-coverage' from isc import dnskey, eventlist, keydict, keyevent, keyzone, utils ############################################################################ # print a fatal error and exit ############################################################################ def fatal(*args, **kwargs): print(*args, **kwargs) sys.exit(1) ############################################################################ # output: ############################################################################ _firstline = True def output(*args, **kwargs): """output text, adding a vertical space this is *not* the first first section being printed since a call to vreset()""" global _firstline if 'skip' in kwargs: skip = kwargs['skip'] kwargs.pop('skip', None) else: skip = True if _firstline: _firstline = False elif skip: print('') if args: print(*args, **kwargs) def vreset(): """reset vertical spacing""" global _firstline _firstline = True ############################################################################ # parse_time ############################################################################ def parse_time(s): """ convert a formatted time (e.g., 1y, 6mo, 15mi, etc) into seconds :param s: String with some text representing a time interval :return: Integer with the number of seconds in the time interval """ s = s.strip() # if s is an integer, we're done already try: return int(s) except ValueError: pass # try to parse as a number with a suffix indicating unit of time r = re.compile(r'([0-9][0-9]*)\s*([A-Za-z]*)') m = r.match(s) if not m: raise ValueError("Cannot parse %s" % s) n, unit = m.groups() n = int(n) unit = unit.lower() if unit.startswith('y'): return n * 31536000 elif unit.startswith('mo'): return n * 2592000 elif unit.startswith('w'): return n * 604800 elif unit.startswith('d'): return n * 86400 elif unit.startswith('h'): return n * 3600 elif unit.startswith('mi'): return n * 60 elif unit.startswith('s'): return n else: raise ValueError("Invalid suffix %s" % unit) ############################################################################ # set_path: ############################################################################ def set_path(command, default=None): """ find the location of a specified command. if a default is supplied and it works, we use it; otherwise we search PATH for a match. :param command: string with a command to look for in the path :param default: default location to use :return: detected location for the desired command """ fpath = default if not fpath or not os.path.isfile(fpath) or not os.access(fpath, os.X_OK): path = os.environ["PATH"] if not path: path = os.path.defpath for directory in path.split(os.pathsep): fpath = os.path.join(directory, command) if os.path.isfile(fpath) and os.access(fpath, os.X_OK): break fpath = None return fpath ############################################################################ # parse_args: ############################################################################ def parse_args(): """Read command line arguments, set global 'args' structure""" compilezone = set_path('named-compilezone', os.path.join(utils.prefix('sbin'), 'named-compilezone')) parser = argparse.ArgumentParser(description=prog + ': checks future ' + 'DNSKEY coverage for a zone') parser.add_argument('zone', type=str, nargs='*', default=None, help='zone(s) to check' + '(default: all zones in the directory)') parser.add_argument('-K', dest='path', default='.', type=str, help='a directory containing keys to process', metavar='dir') parser.add_argument('-f', dest='filename', type=str, help='zone master file', metavar='file') parser.add_argument('-m', dest='maxttl', type=str, help='the longest TTL in the zone(s)', metavar='time') parser.add_argument('-d', dest='keyttl', type=str, help='the DNSKEY TTL', metavar='time') parser.add_argument('-r', dest='resign', default='1944000', type=str, help='the RRSIG refresh interval ' 'in seconds [default: 22.5 days]', metavar='time') parser.add_argument('-c', dest='compilezone', default=compilezone, type=str, help='path to \'named-compilezone\'', metavar='path') parser.add_argument('-l', dest='checklimit', type=str, default='0', help='Length of time to check for ' 'DNSSEC coverage [default: 0 (unlimited)]', metavar='time') parser.add_argument('-z', dest='no_ksk', action='store_true', default=False, help='Only check zone-signing keys (ZSKs)') parser.add_argument('-k', dest='no_zsk', action='store_true', default=False, help='Only check key-signing keys (KSKs)') parser.add_argument('-D', '--debug', dest='debug_mode', action='store_true', default=False, help='Turn on debugging output') parser.add_argument('-v', '--version', action='version', version=utils.version) args = parser.parse_args() if args.no_zsk and args.no_ksk: fatal("ERROR: -z and -k cannot be used together.") elif args.no_zsk or args.no_ksk: args.keytype = "KSK" if args.no_zsk else "ZSK" else: args.keytype = None if args.filename and len(args.zone) > 1: fatal("ERROR: -f can only be used with one zone.") # strip trailing dots if any args.zone = [x[:-1] if (len(x) > 1 and x[-1] == '.') else x for x in args.zone] # convert from time arguments to seconds try: if args.maxttl: m = parse_time(args.maxttl) args.maxttl = m except ValueError: pass try: if args.keyttl: k = parse_time(args.keyttl) args.keyttl = k except ValueError: pass try: if args.resign: r = parse_time(args.resign) args.resign = r except ValueError: pass try: if args.checklimit: lim = args.checklimit r = parse_time(args.checklimit) if r == 0: args.checklimit = None else: args.checklimit = time.time() + r except ValueError: pass # if we've got the values we need from the command line, stop now if args.maxttl and args.keyttl: return args # load keyttl and maxttl data from zonefile if args.zone and args.filename: try: zone = keyzone(args.zone[0], args.filename, args.compilezone) args.maxttl = args.maxttl or zone.maxttl args.keyttl = args.maxttl or zone.keyttl except Exception as e: print("Unable to load zone data from %s: " % args.filename, e) if not args.maxttl: output("WARNING: Maximum TTL value was not specified. Using 1 week\n" "\t (604800 seconds); re-run with the -m option to get more\n" "\t accurate results.") args.maxttl = 604800 return args ############################################################################ # Main ############################################################################ def main(): args = parse_args() print("PHASE 1--Loading keys to check for internal timing problems") try: kd = keydict(path=args.path, zones=args.zone, keyttl=args.keyttl) except Exception as e: fatal('ERROR: Unable to build key dictionary: ' + str(e)) for key in kd: key.check_prepub(output) if key.sep: key.check_postpub(output) else: key.check_postpub(output, args.maxttl + args.resign) output("PHASE 2--Scanning future key events for coverage failures") vreset() try: elist = eventlist(kd) except Exception as e: fatal('ERROR: Unable to build event list: ' + str(e)) errors = False if not args.zone: if not elist.coverage(None, args.keytype, args.checklimit, output): errors = True else: for zone in args.zone: try: if not elist.coverage(zone, args.keytype, args.checklimit, output): errors = True except: output('ERROR: Coverage check failed for zone ' + zone) sys.exit(1 if errors else 0) PK!WC @ @ dnskey.pynu[############################################################################ # Copyright (C) Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, you can obtain one at https://mozilla.org/MPL/2.0/. # # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. ############################################################################ import os import time import calendar from subprocess import Popen, PIPE ######################################################################## # Class dnskey ######################################################################## class TimePast(Exception): def __init__(self, key, prop, value): super(TimePast, self).__init__('%s time for key %s (%d) is already past' % (prop, key, value)) class dnskey: """An individual DNSSEC key. Identified by path, name, algorithm, keyid. Contains a dictionary of metadata events.""" _PROPS = ('Created', 'Publish', 'Activate', 'Inactive', 'Delete', 'Revoke', 'DSPublish', 'SyncPublish', 'SyncDelete') _OPTS = (None, '-P', '-A', '-I', '-D', '-R', None, '-Psync', '-Dsync') _ALGNAMES = (None, 'RSAMD5', 'DH', 'DSA', 'ECC', 'RSASHA1', 'NSEC3DSA', 'NSEC3RSASHA1', 'RSASHA256', None, 'RSASHA512', None, 'ECCGOST', 'ECDSAP256SHA256', 'ECDSAP384SHA384', 'ED25519', 'ED448') def __init__(self, key, directory=None, keyttl=None): # this makes it possible to use algname as a class or instance method if isinstance(key, tuple) and len(key) == 3: self._dir = directory or '.' (name, alg, keyid) = key self.fromtuple(name, alg, keyid, keyttl) self._dir = directory or os.path.dirname(key) or '.' key = os.path.basename(key) (name, alg, keyid) = key.split('+') name = name[1:-1] alg = int(alg) keyid = int(keyid.split('.')[0]) self.fromtuple(name, alg, keyid, keyttl) def fromtuple(self, name, alg, keyid, keyttl): if name.endswith('.'): fullname = name name = name.rstrip('.') else: fullname = name + '.' keystr = "K%s+%03d+%05d" % (fullname, alg, keyid) key_file = self._dir + (self._dir and os.sep or '') + keystr + ".key" private_file = (self._dir + (self._dir and os.sep or '') + keystr + ".private") self.keystr = keystr self.name = name self.alg = int(alg) self.keyid = int(keyid) self.fullname = fullname kfp = open(key_file, "r") for line in kfp: if line[0] == ';': continue tokens = line.split() if not tokens: continue if tokens[1].lower() in ('in', 'ch', 'hs'): septoken = 3 self.ttl = keyttl else: septoken = 4 self.ttl = int(tokens[1]) if not keyttl else keyttl if (int(tokens[septoken]) & 0x1) == 1: self.sep = True else: self.sep = False kfp.close() pfp = open(private_file, "rU") self.metadata = dict() self._changed = dict() self._delete = dict() self._times = dict() self._fmttime = dict() self._timestamps = dict() self._original = dict() self._origttl = None for line in pfp: line = line.strip() if not line or line[0] in ('!#'): continue punctuation = [line.find(c) for c in ':= '] + [len(line)] found = min([pos for pos in punctuation if pos != -1]) name = line[:found].rstrip() value = line[found:].lstrip(":= ").rstrip() self.metadata[name] = value for prop in dnskey._PROPS: self._changed[prop] = False if prop in self.metadata: t = self.parsetime(self.metadata[prop]) self._times[prop] = t self._fmttime[prop] = self.formattime(t) self._timestamps[prop] = self.epochfromtime(t) self._original[prop] = self._timestamps[prop] else: self._times[prop] = None self._fmttime[prop] = None self._timestamps[prop] = None self._original[prop] = None pfp.close() def commit(self, settime_bin, **kwargs): quiet = kwargs.get('quiet', False) cmd = [] first = True if self._origttl is not None: cmd += ["-L", str(self.ttl)] for prop, opt in zip(dnskey._PROPS, dnskey._OPTS): if not opt or not self._changed[prop]: continue delete = False if prop in self._delete and self._delete[prop]: delete = True when = 'none' if delete else self._fmttime[prop] cmd += [opt, when] first = False if cmd: fullcmd = [settime_bin, "-K", self._dir] + cmd + [self.keystr,] if not quiet: print('# ' + ' '.join(fullcmd)) try: p = Popen(fullcmd, stdout=PIPE, stderr=PIPE) stdout, stderr = p.communicate() if stderr: raise Exception(str(stderr)) except Exception as e: raise Exception('unable to run %s: %s' % (settime_bin, str(e))) self._origttl = None for prop in dnskey._PROPS: self._original[prop] = self._timestamps[prop] self._changed[prop] = False @classmethod def generate(cls, keygen_bin, randomdev, keys_dir, name, alg, keysize, sep, ttl, publish=None, activate=None, **kwargs): quiet = kwargs.get('quiet', False) keygen_cmd = [keygen_bin, "-q", "-K", keys_dir, "-L", str(ttl)] if randomdev: keygen_cmd += ["-r", randomdev] if sep: keygen_cmd.append("-fk") if alg: keygen_cmd += ["-a", alg] if keysize: keygen_cmd += ["-b", str(keysize)] if publish: t = dnskey.timefromepoch(publish) keygen_cmd += ["-P", dnskey.formattime(t)] if activate: t = dnskey.timefromepoch(activate) keygen_cmd += ["-A", dnskey.formattime(activate)] keygen_cmd.append(name) if not quiet: print('# ' + ' '.join(keygen_cmd)) p = Popen(keygen_cmd, stdout=PIPE, stderr=PIPE) stdout, stderr = p.communicate() if stderr: raise Exception('unable to generate key: ' + str(stderr)) try: keystr = stdout.splitlines()[0].decode('ascii') newkey = dnskey(keystr, keys_dir, ttl) return newkey except Exception as e: raise Exception('unable to parse generated key: %s' % str(e)) def generate_successor(self, keygen_bin, randomdev, prepublish, **kwargs): quiet = kwargs.get('quiet', False) if not self.inactive(): raise Exception("predecessor key %s has no inactive date" % self) keygen_cmd = [keygen_bin, "-q", "-K", self._dir, "-S", self.keystr] if self.ttl: keygen_cmd += ["-L", str(self.ttl)] if randomdev: keygen_cmd += ["-r", randomdev] if prepublish: keygen_cmd += ["-i", str(prepublish)] if not quiet: print('# ' + ' '.join(keygen_cmd)) p = Popen(keygen_cmd, stdout=PIPE, stderr=PIPE) stdout, stderr = p.communicate() if stderr: raise Exception('unable to generate key: ' + stderr) try: keystr = stdout.splitlines()[0].decode('ascii') newkey = dnskey(keystr, self._dir, self.ttl) return newkey except: raise Exception('unable to generate successor for key %s' % self) @staticmethod def algstr(alg): name = None if alg in range(len(dnskey._ALGNAMES)): name = dnskey._ALGNAMES[alg] return name if name else ("%03d" % alg) @staticmethod def algnum(alg): if not alg: return None alg = alg.upper() try: return dnskey._ALGNAMES.index(alg) except ValueError: return None def algname(self, alg=None): return self.algstr(alg or self.alg) @staticmethod def timefromepoch(secs): return time.gmtime(secs) @staticmethod def parsetime(string): return time.strptime(string, "%Y%m%d%H%M%S") @staticmethod def epochfromtime(t): return calendar.timegm(t) @staticmethod def formattime(t): return time.strftime("%Y%m%d%H%M%S", t) def setmeta(self, prop, secs, now, **kwargs): force = kwargs.get('force', False) if self._timestamps[prop] == secs: return if self._original[prop] is not None and \ self._original[prop] < now and not force: raise TimePast(self, prop, self._original[prop]) if secs is None: self._changed[prop] = False \ if self._original[prop] is None else True self._delete[prop] = True self._timestamps[prop] = None self._times[prop] = None self._fmttime[prop] = None return t = self.timefromepoch(secs) self._timestamps[prop] = secs self._times[prop] = t self._fmttime[prop] = self.formattime(t) self._changed[prop] = False if \ self._original[prop] == self._timestamps[prop] else True def gettime(self, prop): return self._times[prop] def getfmttime(self, prop): return self._fmttime[prop] def gettimestamp(self, prop): return self._timestamps[prop] def created(self): return self._timestamps["Created"] def syncpublish(self): return self._timestamps["SyncPublish"] def setsyncpublish(self, secs, now=time.time(), **kwargs): self.setmeta("SyncPublish", secs, now, **kwargs) def publish(self): return self._timestamps["Publish"] def setpublish(self, secs, now=time.time(), **kwargs): self.setmeta("Publish", secs, now, **kwargs) def activate(self): return self._timestamps["Activate"] def setactivate(self, secs, now=time.time(), **kwargs): self.setmeta("Activate", secs, now, **kwargs) def revoke(self): return self._timestamps["Revoke"] def setrevoke(self, secs, now=time.time(), **kwargs): self.setmeta("Revoke", secs, now, **kwargs) def inactive(self): return self._timestamps["Inactive"] def setinactive(self, secs, now=time.time(), **kwargs): self.setmeta("Inactive", secs, now, **kwargs) def delete(self): return self._timestamps["Delete"] def setdelete(self, secs, now=time.time(), **kwargs): self.setmeta("Delete", secs, now, **kwargs) def syncdelete(self): return self._timestamps["SyncDelete"] def setsyncdelete(self, secs, now=time.time(), **kwargs): self.setmeta("SyncDelete", secs, now, **kwargs) def setttl(self, ttl): if ttl is None or self.ttl == ttl: return elif self._origttl is None: self._origttl = self.ttl self.ttl = ttl elif self._origttl == ttl: self._origttl = None self.ttl = ttl else: self.ttl = ttl def keytype(self): return ("KSK" if self.sep else "ZSK") def __str__(self): return ("%s/%s/%05d" % (self.name, self.algname(), self.keyid)) def __repr__(self): return ("%s/%s/%05d (%s)" % (self.name, self.algname(), self.keyid, ("KSK" if self.sep else "ZSK"))) def date(self): return (self.activate() or self.publish() or self.created()) # keys are sorted first by zone name, then by algorithm. within # the same name/algorithm, they are sorted according to their # 'date' value: the activation date if set, OR the publication # if set, OR the creation date. def __lt__(self, other): if self.name != other.name: return self.name < other.name if self.alg != other.alg: return self.alg < other.alg return self.date() < other.date() def check_prepub(self, output=None): def noop(*args, **kwargs): pass if not output: output = noop now = int(time.time()) a = self.activate() p = self.publish() if not a: return False if not p: if a > now: output("WARNING: Key %s is scheduled for\n" "\t activation but not for publication." % repr(self)) return False if p <= now and a <= now: return True if p == a: output("WARNING: %s is scheduled to be\n" "\t published and activated at the same time. This\n" "\t could result in a coverage gap if the zone was\n" "\t previously signed. Activation should be at least\n" "\t %s after publication." % (repr(self), dnskey.duration(self.ttl) or 'one DNSKEY TTL')) return True if a < p: output("WARNING: Key %s is active before it is published" % repr(self)) return False if self.ttl is not None and a - p < self.ttl: output("WARNING: Key %s is activated too soon\n" "\t after publication; this could result in coverage \n" "\t gaps due to resolver caches containing old data.\n" "\t Activation should be at least %s after\n" "\t publication." % (repr(self), dnskey.duration(self.ttl) or 'one DNSKEY TTL')) return False return True def check_postpub(self, output = None, timespan = None): def noop(*args, **kwargs): pass if output is None: output = noop if timespan is None: timespan = self.ttl if timespan is None: output("WARNING: Key %s using default TTL." % repr(self)) timespan = (60*60*24) now = time.time() d = self.delete() i = self.inactive() if not d: return False if not i: if d > now: output("WARNING: Key %s is scheduled for\n" "\t deletion but not for inactivation." % repr(self)) return False if d < now and i < now: return True if d < i: output("WARNING: Key %s is scheduled for\n" "\t deletion before inactivation." % repr(self)) return False if d - i < timespan: output("WARNING: Key %s scheduled for\n" "\t deletion too soon after deactivation; this may \n" "\t result in coverage gaps due to resolver caches\n" "\t containing old data. Deletion should be at least\n" "\t %s after inactivation." % (repr(self), dnskey.duration(timespan))) return False return True @staticmethod def duration(secs): if not secs: return None units = [("year", 60*60*24*365), ("month", 60*60*24*30), ("day", 60*60*24), ("hour", 60*60), ("minute", 60), ("second", 1)] output = [] for unit in units: v, secs = secs // unit[1], secs % unit[1] if v > 0: output.append("%d %s%s" % (v, unit[0], "s" if v > 1 else "")) return ", ".join(output) PK!A eventlist.pynu[############################################################################ # Copyright (C) Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, you can obtain one at https://mozilla.org/MPL/2.0/. # # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. ############################################################################ from collections import defaultdict from .dnskey import * from .keydict import * from .keyevent import * class eventlist: _K = defaultdict(lambda: defaultdict(list)) _Z = defaultdict(lambda: defaultdict(list)) _zones = set() _kdict = None def __init__(self, kdict): properties = ["SyncPublish", "Publish", "SyncDelete", "Activate", "Inactive", "Delete"] self._kdict = kdict for zone in kdict.zones(): self._zones.add(zone) for alg, keys in kdict[zone].items(): for k in keys.values(): for prop in properties: t = k.gettime(prop) if not t: continue e = keyevent(prop, k, t) if k.sep: self._K[zone][alg].append(e) else: self._Z[zone][alg].append(e) self._K[zone][alg] = sorted(self._K[zone][alg], key=lambda event: event.when) self._Z[zone][alg] = sorted(self._Z[zone][alg], key=lambda event: event.when) # scan events per zone, algorithm, and key type, in order of # occurrence, noting inconsistent states when found def coverage(self, zone, keytype, until, output = None): def noop(*args, **kwargs): pass if not output: output = noop no_zsk = True if (keytype and keytype == "KSK") else False no_ksk = True if (keytype and keytype == "ZSK") else False kok = zok = True found = False if zone and not zone in self._zones: output("ERROR: No key events found for %s" % zone) return False if zone: found = True if not no_ksk: kok = self.checkzone(zone, "KSK", until, output) if not no_zsk: zok = self.checkzone(zone, "ZSK", until, output) else: for z in self._zones: if not no_ksk and z in self._K.keys(): found = True kok = self.checkzone(z, "KSK", until, output) if not no_zsk and z in self._Z.keys(): found = True zok = self.checkzone(z, "ZSK", until, output) if not found: output("ERROR: No key events found") return False return (kok and zok) def checkzone(self, zone, keytype, until, output): allok = True if keytype == "KSK": kz = self._K[zone] else: kz = self._Z[zone] for alg in kz.keys(): output("Checking scheduled %s events for zone %s, " "algorithm %s..." % (keytype, zone, dnskey.algstr(alg))) ok = eventlist.checkset(kz[alg], keytype, until, output) if ok: output("No errors found") allok = allok and ok return allok @staticmethod def showset(eventset, output): if not eventset: return output(" " + eventset[0].showtime() + ":", skip=False) for event in eventset: output(" %s: %s" % (event.what, repr(event.key)), skip=False) @staticmethod def checkset(eventset, keytype, until, output): groups = list() group = list() # collect up all events that have the same time eventsfound = False for event in eventset: # we found an event eventsfound = True # add event to current group if (not group or group[0].when == event.when): group.append(event) # if we're at the end of the list, we're done. if # we've found an event with a later time, start a new group if (group[0].when != event.when): groups.append(group) group = list() group.append(event) if group: groups.append(group) if not eventsfound: output("ERROR: No %s events found" % keytype) return False active = published = None for group in groups: if (until and calendar.timegm(group[0].when) > until): output("Ignoring events after %s" % time.strftime("%a %b %d %H:%M:%S UTC %Y", time.gmtime(until))) return True for event in group: (active, published) = event.status(active, published) eventlist.showset(group, output) # and then check for inconsistencies: if not active: output("ERROR: No %s's are active after this event" % keytype) return False elif not published: output("ERROR: No %s's are published after this event" % keytype) return False elif not published.intersection(active): output("ERROR: No %s's are both active and published " "after this event" % keytype) return False return True PK!+V! ! keydict.pynu[############################################################################ # Copyright (C) Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, you can obtain one at https://mozilla.org/MPL/2.0/. # # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. ############################################################################ from collections import defaultdict from . import dnskey import os import glob ######################################################################## # Class keydict ######################################################################## class keydict: """ A dictionary of keys, indexed by name, algorithm, and key id """ _keydict = defaultdict(lambda: defaultdict(dict)) _defttl = None _missing = [] def __init__(self, dp=None, **kwargs): self._defttl = kwargs.get('keyttl', None) zones = kwargs.get('zones', None) if not zones: path = kwargs.get('path',None) or '.' self.readall(path) else: for zone in zones: if 'path' in kwargs and kwargs['path'] is not None: path = kwargs['path'] else: path = dp and dp.policy(zone).directory or '.' if not self.readone(path, zone): self._missing.append(zone) def readall(self, path): files = glob.glob(os.path.join(path, '*.private')) for infile in files: key = dnskey(infile, path, self._defttl) self._keydict[key.name][key.alg][key.keyid] = key def readone(self, path, zone): if not zone.endswith('.'): zone += '.' match='K' + zone + '+*.private' files = glob.glob(os.path.join(path, match)) found = False for infile in files: key = dnskey(infile, path, self._defttl) if key.fullname != zone: # shouldn't ever happen continue keyname=key.name if zone != '.' else '.' self._keydict[keyname][key.alg][key.keyid] = key found = True return found def __iter__(self): for zone, algorithms in self._keydict.items(): for alg, keys in algorithms.items(): for key in keys.values(): yield key def __getitem__(self, name): return self._keydict[name] def zones(self): return (self._keydict.keys()) def algorithms(self, zone): return (self._keydict[zone].keys()) def keys(self, zone, alg): return (self._keydict[zone][alg].keys()) def missing(self): return (self._missing) PK!׀} keyevent.pynu[############################################################################ # Copyright (C) Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, you can obtain one at https://mozilla.org/MPL/2.0/. # # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. ############################################################################ import time ######################################################################## # Class keyevent ######################################################################## class keyevent: """ A discrete key event, e.g., Publish, Activate, Inactive, Delete, etc. Stores the date of the event, and identifying information about the key to which the event will occur.""" def __init__(self, what, key, when=None): self.what = what self.when = when or key.gettime(what) self.key = key self.sep = key.sep self.zone = key.name self.alg = key.alg self.keyid = key.keyid def __repr__(self): return repr((self.when, self.what, self.keyid, self.sep, self.zone, self.alg)) def showtime(self): return time.strftime("%a %b %d %H:%M:%S UTC %Y", self.when) # update sets of active and published keys, based on # the contents of this keyevent def status(self, active, published, output = None): def noop(*args, **kwargs): pass if not output: output = noop if not active: active = set() if not published: published = set() if self.what == "Activate": active.add(self.keyid) elif self.what == "Publish": published.add(self.keyid) elif self.what == "Inactive": if self.keyid not in active: output("\tWARNING: %s scheduled to become inactive " "before it is active" % repr(self.key)) else: active.remove(self.keyid) elif self.what == "Delete": if self.keyid in published: published.remove(self.keyid) else: output("WARNING: key %s is scheduled for deletion " "before it is published" % repr(self.key)) elif self.what == "Revoke": # We don't need to worry about the logic of this one; # just stop counting this key as either active or published if self.keyid in published: published.remove(self.keyid) if self.keyid in active: active.remove(self.keyid) return active, published PK!T\kk keymgr.pynu[############################################################################ # Copyright (C) Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, you can obtain one at https://mozilla.org/MPL/2.0/. # # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. ############################################################################ from __future__ import print_function import os, sys, argparse, glob, re, time, calendar, pprint from collections import defaultdict prog='dnssec-keymgr' from isc import dnskey, keydict, keyseries, policy, parsetab, utils ############################################################################ # print a fatal error and exit ############################################################################ def fatal(*args, **kwargs): print(*args, **kwargs) sys.exit(1) ############################################################################ # find the location of an external command ############################################################################ def set_path(command, default=None): """ find the location of a specified command. If a default is supplied, exists and it's an executable, we use it; otherwise we search PATH for an alternative. :param command: command to look for :param default: default value to use :return: PATH with the location of a suitable binary """ fpath = default if not fpath or not os.path.isfile(fpath) or not os.access(fpath, os.X_OK): path = os.environ["PATH"] if not path: path = os.path.defpath for directory in path.split(os.pathsep): fpath = directory + os.sep + command if os.path.isfile(fpath) and os.access(fpath, os.X_OK): break fpath = None return fpath ############################################################################ # parse arguments ############################################################################ def parse_args(): """ Read command line arguments, returns 'args' object :return: args object properly prepared """ keygen = set_path('dnssec-keygen', os.path.join(utils.prefix('sbin'), 'dnssec-keygen')) settime = set_path('dnssec-settime', os.path.join(utils.prefix('sbin'), 'dnssec-settime')) parser = argparse.ArgumentParser(description=prog + ': schedule ' 'DNSSEC key rollovers according to a ' 'pre-defined policy') parser.add_argument('zone', type=str, nargs='*', default=None, help='Zone(s) to which the policy should be applied ' + '(default: all zones in the directory)') parser.add_argument('-K', dest='path', type=str, help='Directory containing keys', metavar='dir') parser.add_argument('-c', dest='policyfile', type=str, help='Policy definition file', metavar='file') parser.add_argument('-g', dest='keygen', default=keygen, type=str, help='Path to \'dnssec-keygen\'', metavar='path') parser.add_argument('-r', dest='randomdev', type=str, default=None, help='Path to a file containing random data to pass to \'dnssec-keygen\'', metavar='path') parser.add_argument('-s', dest='settime', default=settime, type=str, help='Path to \'dnssec-settime\'', metavar='path') parser.add_argument('-k', dest='no_zsk', action='store_true', default=False, help='Only apply policy to key-signing keys (KSKs)') parser.add_argument('-z', dest='no_ksk', action='store_true', default=False, help='Only apply policy to zone-signing keys (ZSKs)') parser.add_argument('-f', '--force', dest='force', action='store_true', default=False, help='Force updates to key events '+ 'even if they are in the past') parser.add_argument('-q', '--quiet', dest='quiet', action='store_true', default=False, help='Update keys silently') parser.add_argument('-v', '--version', action='version', version=utils.version) args = parser.parse_args() if args.no_zsk and args.no_ksk: fatal("ERROR: -z and -k cannot be used together.") if args.keygen is None: fatal("ERROR: dnssec-keygen not found") if args.settime is None: fatal("ERROR: dnssec-settime not found") # if a policy file was specified, check that it exists. # if not, use the default file, unless it doesn't exist if args.policyfile is not None: if not os.path.exists(args.policyfile): fatal('ERROR: Policy file "%s" not found' % args.policyfile) else: args.policyfile = os.path.join(utils.sysconfdir, 'dnssec-policy.conf') if not os.path.exists(args.policyfile): args.policyfile = None return args ############################################################################ # main ############################################################################ def main(): args = parse_args() # As we may have specific locations for the binaries, we put that info # into a context object that can be passed around context = {'keygen_path': args.keygen, 'settime_path': args.settime, 'keys_path': args.path, 'randomdev': args.randomdev} try: dp = policy.dnssec_policy(args.policyfile) except Exception as e: fatal('Unable to load DNSSEC policy: ' + str(e)) try: kd = keydict(dp, path=args.path, zones=args.zone) except Exception as e: fatal('Unable to build key dictionary: ' + str(e)) try: ks = keyseries(kd, context=context) except Exception as e: fatal('Unable to build key series: ' + str(e)) try: ks.enforce_policy(dp, ksk=args.no_zsk, zsk=args.no_ksk, force=args.force, quiet=args.quiet) except Exception as e: fatal('Unable to apply policy: ' + str(e)) PK!M2"" keyseries.pynu[############################################################################ # Copyright (C) Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, you can obtain one at https://mozilla.org/MPL/2.0/. # # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. ############################################################################ from collections import defaultdict from .dnskey import * from .keydict import * from .keyevent import * from .policy import * import time class keyseries: _K = defaultdict(lambda: defaultdict(list)) _Z = defaultdict(lambda: defaultdict(list)) _zones = set() _kdict = None _context = None def __init__(self, kdict, now=time.time(), context=None): self._kdict = kdict self._context = context self._zones = set(kdict.missing()) for zone in kdict.zones(): self._zones.add(zone) for alg, keys in kdict[zone].items(): for k in keys.values(): if k.sep: if not (k.delete() and k.delete() < now): self._K[zone][alg].append(k) else: if not (k.delete() and k.delete() < now): self._Z[zone][alg].append(k) self._K[zone][alg].sort() self._Z[zone][alg].sort() def __iter__(self): for zone in self._zones: for collection in [self._K, self._Z]: if zone not in collection: continue for alg, keys in collection[zone].items(): for key in keys: yield key def dump(self): for k in self: print("%s" % repr(k)) def fixseries(self, keys, policy, now, **kwargs): force = kwargs.get('force', False) if not keys: return # handle the first key key = keys[0] if key.sep: rp = policy.ksk_rollperiod prepub = policy.ksk_prepublish or (30 * 86400) postpub = policy.ksk_postpublish or (30 * 86400) else: rp = policy.zsk_rollperiod prepub = policy.zsk_prepublish or (30 * 86400) postpub = policy.zsk_postpublish or (30 * 86400) # the first key should be published and active p = key.publish() a = key.activate() if not p or p > now: key.setpublish(now) p = now if not a or a > now: key.setactivate(now) a = now i = key.inactive() fudge = 300 if not rp: key.setinactive(None, **kwargs) key.setdelete(None, **kwargs) elif not i or a + rp != i: if not i and a + rp > now + prepub + fudge: key.setinactive(a + rp, **kwargs) key.setdelete(a + rp + postpub, **kwargs) elif not i: key.setinactive(now + prepub + fudge, **kwargs) key.setdelete(now + prepub + postpub + fudge, **kwargs) elif i < now: pass elif a + rp > i: key.setinactive(a + rp, **kwargs) key.setdelete(a + rp + postpub, **kwargs) elif a + rp > now + prepub + fudge: key.setinactive(a + rp, **kwargs) key.setdelete(a + rp + postpub, **kwargs) else: key.setinactive(now + prepub + fudge, **kwargs) key.setdelete(now + prepub + postpub + fudge, **kwargs) else: d = key.delete() if not d or i + postpub > now + fudge: key.setdelete(i + postpub, **kwargs) elif not d: key.setdelete(now + postpub + fudge, **kwargs) elif d < now + fudge: pass elif d < i + postpub: key.setdelete(i + postpub, **kwargs) if policy.keyttl != key.ttl: key.setttl(policy.keyttl) # handle all the subsequent keys prev = key for key in keys[1:]: # if no rollperiod, then all keys after the first in # the series kept inactive. # (XXX: we need to change this to allow standby keys) if not rp: key.setpublish(None, **kwargs) key.setactivate(None, **kwargs) key.setinactive(None, **kwargs) key.setdelete(None, **kwargs) if policy.keyttl != key.ttl: key.setttl(policy.keyttl) continue # otherwise, ensure all dates are set correctly based on # the initial key a = prev.inactive() p = a - prepub key.setactivate(a, **kwargs) key.setpublish(p, **kwargs) key.setinactive(a + rp, **kwargs) key.setdelete(a + rp + postpub, **kwargs) prev.setdelete(a + postpub, **kwargs) if policy.keyttl != key.ttl: key.setttl(policy.keyttl) prev = key # if we haven't got sufficient coverage, create successor key(s) while rp and prev.inactive() and \ prev.inactive() < now + policy.coverage: # commit changes to predecessor: a successor can only be # generated if Inactive has been set in the predecessor key prev.commit(self._context['settime_path'], **kwargs) key = prev.generate_successor(self._context['keygen_path'], self._context['randomdev'], prepub, **kwargs) key.setinactive(key.activate() + rp, **kwargs) key.setdelete(key.inactive() + postpub, **kwargs) keys.append(key) prev = key # last key? we already know we have sufficient coverage now, so # disable the inactivation of the final key (if it was set), # ensuring that if dnssec-keymgr isn't run again, the last key # in the series will at least remain usable. prev.setinactive(None, **kwargs) prev.setdelete(None, **kwargs) # commit changes for key in keys: key.commit(self._context['settime_path'], **kwargs) def enforce_policy(self, policies, now=time.time(), **kwargs): # If zones is provided as a parameter, use that list. # If not, use what we have in this object zones = kwargs.get('zones', self._zones) keys_dir = kwargs.get('dir', self._context.get('keys_path', None)) force = kwargs.get('force', False) for zone in zones: collections = [] policy = policies.policy(zone) keys_dir = keys_dir or policy.directory or '.' alg = policy.algorithm algnum = dnskey.algnum(alg) if 'ksk' not in kwargs or not kwargs['ksk']: if len(self._Z[zone][algnum]) == 0: k = dnskey.generate(self._context['keygen_path'], self._context['randomdev'], keys_dir, zone, alg, policy.zsk_keysize, False, policy.keyttl or 3600, **kwargs) self._Z[zone][algnum].append(k) collections.append(self._Z[zone]) if 'zsk' not in kwargs or not kwargs['zsk']: if len(self._K[zone][algnum]) == 0: k = dnskey.generate(self._context['keygen_path'], self._context['randomdev'], keys_dir, zone, alg, policy.ksk_keysize, True, policy.keyttl or 3600, **kwargs) self._K[zone][algnum].append(k) collections.append(self._K[zone]) for collection in collections: for algorithm, keys in collection.items(): if algorithm != algnum: continue try: self.fixseries(keys, policy, now, **kwargs) except Exception as e: raise Exception('%s/%s: %s' % (zone, dnskey.algstr(algnum), str(e))) PK!Snտ keyzone.pynu[############################################################################ # Copyright (C) Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, you can obtain one at https://mozilla.org/MPL/2.0/. # # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. ############################################################################ import os import sys import re from subprocess import Popen, PIPE ######################################################################## # Exceptions ######################################################################## class KeyZoneException(Exception): pass ######################################################################## # class keyzone ######################################################################## class keyzone: """reads a zone file to find data relevant to keys""" def __init__(self, name, filename, czpath): self.maxttl = None self.keyttl = None if not name: return if not czpath or not os.path.isfile(czpath) \ or not os.access(czpath, os.X_OK): raise KeyZoneException('"named-compilezone" not found') return maxttl = keyttl = None fp, _ = Popen([czpath, "-o", "-", name, filename], stdout=PIPE, stderr=PIPE).communicate() for line in fp.splitlines(): if type(line) is not str: line = line.decode('ascii') if re.search('^[:space:]*;', line): continue fields = line.split() if not maxttl or int(fields[1]) > maxttl: maxttl = int(fields[1]) if fields[3] == "DNSKEY": keyttl = int(fields[1]) self.keyttl = keyttl self.maxttl = maxttl PK!oެX}} parsetab.pynu[ # parsetab.py # This file is automatically generated. Do not edit. _tabversion = '3.8' _lr_method = 'LALR' _lr_signature = 'C2FE91AF256AF1CCEB499107DA2CFE7E' _lr_action_items = {'ALGORITHM_POLICY':([0,1,2,3,4,5,6,10,29,46,62,],[-3,7,7,-2,-4,-5,-6,-1,-15,-16,-17,]),'ZONE':([0,1,2,3,4,5,6,10,29,46,62,],[-3,8,8,-2,-4,-5,-6,-1,-15,-16,-17,]),'POLICY':([0,1,2,3,4,5,6,10,27,29,46,47,62,77,88,],[-3,9,9,-2,-4,-5,-6,-1,59,-15,-16,59,-17,-22,-23,]),'$end':([1,3,4,5,6,10,29,46,62,],[0,-2,-4,-5,-6,-1,-15,-16,-17,]),'ALGNAME':([7,61,],[11,80,]),'STR':([8,9,59,],[13,18,18,]),'QSTRING':([8,60,],[14,79,]),'KEYTYPE':([8,9,40,41,42,44,45,59,],[15,19,69,70,71,73,74,19,]),'DATESUFFIX':([8,9,59,67,],[16,20,20,82,]),'LBRACE':([11,12,13,14,15,16,17,18,19,20,21,22,23,],[-14,-14,-10,-11,-12,-13,-14,-7,-8,-9,25,27,27,]),'SEMI':([18,19,20,24,26,28,31,32,33,34,35,36,37,38,48,49,50,51,52,53,54,55,56,57,58,63,64,66,67,68,72,75,76,78,79,80,82,83,84,85,86,87,],[-7,-8,-9,29,46,62,65,-37,-38,-39,-40,-41,-42,-43,77,-24,-25,-26,-27,-28,-29,-30,-31,-32,-33,-34,81,-46,-18,-19,-52,-21,88,-44,-45,-53,-20,-47,-48,-49,-50,-51,]),'COVERAGE':([25,27,30,47,65,77,81,88,],[39,39,39,39,-35,-22,-36,-23,]),'ROLL_PERIOD':([25,27,30,47,65,77,81,88,],[40,40,40,40,-35,-22,-36,-23,]),'PRE_PUBLISH':([25,27,30,47,65,77,81,88,],[41,41,41,41,-35,-22,-36,-23,]),'POST_PUBLISH':([25,27,30,47,65,77,81,88,],[42,42,42,42,-35,-22,-36,-23,]),'KEYTTL':([25,27,30,47,65,77,81,88,],[43,43,43,43,-35,-22,-36,-23,]),'KEY_SIZE':([25,27,30,47,65,77,81,88,],[44,44,44,44,-35,-22,-36,-23,]),'STANDBY':([25,27,30,47,65,77,81,88,],[45,45,45,45,-35,-22,-36,-23,]),'DIRECTORY':([27,47,77,88,],[60,60,-22,-23,]),'ALGORITHM':([27,47,77,88,],[61,61,-22,-23,]),'RBRACE':([30,47,65,77,81,88,],[63,75,-35,-22,-36,-23,]),'NUMBER':([39,43,69,70,71,73,74,],[67,67,67,67,67,86,87,]),'NONE':([39,43,69,70,71,],[68,68,68,68,68,]),} _lr_action = {} for _k, _v in _lr_action_items.items(): for _x,_y in zip(_v[0],_v[1]): if not _x in _lr_action: _lr_action[_x] = {} _lr_action[_x][_k] = _y del _lr_action_items _lr_goto_items = {'policylist':([0,],[1,]),'init':([0,],[2,]),'policy':([1,2,],[3,10,]),'alg_policy':([1,2,],[4,4,]),'zone_policy':([1,2,],[5,5,]),'named_policy':([1,2,],[6,6,]),'domain':([8,],[12,]),'name':([9,59,],[17,78,]),'new_policy':([11,12,17,],[21,22,23,]),'alg_option_group':([21,],[24,]),'policy_option_group':([22,23,],[26,28,]),'alg_option_list':([25,],[30,]),'alg_option':([25,30,],[31,64,]),'coverage_option':([25,27,30,47,],[32,51,32,51,]),'rollperiod_option':([25,27,30,47,],[33,52,33,52,]),'prepublish_option':([25,27,30,47,],[34,53,34,53,]),'postpublish_option':([25,27,30,47,],[35,54,35,54,]),'keyttl_option':([25,27,30,47,],[36,57,36,57,]),'keysize_option':([25,27,30,47,],[37,55,37,55,]),'standby_option':([25,27,30,47,],[38,58,38,58,]),'policy_option_list':([27,],[47,]),'policy_option':([27,47,],[48,76,]),'parent_option':([27,47,],[49,49,]),'directory_option':([27,47,],[50,50,]),'algorithm_option':([27,47,],[56,56,]),'duration':([39,43,69,70,71,],[66,72,83,84,85,]),} _lr_goto = {} for _k, _v in _lr_goto_items.items(): for _x, _y in zip(_v[0], _v[1]): if not _x in _lr_goto: _lr_goto[_x] = {} _lr_goto[_x][_k] = _y del _lr_goto_items _lr_productions = [ ("S' -> policylist","S'",1,None,None,None), ('policylist -> init policy','policylist',2,'p_policylist','policy.py',523), ('policylist -> policylist policy','policylist',2,'p_policylist','policy.py',524), ('init -> ','init',0,'p_init','policy.py',528), ('policy -> alg_policy','policy',1,'p_policy','policy.py',532), ('policy -> zone_policy','policy',1,'p_policy','policy.py',533), ('policy -> named_policy','policy',1,'p_policy','policy.py',534), ('name -> STR','name',1,'p_name','policy.py',538), ('name -> KEYTYPE','name',1,'p_name','policy.py',539), ('name -> DATESUFFIX','name',1,'p_name','policy.py',540), ('domain -> STR','domain',1,'p_domain','policy.py',545), ('domain -> QSTRING','domain',1,'p_domain','policy.py',546), ('domain -> KEYTYPE','domain',1,'p_domain','policy.py',547), ('domain -> DATESUFFIX','domain',1,'p_domain','policy.py',548), ('new_policy -> ','new_policy',0,'p_new_policy','policy.py',555), ('alg_policy -> ALGORITHM_POLICY ALGNAME new_policy alg_option_group SEMI','alg_policy',5,'p_alg_policy','policy.py',559), ('zone_policy -> ZONE domain new_policy policy_option_group SEMI','zone_policy',5,'p_zone_policy','policy.py',566), ('named_policy -> POLICY name new_policy policy_option_group SEMI','named_policy',5,'p_named_policy','policy.py',573), ('duration -> NUMBER','duration',1,'p_duration_1','policy.py',579), ('duration -> NONE','duration',1,'p_duration_2','policy.py',584), ('duration -> NUMBER DATESUFFIX','duration',2,'p_duration_3','policy.py',589), ('policy_option_group -> LBRACE policy_option_list RBRACE','policy_option_group',3,'p_policy_option_group','policy.py',608), ('policy_option_list -> policy_option SEMI','policy_option_list',2,'p_policy_option_list','policy.py',612), ('policy_option_list -> policy_option_list policy_option SEMI','policy_option_list',3,'p_policy_option_list','policy.py',613), ('policy_option -> parent_option','policy_option',1,'p_policy_option','policy.py',617), ('policy_option -> directory_option','policy_option',1,'p_policy_option','policy.py',618), ('policy_option -> coverage_option','policy_option',1,'p_policy_option','policy.py',619), ('policy_option -> rollperiod_option','policy_option',1,'p_policy_option','policy.py',620), ('policy_option -> prepublish_option','policy_option',1,'p_policy_option','policy.py',621), ('policy_option -> postpublish_option','policy_option',1,'p_policy_option','policy.py',622), ('policy_option -> keysize_option','policy_option',1,'p_policy_option','policy.py',623), ('policy_option -> algorithm_option','policy_option',1,'p_policy_option','policy.py',624), ('policy_option -> keyttl_option','policy_option',1,'p_policy_option','policy.py',625), ('policy_option -> standby_option','policy_option',1,'p_policy_option','policy.py',626), ('alg_option_group -> LBRACE alg_option_list RBRACE','alg_option_group',3,'p_alg_option_group','policy.py',630), ('alg_option_list -> alg_option SEMI','alg_option_list',2,'p_alg_option_list','policy.py',634), ('alg_option_list -> alg_option_list alg_option SEMI','alg_option_list',3,'p_alg_option_list','policy.py',635), ('alg_option -> coverage_option','alg_option',1,'p_alg_option','policy.py',639), ('alg_option -> rollperiod_option','alg_option',1,'p_alg_option','policy.py',640), ('alg_option -> prepublish_option','alg_option',1,'p_alg_option','policy.py',641), ('alg_option -> postpublish_option','alg_option',1,'p_alg_option','policy.py',642), ('alg_option -> keyttl_option','alg_option',1,'p_alg_option','policy.py',643), ('alg_option -> keysize_option','alg_option',1,'p_alg_option','policy.py',644), ('alg_option -> standby_option','alg_option',1,'p_alg_option','policy.py',645), ('parent_option -> POLICY name','parent_option',2,'p_parent_option','policy.py',649), ('directory_option -> DIRECTORY QSTRING','directory_option',2,'p_directory_option','policy.py',653), ('coverage_option -> COVERAGE duration','coverage_option',2,'p_coverage_option','policy.py',657), ('rollperiod_option -> ROLL_PERIOD KEYTYPE duration','rollperiod_option',3,'p_rollperiod_option','policy.py',661), ('prepublish_option -> PRE_PUBLISH KEYTYPE duration','prepublish_option',3,'p_prepublish_option','policy.py',668), ('postpublish_option -> POST_PUBLISH KEYTYPE duration','postpublish_option',3,'p_postpublish_option','policy.py',675), ('keysize_option -> KEY_SIZE KEYTYPE NUMBER','keysize_option',3,'p_keysize_option','policy.py',682), ('standby_option -> STANDBY KEYTYPE NUMBER','standby_option',3,'p_standby_option','policy.py',689), ('keyttl_option -> KEYTTL duration','keyttl_option',2,'p_keyttl_option','policy.py',696), ('algorithm_option -> ALGORITHM ALGNAME','algorithm_option',2,'p_algorithm_option','policy.py',700), ] PK!=2g2g policy.pynu[############################################################################ # Copyright (C) Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, you can obtain one at https://mozilla.org/MPL/2.0/. # # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. ############################################################################ import re import ply.lex as lex import ply.yacc as yacc from string import * from copy import copy ############################################################################ # PolicyLex: a lexer for the policy file syntax. ############################################################################ class PolicyLex: reserved = ('POLICY', 'ALGORITHM_POLICY', 'ZONE', 'ALGORITHM', 'DIRECTORY', 'KEYTTL', 'KEY_SIZE', 'ROLL_PERIOD', 'PRE_PUBLISH', 'POST_PUBLISH', 'COVERAGE', 'STANDBY', 'NONE') tokens = reserved + ('DATESUFFIX', 'KEYTYPE', 'ALGNAME', 'STR', 'QSTRING', 'NUMBER', 'LBRACE', 'RBRACE', 'SEMI') reserved_map = {} t_ignore = ' \t' t_ignore_olcomment = r'(//|\#).*' t_LBRACE = r'\{' t_RBRACE = r'\}' t_SEMI = r';'; def t_newline(self, t): r'\n+' t.lexer.lineno += t.value.count("\n") def t_comment(self, t): r'/\*(.|\n)*?\*/' t.lexer.lineno += t.value.count('\n') def t_DATESUFFIX(self, t): r'(?i)(?<=[0-9 \t])(y(?:ears|ear|ea|e)?|mo(?:nths|nth|nt|n)?|w(?:eeks|eek|ee|e)?|d(?:ays|ay|a)?|h(?:ours|our|ou|o)?|mi(?:nutes|nute|nut|nu|n)?|s(?:econds|econd|econ|eco|ec|e)?)\b' t.value = re.match(r'(?i)(y|mo|w|d|h|mi|s)([a-z]*)', t.value).group(1).lower() return t def t_KEYTYPE(self, t): r'(?i)\b(KSK|ZSK)\b' t.value = t.value.upper() return t def t_ALGNAME(self, t): r'(?i)\b(RSAMD5|DH|DSA|NSEC3DSA|ECC|RSASHA1|NSEC3RSASHA1|RSASHA256|RSASHA512|ECCGOST|ECDSAP256SHA256|ECDSAP384SHA384|ED25519|ED448)\b' t.value = t.value.upper() return t def t_STR(self, t): r'[A-Za-z._-][\w._-]*' t.type = self.reserved_map.get(t.value, "STR") return t def t_QSTRING(self, t): r'"([^"\n]|(\\"))*"' t.type = self.reserved_map.get(t.value, "QSTRING") t.value = t.value[1:-1] return t def t_NUMBER(self, t): r'\d+' t.value = int(t.value) return t def t_error(self, t): print("Illegal character '%s'" % t.value[0]) t.lexer.skip(1) def __init__(self, **kwargs): if 'maketrans' in dir(str): trans = str.maketrans('_', '-') else: trans = maketrans('_', '-') for r in self.reserved: self.reserved_map[r.lower().translate(trans)] = r self.lexer = lex.lex(object=self, **kwargs) def test(self, text): self.lexer.input(text) while True: t = self.lexer.token() if not t: break print(t) ############################################################################ # Policy: this object holds a set of DNSSEC policy settings. ############################################################################ class Policy: is_zone = False is_alg = False is_constructed = False ksk_rollperiod = None zsk_rollperiod = None ksk_prepublish = None zsk_prepublish = None ksk_postpublish = None zsk_postpublish = None ksk_keysize = None zsk_keysize = None ksk_standby = None zsk_standby = None keyttl = None coverage = None directory = None valid_key_sz_per_algo = {'DSA': [512, 1024], 'NSEC3DSA': [512, 1024], 'RSAMD5': [512, 4096], 'RSASHA1': [512, 4096], 'NSEC3RSASHA1': [512, 4096], 'RSASHA256': [512, 4096], 'RSASHA512': [512, 4096], 'ECCGOST': None, 'ECDSAP256SHA256': None, 'ECDSAP384SHA384': None, 'ED25519': None, 'ED448': None} def __init__(self, name=None, algorithm=None, parent=None): self.name = name self.algorithm = algorithm self.parent = parent pass def __repr__(self): return ("%spolicy %s:\n" "\tinherits %s\n" "\tdirectory %s\n" "\talgorithm %s\n" "\tcoverage %s\n" "\tksk_keysize %s\n" "\tzsk_keysize %s\n" "\tksk_rollperiod %s\n" "\tzsk_rollperiod %s\n" "\tksk_prepublish %s\n" "\tksk_postpublish %s\n" "\tzsk_prepublish %s\n" "\tzsk_postpublish %s\n" "\tksk_standby %s\n" "\tzsk_standby %s\n" "\tkeyttl %s\n" % ((self.is_constructed and 'constructed ' or \ self.is_zone and 'zone ' or \ self.is_alg and 'algorithm ' or ''), self.name or 'UNKNOWN', self.parent and self.parent.name or 'None', self.directory and ('"' + str(self.directory) + '"') or 'None', self.algorithm or 'None', self.coverage and str(self.coverage) or 'None', self.ksk_keysize and str(self.ksk_keysize) or 'None', self.zsk_keysize and str(self.zsk_keysize) or 'None', self.ksk_rollperiod and str(self.ksk_rollperiod) or 'None', self.zsk_rollperiod and str(self.zsk_rollperiod) or 'None', self.ksk_prepublish and str(self.ksk_prepublish) or 'None', self.ksk_postpublish and str(self.ksk_postpublish) or 'None', self.zsk_prepublish and str(self.zsk_prepublish) or 'None', self.zsk_postpublish and str(self.zsk_postpublish) or 'None', self.ksk_standby and str(self.ksk_standby) or 'None', self.zsk_standby and str(self.zsk_standby) or 'None', self.keyttl and str(self.keyttl) or 'None')) def __verify_size(self, key_size, size_range): return (size_range[0] <= key_size <= size_range[1]) def get_name(self): return self.name def constructed(self): return self.is_constructed def validate(self): """ Check if the values in the policy make sense :return: True/False if the policy passes validation """ if self.ksk_rollperiod and \ self.ksk_prepublish is not None and \ self.ksk_prepublish > self.ksk_rollperiod: print(self.ksk_rollperiod) return (False, ('KSK pre-publish period (%d) exceeds rollover period %d' % (self.ksk_prepublish, self.ksk_rollperiod))) if self.ksk_rollperiod and \ self.ksk_postpublish is not None and \ self.ksk_postpublish > self.ksk_rollperiod: return (False, ('KSK post-publish period (%d) exceeds rollover period %d' % (self.ksk_postpublish, self.ksk_rollperiod))) if self.zsk_rollperiod and \ self.zsk_prepublish is not None and \ self.zsk_prepublish >= self.zsk_rollperiod: return (False, ('ZSK pre-publish period (%d) exceeds rollover period %d' % (self.zsk_prepublish, self.zsk_rollperiod))) if self.zsk_rollperiod and \ self.zsk_postpublish is not None and \ self.zsk_postpublish >= self.zsk_rollperiod: return (False, ('ZSK post-publish period (%d) exceeds rollover period %d' % (self.zsk_postpublish, self.zsk_rollperiod))) if self.ksk_rollperiod and \ self.ksk_prepublish and self.ksk_postpublish and \ self.ksk_prepublish + self.ksk_postpublish >= self.ksk_rollperiod: return (False, (('KSK pre/post-publish periods (%d/%d) ' + 'combined exceed rollover period %d') % (self.ksk_prepublish, self.ksk_postpublish, self.ksk_rollperiod))) if self.zsk_rollperiod and \ self.zsk_prepublish and self.zsk_postpublish and \ self.zsk_prepublish + self.zsk_postpublish >= self.zsk_rollperiod: return (False, (('ZSK pre/post-publish periods (%d/%d) ' + 'combined exceed rollover period %d') % (self.zsk_prepublish, self.zsk_postpublish, self.zsk_rollperiod))) if self.algorithm is not None: # Validate the key size key_sz_range = self.valid_key_sz_per_algo.get(self.algorithm) if key_sz_range is not None: # Verify KSK if not self.__verify_size(self.ksk_keysize, key_sz_range): return False, 'KSK key size %d outside valid range %s' \ % (self.ksk_keysize, key_sz_range) # Verify ZSK if not self.__verify_size(self.zsk_keysize, key_sz_range): return False, 'ZSK key size %d outside valid range %s' \ % (self.zsk_keysize, key_sz_range) # Specific check for DSA keys if self.algorithm in ['DSA', 'NSEC3DSA'] and \ self.ksk_keysize % 64 != 0: return False, \ ('KSK key size %d not divisible by 64 ' + 'as required for DSA') % self.ksk_keysize if self.algorithm in ['DSA', 'NSEC3DSA'] and \ self.zsk_keysize % 64 != 0: return False, \ ('ZSK key size %d not divisible by 64 ' + 'as required for DSA') % self.zsk_keysize if self.algorithm in ['ECCGOST', \ 'ECDSAP256SHA256', \ 'ECDSAP384SHA384', \ 'ED25519', \ 'ED448']: self.ksk_keysize = None self.zsk_keysize = None return True, '' ############################################################################ # dnssec_policy: # This class reads a dnssec.policy file and creates a dictionary of # DNSSEC policy rules from which a policy for a specific zone can # be generated. ############################################################################ class PolicyException(Exception): pass class dnssec_policy: alg_policy = {} named_policy = {} zone_policy = {} current = None filename = None initial = True def __init__(self, filename=None, **kwargs): self.plex = PolicyLex() self.tokens = self.plex.tokens if 'debug' not in kwargs: kwargs['debug'] = False if 'write_tables' not in kwargs: kwargs['write_tables'] = False self.parser = yacc.yacc(module=self, **kwargs) # set defaults self.setup('''policy global { algorithm rsasha256; key-size ksk 2048; key-size zsk 2048; roll-period ksk 0; roll-period zsk 1y; pre-publish ksk 1mo; pre-publish zsk 1mo; post-publish ksk 1mo; post-publish zsk 1mo; standby ksk 0; standby zsk 0; keyttl 1h; coverage 6mo; }; policy default { policy global; };''') p = Policy() p.algorithm = None p.is_alg = True p.ksk_keysize = 2048; p.zsk_keysize = 2048; # set default algorithm policies # these need a lower default key size: self.alg_policy['DSA'] = copy(p) self.alg_policy['DSA'].algorithm = "DSA" self.alg_policy['DSA'].name = "DSA" self.alg_policy['DSA'].ksk_keysize = 1024; self.alg_policy['NSEC3DSA'] = copy(p) self.alg_policy['NSEC3DSA'].algorithm = "NSEC3DSA" self.alg_policy['NSEC3DSA'].name = "NSEC3DSA" self.alg_policy['NSEC3DSA'].ksk_keysize = 1024; # these can use default settings self.alg_policy['RSAMD5'] = copy(p) self.alg_policy['RSAMD5'].algorithm = "RSAMD5" self.alg_policy['RSAMD5'].name = "RSAMD5" self.alg_policy['RSASHA1'] = copy(p) self.alg_policy['RSASHA1'].algorithm = "RSASHA1" self.alg_policy['RSASHA1'].name = "RSASHA1" self.alg_policy['NSEC3RSASHA1'] = copy(p) self.alg_policy['NSEC3RSASHA1'].algorithm = "NSEC3RSASHA1" self.alg_policy['NSEC3RSASHA1'].name = "NSEC3RSASHA1" self.alg_policy['RSASHA256'] = copy(p) self.alg_policy['RSASHA256'].algorithm = "RSASHA256" self.alg_policy['RSASHA256'].name = "RSASHA256" self.alg_policy['RSASHA512'] = copy(p) self.alg_policy['RSASHA512'].algorithm = "RSASHA512" self.alg_policy['RSASHA512'].name = "RSASHA512" self.alg_policy['ECCGOST'] = copy(p) self.alg_policy['ECCGOST'].algorithm = "ECCGOST" self.alg_policy['ECCGOST'].name = "ECCGOST" self.alg_policy['ECDSAP256SHA256'] = copy(p) self.alg_policy['ECDSAP256SHA256'].algorithm = "ECDSAP256SHA256" self.alg_policy['ECDSAP256SHA256'].name = "ECDSAP256SHA256" self.alg_policy['ECDSAP256SHA256'].ksk_keysize = None; self.alg_policy['ECDSAP256SHA256'].zsk_keysize = None; self.alg_policy['ECDSAP384SHA384'] = copy(p) self.alg_policy['ECDSAP384SHA384'].algorithm = "ECDSAP384SHA384" self.alg_policy['ECDSAP384SHA384'].name = "ECDSAP384SHA384" self.alg_policy['ECDSAP384SHA384'].ksk_keysize = None; self.alg_policy['ECDSAP384SHA384'].zsk_keysize = None; self.alg_policy['ED25519'] = copy(p) self.alg_policy['ED25519'].algorithm = "ED25519" self.alg_policy['ED25519'].name = "ED25519" self.alg_policy['ED25519'].ksk_keysize = None; self.alg_policy['ED25519'].zsk_keysize = None; self.alg_policy['ED448'] = copy(p) self.alg_policy['ED448'].algorithm = "ED448" self.alg_policy['ED448'].name = "ED448" self.alg_policy['ED448'].ksk_keysize = None; self.alg_policy['ED448'].zsk_keysize = None; if filename: self.load(filename) def load(self, filename): self.filename = filename self.initial = True with open(filename) as f: text = f.read() self.plex.lexer.lineno = 0 self.parser.parse(text) self.filename = None def setup(self, text): self.initial = True self.plex.lexer.lineno = 0 self.parser.parse(text) def policy(self, zone, **kwargs): z = zone.lower() p = None if z in self.zone_policy: p = self.zone_policy[z] if p is None: p = copy(self.named_policy['default']) p.name = zone p.is_constructed = True if p.algorithm is None: parent = p.parent or self.named_policy['default'] while parent and not parent.algorithm: parent = parent.parent p.algorithm = parent and parent.algorithm or None if p.algorithm in self.alg_policy: ap = self.alg_policy[p.algorithm] else: raise PolicyException('algorithm not found') if p.directory is None: parent = p.parent or self.named_policy['default'] while parent is not None and not parent.directory: parent = parent.parent p.directory = parent and parent.directory if p.coverage is None: parent = p.parent or self.named_policy['default'] while parent and not parent.coverage: parent = parent.parent p.coverage = parent and parent.coverage or ap.coverage if p.ksk_keysize is None: parent = p.parent or self.named_policy['default'] while parent.parent and not parent.ksk_keysize: parent = parent.parent p.ksk_keysize = parent and parent.ksk_keysize or ap.ksk_keysize if p.zsk_keysize is None: parent = p.parent or self.named_policy['default'] while parent.parent and not parent.zsk_keysize: parent = parent.parent p.zsk_keysize = parent and parent.zsk_keysize or ap.zsk_keysize if p.ksk_rollperiod is None: parent = p.parent or self.named_policy['default'] while parent.parent and not parent.ksk_rollperiod: parent = parent.parent p.ksk_rollperiod = parent and \ parent.ksk_rollperiod or ap.ksk_rollperiod if p.zsk_rollperiod is None: parent = p.parent or self.named_policy['default'] while parent.parent and not parent.zsk_rollperiod: parent = parent.parent p.zsk_rollperiod = parent and \ parent.zsk_rollperiod or ap.zsk_rollperiod if p.ksk_prepublish is None: parent = p.parent or self.named_policy['default'] while parent.parent and not parent.ksk_prepublish: parent = parent.parent p.ksk_prepublish = parent and \ parent.ksk_prepublish or ap.ksk_prepublish if p.zsk_prepublish is None: parent = p.parent or self.named_policy['default'] while parent.parent and not parent.zsk_prepublish: parent = parent.parent p.zsk_prepublish = parent and \ parent.zsk_prepublish or ap.zsk_prepublish if p.ksk_postpublish is None: parent = p.parent or self.named_policy['default'] while parent.parent and not parent.ksk_postpublish: parent = parent.parent p.ksk_postpublish = parent and \ parent.ksk_postpublish or ap.ksk_postpublish if p.zsk_postpublish is None: parent = p.parent or self.named_policy['default'] while parent.parent and not parent.zsk_postpublish: parent = parent.parent p.zsk_postpublish = parent and \ parent.zsk_postpublish or ap.zsk_postpublish if p.keyttl is None: parent = p.parent or self.named_policy['default'] while parent is not None and not parent.keyttl: parent = parent.parent p.keyttl = parent and parent.keyttl if 'novalidate' not in kwargs or not kwargs['novalidate']: (valid, msg) = p.validate() if not valid: raise PolicyException(msg) return None return p def p_policylist(self, p): '''policylist : init policy | policylist policy''' pass def p_init(self, p): "init :" self.initial = False def p_policy(self, p): '''policy : alg_policy | zone_policy | named_policy''' pass def p_name(self, p): '''name : STR | KEYTYPE | DATESUFFIX''' p[0] = p[1] pass def p_domain(self, p): '''domain : STR | QSTRING | KEYTYPE | DATESUFFIX''' p[0] = p[1].strip() if not re.match(r'^[\w.-][\w.-]*$', p[0]): raise PolicyException('invalid domain') pass def p_new_policy(self, p): "new_policy :" self.current = Policy() def p_alg_policy(self, p): "alg_policy : ALGORITHM_POLICY ALGNAME new_policy alg_option_group SEMI" self.current.name = p[2] self.current.is_alg = True self.alg_policy[p[2]] = self.current pass def p_zone_policy(self, p): "zone_policy : ZONE domain new_policy policy_option_group SEMI" self.current.name = p[2].rstrip('.') self.current.is_zone = True self.zone_policy[p[2].rstrip('.').lower()] = self.current pass def p_named_policy(self, p): "named_policy : POLICY name new_policy policy_option_group SEMI" self.current.name = p[2] self.named_policy[p[2].lower()] = self.current pass def p_duration_1(self, p): "duration : NUMBER" p[0] = p[1] pass def p_duration_2(self, p): "duration : NONE" p[0] = None pass def p_duration_3(self, p): "duration : NUMBER DATESUFFIX" if p[2] == "y": p[0] = p[1] * 31536000 # year elif p[2] == "mo": p[0] = p[1] * 2592000 # month elif p[2] == "w": p[0] = p[1] * 604800 # week elif p[2] == "d": p[0] = p[1] * 86400 # day elif p[2] == "h": p[0] = p[1] * 3600 # hour elif p[2] == "mi": p[0] = p[1] * 60 # minute elif p[2] == "s": p[0] = p[1] # second else: raise PolicyException('invalid duration') def p_policy_option_group(self, p): "policy_option_group : LBRACE policy_option_list RBRACE" pass def p_policy_option_list(self, p): '''policy_option_list : policy_option SEMI | policy_option_list policy_option SEMI''' pass def p_policy_option(self, p): '''policy_option : parent_option | directory_option | coverage_option | rollperiod_option | prepublish_option | postpublish_option | keysize_option | algorithm_option | keyttl_option | standby_option''' pass def p_alg_option_group(self, p): "alg_option_group : LBRACE alg_option_list RBRACE" pass def p_alg_option_list(self, p): '''alg_option_list : alg_option SEMI | alg_option_list alg_option SEMI''' pass def p_alg_option(self, p): '''alg_option : coverage_option | rollperiod_option | prepublish_option | postpublish_option | keyttl_option | keysize_option | standby_option''' pass def p_parent_option(self, p): "parent_option : POLICY name" self.current.parent = self.named_policy[p[2].lower()] def p_directory_option(self, p): "directory_option : DIRECTORY QSTRING" self.current.directory = p[2] def p_coverage_option(self, p): "coverage_option : COVERAGE duration" self.current.coverage = p[2] def p_rollperiod_option(self, p): "rollperiod_option : ROLL_PERIOD KEYTYPE duration" if p[2] == "KSK": self.current.ksk_rollperiod = p[3] else: self.current.zsk_rollperiod = p[3] def p_prepublish_option(self, p): "prepublish_option : PRE_PUBLISH KEYTYPE duration" if p[2] == "KSK": self.current.ksk_prepublish = p[3] else: self.current.zsk_prepublish = p[3] def p_postpublish_option(self, p): "postpublish_option : POST_PUBLISH KEYTYPE duration" if p[2] == "KSK": self.current.ksk_postpublish = p[3] else: self.current.zsk_postpublish = p[3] def p_keysize_option(self, p): "keysize_option : KEY_SIZE KEYTYPE NUMBER" if p[2] == "KSK": self.current.ksk_keysize = p[3] else: self.current.zsk_keysize = p[3] def p_standby_option(self, p): "standby_option : STANDBY KEYTYPE NUMBER" if p[2] == "KSK": self.current.ksk_standby = p[3] else: self.current.zsk_standby = p[3] def p_keyttl_option(self, p): "keyttl_option : KEYTTL duration" self.current.keyttl = p[2] def p_algorithm_option(self, p): "algorithm_option : ALGORITHM ALGNAME" self.current.algorithm = p[2] def p_error(self, p): if p: print("%s%s%d:syntax error near '%s'" % (self.filename or "", ":" if self.filename else "", p.lineno, p.value)) else: if not self.initial: raise PolicyException("%s%s%d:unexpected end of input" % (self.filename or "", ":" if self.filename else "", p and p.lineno or 0)) if __name__ == "__main__": import sys if sys.argv[1] == "lex": file = open(sys.argv[2]) text = file.read() file.close() plex = PolicyLex(debug=1) plex.test(text) elif sys.argv[1] == "parse": try: pp = dnssec_policy(sys.argv[2], write_tables=True, debug=True) print(pp.named_policy['default']) print(pp.policy("nonexistent.zone")) except Exception as e: print(e.args[0]) PK!~Q3++rndc.pynu[############################################################################ # Copyright (C) Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, you can obtain one at https://mozilla.org/MPL/2.0/. # # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. ############################################################################ ############################################################################ # rndc.py # This module implements the RNDC control protocol. ############################################################################ from collections import OrderedDict import time import struct import hashlib import hmac import base64 import random import socket class rndc(object): """RNDC protocol client library""" __algos = {'md5': 157, 'sha1': 161, 'sha224': 162, 'sha256': 163, 'sha384': 164, 'sha512': 165} def __init__(self, host, algo, secret): """Creates a persistent connection to RNDC and logs in host - (ip, port) tuple algo - HMAC algorithm: one of md5, sha1, sha224, sha256, sha384, sha512 (with optional prefix 'hmac-') secret - HMAC secret, base64 encoded""" self.host = host algo = algo.lower() if algo.startswith('hmac-'): algo = algo[5:] self.algo = algo self.hlalgo = getattr(hashlib, algo) self.secret = base64.b64decode(secret) self.ser = random.randint(0, 1 << 24) self.nonce = None self.__connect_login() def call(self, cmd): """Call a RNDC command, all parsing is done on the server side cmd - a complete string with a command (eg 'reload zone example.com') """ return dict(self.__command(type=cmd)['_data']) def __serialize_dict(self, data, ignore_auth=False): rv = bytearray() for k, v in data.items(): if ignore_auth and k == '_auth': continue rv += struct.pack('B', len(k)) + k.encode('ascii') if type(v) == str: rv += struct.pack('>BI', 1, len(v)) + v.encode('ascii') elif type(v) == bytes: rv += struct.pack('>BI', 1, len(v)) + v elif type(v) == bytearray: rv += struct.pack('>BI', 1, len(v)) + v elif type(v) == OrderedDict: sd = self.__serialize_dict(v) rv += struct.pack('>BI', 2, len(sd)) + sd else: raise NotImplementedError('Cannot serialize element of type %s' % type(v)) return rv def __prep_message(self, *args, **kwargs): self.ser += 1 now = int(time.time()) data = OrderedDict(*args, **kwargs) d = OrderedDict() d['_auth'] = OrderedDict() d['_ctrl'] = OrderedDict() d['_ctrl']['_ser'] = str(self.ser) d['_ctrl']['_tim'] = str(now) d['_ctrl']['_exp'] = str(now+60) if self.nonce is not None: d['_ctrl']['_nonce'] = self.nonce d['_data'] = data msg = self.__serialize_dict(d, ignore_auth=True) hash = hmac.new(self.secret, msg, self.hlalgo).digest() bhash = base64.b64encode(hash) if self.algo == 'md5': d['_auth']['hmd5'] = struct.pack('22s', bhash) else: d['_auth']['hsha'] = bytearray(struct.pack('B88s', self.__algos[self.algo], bhash)) msg = self.__serialize_dict(d) msg = struct.pack('>II', len(msg) + 4, 1) + msg return msg def __verify_msg(self, msg): if self.nonce is not None and msg['_ctrl']['_nonce'] != self.nonce: return False if self.algo == 'md5': bhash = msg['_auth']['hmd5'] else: bhash = msg['_auth']['hsha'][1:] if type(bhash) == bytes: bhash = bhash.decode('ascii') bhash += '=' * (4 - (len(bhash) % 4)) remote_hash = base64.b64decode(bhash) my_msg = self.__serialize_dict(msg, ignore_auth=True) my_hash = hmac.new(self.secret, my_msg, self.hlalgo).digest() return (my_hash == remote_hash) def __command(self, *args, **kwargs): msg = self.__prep_message(*args, **kwargs) sent = self.socket.send(msg) if sent != len(msg): raise IOError("Cannot send the message") header = self.socket.recv(8) if len(header) != 8: # What should we throw here? Bad auth can cause this... raise IOError("Can't read response header") length, version = struct.unpack('>II', header) if version != 1: raise NotImplementedError('Wrong message version %d' % version) # it includes the header length -= 4 data = self.socket.recv(length, socket.MSG_WAITALL) if len(data) != length: raise IOError("Can't read response data") if type(data) == str: data = bytearray(data) msg = self.__parse_message(data) if not self.__verify_msg(msg): raise IOError("Authentication failure") return msg def __connect_login(self): self.socket = socket.create_connection(self.host) self.nonce = None msg = self.__command(type='null') self.nonce = msg['_ctrl']['_nonce'] def __parse_element(self, input): pos = 0 labellen = input[pos] pos += 1 label = input[pos:pos+labellen].decode('ascii') pos += labellen type = input[pos] pos += 1 datalen = struct.unpack('>I', input[pos:pos+4])[0] pos += 4 data = input[pos:pos+datalen] pos += datalen rest = input[pos:] if type == 1: # raw binary value return label, data, rest elif type == 2: # dictionary d = OrderedDict() while len(data) > 0: ilabel, value, data = self.__parse_element(data) d[ilabel] = value return label, d, rest # TODO type 3 - list else: raise NotImplementedError('Unknown element type %d' % type) def __parse_message(self, input): rv = OrderedDict() hdata = None while len(input) > 0: label, value, input = self.__parse_element(input) rv[label] = value return rv PK!utils.pynu[############################################################################ # Copyright (C) Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, you can obtain one at https://mozilla.org/MPL/2.0/. # # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. ############################################################################ import os # These routines permit platform-independent location of BIND 9 tools if os.name == 'nt': import win32con import win32api def prefix(bindir=''): if os.name != 'nt': return os.path.join('/usr', bindir) hklm = win32con.HKEY_LOCAL_MACHINE bind_subkey = "Software\\ISC\\BIND" sam = win32con.KEY_READ h_key = None key_found = True # can fail if the registry redirected for 32/64 bits try: h_key = win32api.RegOpenKeyEx(hklm, bind_subkey, 0, sam) except: key_found = False # retry for 32 bit python with 64 bit bind9 if not key_found: key_found = True sam64 = sam | win32con.KEY_WOW64_64KEY try: h_key = win32api.RegOpenKeyEx(hklm, bind_subkey, 0, sam64) except: key_found = False # retry 64 bit python with 32 bit bind9 if not key_found: key_found = True sam32 = sam | win32con.KEY_WOW64_32KEY try: h_key = win32api.RegOpenKeyEx(hklm, bind_subkey, 0, sam32) except: key_found = False if key_found: try: (named_base, _) = win32api.RegQueryValueEx(h_key, "InstallDir") except: key_found = False win32api.RegCloseKey(h_key) if key_found: return os.path.join(named_base, bindir) return os.path.join(win32api.GetSystemDirectory(), bindir) def shellquote(s): if os.name == 'nt': return '"' + s.replace('"', '"\\"') + '"' return "'" + s.replace("'", "'\\''") + "'" version = '9.11.36-RedHat-9.11.36-16.el8_10.2' if os.name != 'nt': sysconfdir = '/etc' else: sysconfdir = prefix('etc') PK! &__pycache__/utils.cpython-36.opt-1.pycnu[PK!  __pycache__/utils.cpython-36.pycnu[PK!ņ), __pycache__/__init__.cpython-36.opt-1.pycnu[PK!ņ#i __pycache__/__init__.cpython-36.pycnu[PK!\=(__pycache__/checkds.cpython-36.opt-1.pycnu[PK!\="__pycache__/checkds.cpython-36.pycnu[PK!l)0__pycache__/coverage.cpython-36.opt-1.pycnu[PK!l#I__pycache__/coverage.cpython-36.pycnu[PK!1X5X5'c__pycache__/dnskey.cpython-36.opt-1.pycnu[PK!1X5X5!__pycache__/dnskey.cpython-36.pycnu[PK!*h__pycache__/eventlist.cpython-36.opt-1.pycnu[PK!$__pycache__/eventlist.cpython-36.pycnu[PK!FN7 (__pycache__/keydict.cpython-36.opt-1.pycnu[PK!FN7 "'__pycache__/keydict.cpython-36.pycnu[PK!N@@)__pycache__/keyevent.cpython-36.opt-1.pycnu[PK!N@@# __pycache__/keyevent.cpython-36.pycnu[PK!@ uu'__pycache__/keymgr.cpython-36.opt-1.pycnu[PK!@ uu!|!__pycache__/keymgr.cpython-36.pycnu[PK!1}n*B2__pycache__/keyseries.cpython-36.opt-1.pycnu[PK!1}n$aD__pycache__/keyseries.cpython-36.pycnu[PK!S (zV__pycache__/keyzone.cpython-36.opt-1.pycnu[PK!S "[__pycache__/keyzone.cpython-36.pycnu[PK!ܴ@)`__pycache__/parsetab.cpython-36.opt-1.pycnu[PK!ܴ@#{__pycache__/parsetab.cpython-36.pycnu[PK!LLL'__pycache__/policy.cpython-36.opt-1.pycnu[PK!LLL!__pycache__/policy.cpython-36.pycnu[PK!S%0__pycache__/rndc.cpython-36.opt-1.pycnu[PK!SD__pycache__/rndc.cpython-36.pycnu[PK!`J *Y__init__.pynu[PK!'ס&& ]checkds.pynu[PK!5&& nxcoverage.pynu[PK!WC @ @ dnskey.pynu[PK!A eventlist.pynu[PK!+V! ! keydict.pynu[PK!׀} nkeyevent.pynu[PK!T\kk  keymgr.pynu[PK!M2"" X'keyseries.pynu[PK!Snտ Ikeyzone.pynu[PK!oެX}} Qparsetab.pynu[PK!=2g2g Wqpolicy.pynu[PK!~Q3++rndc.pynu[PK!$utils.pynu[PK**