commit 2034e94d7efec66ac0ad8bd06d7a72b7a17d3bd6 Author: Florian Obser Date: Fri Dec 2 15:51:07 2022 +0100 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2d19fc7 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.html diff --git a/algorithm-roll.org b/algorithm-roll.org new file mode 100644 index 0000000..4bfc19f --- /dev/null +++ b/algorithm-roll.org @@ -0,0 +1,198 @@ +#+TITLE: DNSSEC algorithm roll-over +#+DATE: 2020-06-08 + +* Intro +tlakh.xyz uses [[https://powerdns.com/][PowerDNS]] running on OpenBSD as a hidden signer. Zones +are transferred via AXFR to authoritative nameservers running [[https://www.nlnetlabs.nl/projects/nsd/about/][NSD]] on +OpenBSD. Version 4.3 of PowerDNS introduced support for [[https://doc.powerdns.com/authoritative/changelog/4.3.html#change-8b0ef5df0dad7b9d5c3c8957a3022cec][algorithm +roll-overs]]. We wanted to change the signing algorithm from =RSASHA512= +(Algorithm 10) to =ECDSAP256SHA256= (Algorithm 13) as recommended by +[[https://tools.ietf.org/html/rfc8624#section-3.2][RFC 8624]]. We followed [[https://tools.ietf.org/html/rfc6781.html#section-4.1.4][RFC 6781]] for the rollover steps. +* Roll-over +The following subsections will use the state names from [[https://tools.ietf.org/html/rfc6781.html#section-4.1.4][RFC 6781]]. +** initial +On June 8th 2020 tlakh.xyz was signed with RSASHA512 (Algorithm +10). We wanted to change the algorithm to ECDSAP256SHA256 (Algorithm +13). +#+begin_example +$ pdnsutil list-keys tlakh.xyz +Zone Type Size Algorithm ID Location Keytag +---------------------------------------------------------------------------------- +tlakh.xyz ZSK 2048 RSASHA512 6 cryptokeys 65156 +tlakh.xyz KSK 4096 RSASHA512 5 cryptokeys 15216 +#+end_example +** new RRSIGs +DNSKEYs and RRSIGs in the tlakh.xyz zone have a TTL of 86000 seconds +(1 day): +#+begin_example +$ dig @a.ns.sha256.net. +dnssec +norec +noall +answer tlakh.xyz DNSKEY +tlakh.xyz. 86400 IN DNSKEY 256 3 10 AwEAAaqRIYWrsASI40dwuwfbo04WT0SAKOi3espbBQuRIRS0t74isCgN H7lCzOf5AW50fwSWpceiY5CB7gddvKCJIJyBrRLkaFdT5cPGDfklNcYY Cp+pv8u1umzoiDtpoDZcnqtO7+0TuGZVweMLrVajrapZkeSp3h4I1kDw PQhcpcJnuYeN/nMtLggfX19X/sXPKo6Gm23n3gTXp8EZu9dGy5KcQYdx ilQCUL2RVJqoYBDOoLtF3spthEXbsxDobCPz2zbzENvNWLtV7aZSiefu SoBfZlGxC9eWypo5LtCaJlfQiUktFrB0BqrmIWqHxuAa2c1+bZuhdlEq 4Oa+UGd4N9M= +tlakh.xyz. 86400 IN DNSKEY 257 3 10 AwEAAeoCANNycAHU3FtrctGycQ1/I5pN8iWNSZVhruxJsyiD75H7Mzet /gWRLiNmJ6e/aFPYuvWtdOjFyfOec5gIlI9J9cxY4L3KRSkeB/wjPkxf 9GXvqxcDLg3P1eaC63/rPdhjfgq3nE3Bw3NXlTuD6SWB6YdfioiyVo+e JThrYhaFqKzPqZbGn3fEGuOp39zJ+Qunq98Vg7oTh0ch3k2H9XhRP3W+ zEPnvmPKLo9+k92xvfZasgCay8vjaNRQubn9nNtNwUPKJSCIXKvmrykB PLAXBcjHlFSc6D7g4jVwzWrYtEeAA+fxqA/UBXGFrJWC3ZdD/mtDkT+v JKAL4HqCojFrRKgWq//QenhjZeZ0Efq767ZvZvqoyNweTcwGdXYteRCB R0qV4TLjD8vMczMfFboZkEJo4Xj8xDDmoslErlMGsC8TJ0uQeKB6YqKI dRJqQwtrFHx+rxFvA3+SAcKlccjZo2024f2Rq0lUSb838j1z1xY9ACh/ ht0ixk0bArQ/TdqNC6SwTniiQaJfmIik64gCZE7sxMJmryxkEjtHiLie Czls4RUMpuIc3F6d/3Gq75sgt129bYWWzNIsGaqZKL97Zl4qVpOsK3I7 yX7gNR7ogp7d/bGj11BUOU3ZsmJ30tvcD8CdNhokXFTyx8Z4QvNuUJKt TalgU/yRpCwTclRB +tlakh.xyz. 86400 IN RRSIG DNSKEY 10 2 86400 20200618000000 20200528000000 15216 tlakh.xyz. gE3lNMY/Ted8nvgXH+rBm+uuKMUly5fp061Hd9kePhZSvZWzH2gaaTaJ s0kXUNBYsuUX1BeThZWPLqJDEKk9hkiffT8Mt7dBVsP9cS7rj8sM10st UWN7vrxpY4dcToknuyRaIiHU7K0/0pGWcgUcTJnwfuJfmDYexNZUf4mW kG5Ro89sSLZR3c9peKvXUig7f61e3QbS1m0h1ZsEf/hQuozb354z+x2I 0zv1LqFZt8IOTF5AD5RcZe1OatJlF02Z5Yzkj75uwa5MTD8Gfwu1vmTL 9gOieVu+10PJub7y62kcr5ZMmkUXeTHcMG+Oy6Y9IOMBMF2btNmCDY2P rGNReiRDSnQEU9726KeVGtlhyAjqDwCFuFWYug3cCJZ98aQrOXSjWXTG XyOyO+fxT2BfzUbq4L35xv34f83g5ulZvFO/oUXz1Rulhut3UUSGyev3 jqzQ4VIcYwsXRRWrlG+fZUhYtDjXCcqAtZyHtOY2oU5CNKuYDvyZMdAQ voecdB0VzzX3TXBV+ykpPeLp/qOKhxRYZao4p7ZkXqHAxSXjrV3ws2// CQhD43ex+qleMGPrlQkHa5sjwGhgvfEyqV2YKOcq41I/j8nltHoZy2sR 6NlFv1TAWlNgK4bHGQmQHTnC95URgSzFuemy4d6JDo/htFLfTIMRjWbj 9OqBoT/8xgw= +#+end_example + +After introducing RRSIGs made with the new key we had to wait at least +1 day for the new RRset to propagate to caches. At about 16:45 UTC on +June 8th 2020 we introduced new ZSK and KSK keys with algorithm 13 but +set the key to unpublished: +#+begin_example +$ pdnsutil add-zone-key tlakh.xyz zsk active unpublished ecdsa256 +Added a ZSK with algorithm = 13, active=1 +$ pdnsutil add-zone-key tlakh.xyz ksk active unpublished ecdsa256 +Added a KSK with algorithm = 13, active=1 +$ pdnsutil list-keys tlakh.xyz +Zone Type Size Algorithm ID Location Keytag +---------------------------------------------------------------------------------- +tlakh.xyz ZSK 2048 RSASHA512 6 cryptokeys 65156 +tlakh.xyz ZSK 256 ECDSAP256SHA256 13 cryptokeys 60132 +tlakh.xyz KSK 4096 RSASHA512 5 cryptokeys 15216 +tlakh.xyz KSK 256 ECDSAP256SHA256 14 cryptokeys 22433 +#+end_example + +The newly signed zone had now double signatures: +#+begin_example +$ dig @a.ns.sha256.net. +dnssec +norec +noall +answer tlakh.xyz A +tlakh.xyz. 86400 IN A 45.32.179.105 +tlakh.xyz. 86400 IN RRSIG A 10 2 86400 20200618000000 20200528000000 65156 tlakh.xyz. ocpnfmI2U0l24+PGUhiJwYaezqpFnpTgTphW6zfuc8uIqYrc94xcGx9o 9Bt6RoSWd1X0DG2BKWZKHI+5NEFZ1YQvTP3n5MzPNP8f9KCUkriY0Y6z RwxZJK9x/m5HuB9Nd1+sASFzc4rZme/EKGFvbGooAznFe2WAxblNLxA/ yrXHwuP5tBh4SYrgayQCFWHgrbtJfS57d/s/KorwhwQIAsiqLg68rFV3 IPjaKjWWgQfEsiAq0fuEULuRTZffqdMrLtzj9LHo2h3n9jKwHZ/B/8Cs gi3/Cu62PlBOtSRBi107jyC6TXmTzyK6YdhjJ0heam3eFXo7vSAmmTj8 UagaIQ== +tlakh.xyz. 86400 IN RRSIG A 13 2 86400 20200618000000 20200528000000 60132 tlakh.xyz. Gqg0ML2H/O3EFSH1IolyrwGmbt/U6RkMxHnz7w1OGzmP+d4c7hyFuNdb 2zZXlTVYws0RnExAoY/3rOF7dTa3IA== +#+end_example + +[[https://dnsviz.net/d/tlakh.xyz/Xt5ssA/dnssec/][dnsviz]] ([[file:algorithm-roll/tlakh.xyz-2020-06-08-16_52_00-UTC.png][local copy]]) also saw RRsets from the new keys but not the keys +themselves. + +** new DNSKEY +At about 16:55 UTC on June 9th 2020 we published the new DNSKEYs: +#+begin_example +$ pdnsutil publish-zone-key tlakh.xyz 13 +$ pdnsutil publish-zone-key tlakh.xyz 14 +#+end_example + +The newly signed zone now had 4 DNSKEYs: +#+begin_example +$ dig @a.ns.sha256.net. +dnssec +norec +noall +answer tlakh.xyz DNSKEY +tlakh.xyz. 86400 IN DNSKEY 256 3 10 AwEAAaqRIYWrsASI40dwuwfbo04WT0SAKOi3espbBQuRIRS0t74isCgN H7lCzOf5AW50fwSWpceiY5CB7gddvKCJIJyBrRLkaFdT5cPGDfklNcYY Cp+pv8u1umzoiDtpoDZcnqtO7+0TuGZVweMLrVajrapZkeSp3h4I1kDw PQhcpcJnuYeN/nMtLggfX19X/sXPKo6Gm23n3gTXp8EZu9dGy5KcQYdx ilQCUL2RVJqoYBDOoLtF3spthEXbsxDobCPz2zbzENvNWLtV7aZSiefu SoBfZlGxC9eWypo5LtCaJlfQiUktFrB0BqrmIWqHxuAa2c1+bZuhdlEq 4Oa+UGd4N9M= +tlakh.xyz. 86400 IN DNSKEY 256 3 13 9Du0N8A9jI+w3gbBcuyaaL9YMM/ooAJvvpewmooIfWajgFPyLvGhr0zR ylhMCoVtbl4XSMD+di1LMiAIhPN9Eg== +tlakh.xyz. 86400 IN DNSKEY 257 3 10 AwEAAeoCANNycAHU3FtrctGycQ1/I5pN8iWNSZVhruxJsyiD75H7Mzet /gWRLiNmJ6e/aFPYuvWtdOjFyfOec5gIlI9J9cxY4L3KRSkeB/wjPkxf 9GXvqxcDLg3P1eaC63/rPdhjfgq3nE3Bw3NXlTuD6SWB6YdfioiyVo+e JThrYhaFqKzPqZbGn3fEGuOp39zJ+Qunq98Vg7oTh0ch3k2H9XhRP3W+ zEPnvmPKLo9+k92xvfZasgCay8vjaNRQubn9nNtNwUPKJSCIXKvmrykB PLAXBcjHlFSc6D7g4jVwzWrYtEeAA+fxqA/UBXGFrJWC3ZdD/mtDkT+v JKAL4HqCojFrRKgWq//QenhjZeZ0Efq767ZvZvqoyNweTcwGdXYteRCB R0qV4TLjD8vMczMfFboZkEJo4Xj8xDDmoslErlMGsC8TJ0uQeKB6YqKI dRJqQwtrFHx+rxFvA3+SAcKlccjZo2024f2Rq0lUSb838j1z1xY9ACh/ ht0ixk0bArQ/TdqNC6SwTniiQaJfmIik64gCZE7sxMJmryxkEjtHiLie Czls4RUMpuIc3F6d/3Gq75sgt129bYWWzNIsGaqZKL97Zl4qVpOsK3I7 yX7gNR7ogp7d/bGj11BUOU3ZsmJ30tvcD8CdNhokXFTyx8Z4QvNuUJKt TalgU/yRpCwTclRB +tlakh.xyz. 86400 IN DNSKEY 257 3 13 p3cC5drs8jRsY7um9Bb4QyEfecpyY5oXh45X4FskftvDAda46SVT9WVe uqIgofK/XfEW15ugLkWjF5uHCKPWsw== +tlakh.xyz. 86400 IN RRSIG DNSKEY 10 2 86400 20200618000000 20200528000000 15216 tlakh.xyz. H5ZuAY1cMy3IPQiRahFzO4XeFpkFD1IRNSxffBL/JrfAsg3WuKEHBjhN NefYeMccydd/TB4A+D01xUKHqTEg6HhEbeCdzbihEmgHZeMXIt6G/OVA jWqEyspahK5AbDyIAWoKInaDC9NfHA8uxqFmnU7dpVg26hhuAaiQJE7j RxyoKXZY857jzEZf6E62QHw/7l9z/e5R94R/Nfc73Ch57MyWsH7pY+CS KXI6KhrfK5wY/paDPLzWP48KZ5VoP+laPFSV1qFYFa40hk/Z0wbZGQSm iKrk3Dfu6lagEeYfXDaCzISauwCYbxTw4l8adXbbBypAtdrFqcUaaCZG 5KjOFcYrUtymaucShbwjfcWrZdJTd4D32tNrWhv17QQCM1k3M7uO8FdG jyPPfoChRSh3Hd5h4v8z2bkjIrMd4Z54xeaxoL49+2R0L0ei6L/4pxap 7SVVOkqICTlT4nMI2XihTEmmqFeOQNoKdgYb/VHZqWP9n8jqlXf5emr6 UQS8bSH1pjigslY7ug8bW/tvfcPX2AtAXW2M0HmxgOlbxFC8AqYJom5l dqpPbTeyyXawE/TBf/naAvkXpzyYoIU1N5oI4ckRyEaJEO2rjgmtn4fA JDo2HjMmssFyiH/pGSSiV/ZbOqri6XecsKOIgr5LvzMeAHRkw9od2Kmg Y9NUjUfPMVk= +tlakh.xyz. 86400 IN RRSIG DNSKEY 13 2 86400 20200618000000 20200528000000 22433 tlakh.xyz. rtFezrjl4R0A8SvyYCDg5M1SNASINPcLqNdYzveKqq80sVqKwmvr+o9l IQMFPE5PMIFYC7SS5utV8I5RqNV/7Q== +#+end_example + +[[https://dnsviz.net/d/tlakh.xyz/Xt-_BQ/dnssec/][dnsviz]] ([[file:algorithm-roll/tlakh.xyz-2020-06-09-16_55_33-UTC.png][local copy]]) also saw all DNSKEYs. There seemed to be arrows +missing from the DNSKEY with id 22433 to all other DNSKEYs on the +dnsviz visualisation but the [[https://dnsviz.net/d/tlakh.xyz/Xt-_BQ/responses/][responses]] showed the RRSIG from the new +DNSKEY. + +** new DS +The old DNSKYE RRset containing only two keys expired around 17:00 UTC +on June 10th 2020. At this point the old DS record could have been +replaced with a new DS record but we didn't get around to it. + +We continued on the morning of the 11th, first we fetched the NS set +for xyz: +#+begin_example +$ dig +noall +answer xyz NS +xyz. 37933 IN NS x.nic.xyz. +xyz. 37933 IN NS y.nic.xyz. +xyz. 37933 IN NS z.nic.xyz. +xyz. 37933 IN NS generationxyz.nic.xyz. +#+end_example + +and checked all of them for the DS record for tlakh.xyz: +#+begin_example +$ for i in x y z generationxyz; do dig @$i.nic.xyz +noall +answer tlakh.xyz DS; done +tlakh.xyz. 3600 IN DS 15216 10 2 38C610B933677FC6BB5E39E3649646691AABDD5100D0BF6362E5A095 4477CC8A +tlakh.xyz. 3600 IN DS 15216 10 2 38C610B933677FC6BB5E39E3649646691AABDD5100D0BF6362E5A095 4477CC8A +tlakh.xyz. 3600 IN DS 15216 10 2 38C610B933677FC6BB5E39E3649646691AABDD5100D0BF6362E5A095 4477CC8A +tlakh.xyz. 3600 IN DS 15216 10 2 38C610B933677FC6BB5E39E3649646691AABDD5100D0BF6362E5A095 4477CC8A +#+end_example + +The TTL was 3600 seconds or one hour. After introducing the new DS +record we had to wait at least this long. This is complicated by the +fact that we did not now how long it would take for the DS record to +show up in the xyz zone and how long it would take for the xyz zone to +propagate to all authoritative nameservers. xyz probably employed +anycast as well so it would be very difficult for us to observe all +nameservers. The registrar for tlakh.xyz wants the DNSKEY to submit +the DS record to the registry: +#+begin_example +$ pdnsutil export-zone-dnskey tlakh.xyz 14 +tlakh.xyz IN DNSKEY 257 3 13 p3cC5drs8jRsY7um9Bb4QyEfecpyY5oXh45X4FskftvDAda46SVT9WVeuqIgofK/XfEW15ugLkWjF5uHCKPWsw== +#+end_example + +We entered the DNSKEY in the registrar webinterface at about 05:45 UTC +on June 11th 2020. At 05:52 we started to see the new DS record on +some authoritative nameservers: +#+begin_example +$ for i in x y z generationxyz; do dig @$i.nic.xyz +noall +answer tlakh.xyz DS; done +tlakh.xyz. 3600 IN DS 15216 10 2 38C610B933677FC6BB5E39E3649646691AABDD5100D0BF6362E5A095 4477CC8A +tlakh.xyz. 3600 IN DS 22433 13 2 692C34230671F2CD2A2D7DC7432B373B556D357787883DE754660A69 E4F6D05F +tlakh.xyz. 3600 IN DS 22433 13 2 692C34230671F2CD2A2D7DC7432B373B556D357787883DE754660A69 E4F6D05F +tlakh.xyz. 3600 IN DS 15216 10 2 38C610B933677FC6BB5E39E3649646691AABDD5100D0BF6362E5A095 4477CC8A +#+end_example + +And at 05:53 it was visible on all nameservers, at least from this +vantage point: +#+begin_example +$ for i in x y z generationxyz; do dig @$i.nic.xyz +noall +answer +norec tlakh.xyz DS; done +tlakh.xyz. 3600 IN DS 22433 13 2 692C34230671F2CD2A2D7DC7432B373B556D357787883DE754660A69 E4F6D05F +tlakh.xyz. 3600 IN DS 22433 13 2 692C34230671F2CD2A2D7DC7432B373B556D357787883DE754660A69 E4F6D05F +tlakh.xyz. 3600 IN DS 22433 13 2 692C34230671F2CD2A2D7DC7432B373B556D357787883DE754660A69 E4F6D05F +tlakh.xyz. 3600 IN DS 22433 13 2 692C34230671F2CD2A2D7DC7432B373B556D357787883DE754660A69 E4F6D05F +#+end_example + +We then setup 4 RIPE Atlas measurements to query [[https://atlas.ripe.net/measurements/25704650/][x.nic.xyz]], [[https://atlas.ripe.net/measurements/25704651/][y.nic.xyz]], +[[https://atlas.ripe.net/measurements/25704652/][z.nic.xyz]], and [[https://atlas.ripe.net/measurements/25704654/][generationxyz.nic.xyz]] for the DS record of tlakh.xyz +from 500 probes world wide. We used the RIPE Atlas cli tool to analyse +the results, for example for x.nic.xyz: +#+begin_example +$ ripe-atlas report 25704650 | fgrep DS | sort | uniq -c + 468 ;tlakh.xyz. IN DS + 1 tlakh.xyz. 3577 IN DS 22433 13 2 692c34230671f2cd2a2d7dc7432b373b556d357787883de754660a69e4f6d05f + 457 tlakh.xyz. 3600 IN DS 22433 13 2 692c34230671f2cd2a2d7dc7432b373b556d357787883de754660a69e4f6d05f +#+end_example + +At about 06:00 UTC we were confident that the new DS record had +propagated world wide. [[https://dnsviz.net/d/tlakh.xyz/XuHKww/dnssec/][dnsviz]] ([[file:algorithm-roll/tlakh.xyz-2020-06-11-06_10_11-UTC.png][local copy]]) saw the new DS record +pointing to the new DNSKEY. +** DNSKEY removal +With a TTL of one hour for the DS record in the xyz zone the old +DNSKEYs could have been removed at 07:00 UTC on June 11th 2020. We +removed them one hour later, at around 08:00 UTC: +#+begin_example +$ pdnsutil unpublish-zone-key tlakh.xyz 6 +$ pdnsutil unpublish-zone-key tlakh.xyz 5 +#+end_example + +We saw two DNSKEYs instead of four, one ZSK and one KSK. There are +still two RRSIGs, one with algorithm 10, the old one and one with +algorithm 13 since we only unpublished the old keys but they are still +used for signing. +#+begin_example +$ dig @a.ns.sha256.net. +dnssec +norec +noall +answer tlakh.xyz DNSKEY +tlakh.xyz. 86400 IN DNSKEY 256 3 13 9Du0N8A9jI+w3gbBcuyaaL9YMM/ooAJvvpewmooIfWajgFPyLvGhr0zR ylhMCoVtbl4XSMD+di1LMiAIhPN9Eg== +tlakh.xyz. 86400 IN DNSKEY 257 3 13 p3cC5drs8jRsY7um9Bb4QyEfecpyY5oXh45X4FskftvDAda46SVT9WVe uqIgofK/XfEW15ugLkWjF5uHCKPWsw== +tlakh.xyz. 86400 IN RRSIG DNSKEY 10 2 86400 20200625000000 20200604000000 15216 tlakh.xyz. dGiAsG2KyIgivCEsEwXpCUg8vHspOJcDavDWF4ob5D4AaGxOg2rsUDeu AhbNRfKjWVwNOYNf4zxyqqDNAQeyU00ZsrBDhWkz4gGH8MHddB8quLzX vQDjhv4gHepidFOy1QIyKGsgvwPoxSDf5VpHYJxUiZKSq1AERT/IeR0Q DOqQcJ/UAjRLdXDox3JqFnwmvXoyY5SDjxIoHiRU5gnmEmDpFyvrLMUY SfQ8LvU4KV0UFIPWHjyApgysk2YFJfLWFiKrBZMAaD/aD6rTuvPIdPq7 AYGC5YpsR3+6m6S1uKKfeC2ZdnacKdVgVWcIuL3KrnHflpSGtEcL7Y2V gBYY96eEWKSQ8IlOp5fpIQbQcw31R3dQeQWuac8U3NmH+X2UNzZtozLI 5d5U8ZqYZKkoVh6K4cCxZjkx6UnFeSL4FAHxFc05/1sixED8ueFhCa15 NdKaRpPJXjTAqN5Ans8Z/jJ+aosg7Cnn7BrQTg0/qhU9TYY7U8PdaBaP cCwrkENdA1LvitXa/kI9G2r9c0WMkUh5zOcVxytmYot5zVzjXoB7lD2q OE0efBCKEfwI93aOD3CdS/9aE6eB7A0TAhI/MejCho3dNFM48TF57EHc 1WOVxFVdAYyw8bcKTFV5sQOzt5YN3iU4TD4Y3ZnJ0w3/LhD24ngm/A3p zNmtB2mqwhI= +tlakh.xyz. 86400 IN RRSIG DNSKEY 13 2 86400 20200625000000 20200604000000 22433 tlakh.xyz. CbBp81aMiMLXoAbJuPA0XymHiYJGyWiIKXxAQpoTWGN7sc2P/mF/Ea9V Rg1tYw392vEhM/bi9GjHHnzNQR6+1g== +#+end_example + +[[https://dnsviz.net/d/tlakh.xyz/XuHlmg/dnssec/][dnsviz]] ([[file:algorithm-roll/tlakh.xyz-2020-06-11-08_04_42-UTC.png][local copy]]) saw RRSIGs from the old key but no longer the key. + +** RRSIGs removal +One day later, at about 08:15 on June 12th 2020 it was time to +completely remove the old keys: +#+begin_example +$ pdnsutil remove-zone-key tlakh.xyz 5 +$ pdnsutil remove-zone-key tlakh.xyz 6 +#+end_example + +The DNSKYEY RRset was only signed by the new and now only KSK key: +#+begin_example +$ dig @a.ns.sha256.net. +dnssec +norec +noall +answer tlakh.xyz DNSKEY +tlakh.xyz. 86400 IN DNSKEY 256 3 13 9Du0N8A9jI+w3gbBcuyaaL9YMM/ooAJvvpewmooIfWajgFPyLvGhr0zR ylhMCoVtbl4XSMD+di1LMiAIhPN9Eg== +tlakh.xyz. 86400 IN DNSKEY 257 3 13 p3cC5drs8jRsY7um9Bb4QyEfecpyY5oXh45X4FskftvDAda46SVT9WVe uqIgofK/XfEW15ugLkWjF5uHCKPWsw== +tlakh.xyz. 86400 IN RRSIG DNSKEY 13 2 86400 20200625000000 20200604000000 22433 tlakh.xyz. CbBp81aMiMLXoAbJuPA0XymHiYJGyWiIKXxAQpoTWGN7sc2P/mF/Ea9V Rg1tYw392vEhM/bi9GjHHnzNQR6+1g== +#+end_example + +[[https://dnsviz.net/d/tlakh.xyz/XuM6QA/dnssec/][dnsviz]] ([[file:algorithm-roll/tlakh.xyz-2020-06-12-08_18_08-UTC.png][local copy]]) confirmed this. With this the algorithm roll-over +was done. diff --git a/algorithm-roll/tlakh.xyz-2020-06-08-16_52_00-UTC.png b/algorithm-roll/tlakh.xyz-2020-06-08-16_52_00-UTC.png new file mode 100644 index 0000000..87ca5e5 Binary files /dev/null and b/algorithm-roll/tlakh.xyz-2020-06-08-16_52_00-UTC.png differ diff --git a/algorithm-roll/tlakh.xyz-2020-06-09-16_55_33-UTC.png b/algorithm-roll/tlakh.xyz-2020-06-09-16_55_33-UTC.png new file mode 100644 index 0000000..724ba3a Binary files /dev/null and b/algorithm-roll/tlakh.xyz-2020-06-09-16_55_33-UTC.png differ diff --git a/algorithm-roll/tlakh.xyz-2020-06-11-06_10_11-UTC.png b/algorithm-roll/tlakh.xyz-2020-06-11-06_10_11-UTC.png new file mode 100644 index 0000000..67fc6f4 Binary files /dev/null and b/algorithm-roll/tlakh.xyz-2020-06-11-06_10_11-UTC.png differ diff --git a/algorithm-roll/tlakh.xyz-2020-06-11-08_04_42-UTC.png b/algorithm-roll/tlakh.xyz-2020-06-11-08_04_42-UTC.png new file mode 100644 index 0000000..a032334 Binary files /dev/null and b/algorithm-roll/tlakh.xyz-2020-06-11-08_04_42-UTC.png differ diff --git a/algorithm-roll/tlakh.xyz-2020-06-12-08_18_08-UTC.png b/algorithm-roll/tlakh.xyz-2020-06-12-08_18_08-UTC.png new file mode 100644 index 0000000..d2f2f07 Binary files /dev/null and b/algorithm-roll/tlakh.xyz-2020-06-12-08_18_08-UTC.png differ diff --git a/fuzzing-ping.org b/fuzzing-ping.org new file mode 100644 index 0000000..b601a41 --- /dev/null +++ b/fuzzing-ping.org @@ -0,0 +1,368 @@ +#+TITLE: Fuzzing ping(8) +#+SUBTITLE: ... and finding a 24 year old bug. +#+DATE: 2022-12-01 +* Prologue +[[https://freebsd.org][FreeBSD]] had a [[https://www.freebsd.org/security/advisories/FreeBSD-SA-22:15.ping.asc][security fluctuation]] in their implementation of =ping(8)= +the other day. As someone who has done a lot of work on [[https://man.openbsd.org/man/ping.8][=ping(8)=]] in +[[https://openbsd.org][OpenBSD]] this tickled my interests. +* What about OpenBSD? +=ping(8)= is ancient: +#+begin_example + * Author - + * Mike Muuss + * U. S. Army Ballistic Research Laboratory + * December, 1983 +#+end_example + +What we know today as =ping(8)= started to become recognizable in 1986, for +example see this [[https://github.com/csrg/csrg/commit/962056110ebf62ed8d4368964c7e82ac7434ea82][csrg commit]]. + +FreeBSD identified a stack overflow in the =pr_pack()= function and I +expected a lot of similarity between the BSDs. This stuff did not +change a lot since the csrg days. + +Step one: Does this effect us? Turns out, it does not. FreeBSD rewrote +=pr_pack()= in [[https://github.com/freebsd/freebsd-src/commit/d9cacf605e2ac0f704e1ce76357cbfbe6cb63d52][2019]], citing alignment problems. + +Now we could join the punters on the Internet and point and laugh. But +that's just rude, uncalled for, and generally boring and +pointless. Technically I'm on vacation and I had resolved to only do +fun things this week. So let's have some fun. + +Step two: FreeBSD had a problem in =pr_pack()= because that function +handles data from the network. The data is untrusted and needs to be +validated. Now is a good time as any to check OpenBSD's implementation +of =pr_pack()=. I wanted to try fuzzing something, anything, with [[https://en.wikipedia.org/wiki/American_fuzzy_lop_(fuzzer)][afl]] +for a few years, but never got around to it. I thought I might as well +do it now, might be fun. + +* Make sure you are not holding it wrong. +I installed =afl++= from packages and glanced at "[[https://aflplus.plus/docs/tutorials/libxml2_tutorial/][Fuzzing libxml2 with +AFL++]]". +Here is what we need: ++ A program to test. Something with a know bug so that we can tell the + fuzzing works. ++ A file as input, that does not trigger the bug. ++ Compile the program with =afl-clang-fast=. ++ Run =afl-fuzz=. + +=test.c:= +#+begin_src C + /* Written by Florian Obser, Public Domain */ + #include + #include + #include + #include + + int + main(int argc, char **argv) + { + FILE *f; + size_t fsize; + uint8_t *buf, len, *dbuf; + + f = fopen(argv[1], "rb"); + fseek(f, 0, SEEK_END); + fsize = ftell(f); + rewind(f); + + buf = malloc(fsize + 1); + if (buf == NULL) + err(1, NULL); + fread(buf, fsize, 1, f); + fclose(f); + + buf[fsize] = 0; + + len = buf[0]; + + dbuf = malloc(len); + if (dbuf == NULL) + err(1, NULL); + memcpy(buf + 1, dbuf, fsize - 1); + warnx("len: %d", len); + return 0; + } +#+end_src +This program has a trivial buffer overflow. It figures out how big a +file is on disk and stores this in =fsize=. Then it goes ahead and +reads the whole file into a buffer. It interprets the first byte as +the length of data (=len=) and allocates a new buffer (=dbuf=) of this +size. It skips the length byte and copies =fsize - 1= bytes into the +new buffer. So it trusts that the amount of data it read from disk is +the same as indicated by the length byte. + +While this might seem silly, this is how real world buffer overflows +look like. + +Here is a file where the length byte and file size agree. Create +folders =in= and =out= and place =test.txt= into =in/test.txt=. Don't +forget the newline. + +=test.txt=: +#+begin_example +ABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB +#+end_example + +Compile =test.c=: +#+begin_src shell + CC=/usr/local/bin/afl-clang-fast make test +#+end_src + +and run =afl-fuzz=: +#+begin_src shell + afl-fuzz -i in/ -o out -- ./test @@ +#+end_src +It more or less immediately finds a crash. The reproducer(s) are in +=out/default/crashes/=. +* Fuzzing =ping(8)= +At this point we are facing a few problems. What does it mean to fuzz +=ping(8)=, where are we getting the sample input from and how do we feed +it to =ping(8)=. + +From a high level point of view =ping(8)= parses arguments, initializes +a bunch of stuff and then enters an infinite loop sending ICMP echo +packets and waiting for a reply. It then parses and prints the reply. + +Parsing the reply is the interesting thing. The reply comes from the +network and is untrusted. This is where things go wrong. The parsing +is handled by =pr_pack()=, so that's what we should fuzz. + +** =in/= for =ping(8)= +Now we need sample data. An ICMP package is binary data +on-wire. Crafting it by hand is annoying. So let's just hack =ping(8)= +to dump the packet to disk. +#+begin_src diff +diff --git sbin/ping/ping.c sbin/ping/ping.c +index a3b3d650eb5..78b571b95b4 100644 +--- sbin/ping/ping.c ++++ sbin/ping/ping.c +@@ -79,6 +79,7 @@ + + #include + #include ++#include + #include + #include + +@@ -95,6 +96,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -217,6 +219,8 @@ const char *pr_addr(struct sockaddr *, socklen_t); + void pr_pack(u_char *, int, struct msghdr *); + __dead void usage(void); + ++void output(char *, u_char *, int); ++ + /* IPv4 specific functions */ + void pr_ipopt(int, u_char *); + int in_cksum(u_short *, int); +@@ -255,7 +259,7 @@ main(int argc, char *argv[]) + int df = 0, tos = 0, bufspace = IP_MAXPACKET, hoplimit = -1, mflag = 0; + u_char *datap, *packet; + u_char ttl = MAXTTL; +- char *e, *target, hbuf[NI_MAXHOST], *source = NULL; ++ char *e, *target, hbuf[NI_MAXHOST], *source = NULL, *output_path = NULL; + char rspace[3 + 4 * NROUTES + 1]; /* record route space */ + const char *errstr; + double fraction, integral, seconds; +@@ -264,11 +268,13 @@ main(int argc, char *argv[]) + u_int rtableid = 0; + extern char *__progname; + ++#if 0 + /* Cannot pledge due to special setsockopt()s below */ + if (unveil("/", "r") == -1) + err(1, "unveil /"); + if (unveil(NULL, NULL) == -1) + err(1, "unveil"); ++#endif + + if (strcmp("ping6", __progname) == 0) { + v6flag = 1; +@@ -297,8 +303,8 @@ main(int argc, char *argv[]) + preload = 0; + datap = &outpack[ECHOLEN + ECHOTMLEN]; + while ((ch = getopt(argc, argv, v6flag ? +- "c:DdEefgHh:I:i:Ll:mNnp:qS:s:T:V:vw:" : +- "DEI:LRS:c:defgHi:l:np:qs:T:t:V:vw:")) != -1) { ++ "c:DdEefgHh:I:i:Ll:mNno:p:qS:s:T:V:vw:" : ++ "DEI:LRS:c:defgHi:l:no:p:qs:T:t:V:vw:")) != -1) { + switch(ch) { + case 'c': + npackets = strtonum(optarg, 0, INT64_MAX, &errstr); +@@ -375,6 +381,9 @@ main(int argc, char *argv[]) + case 'n': + options &= ~F_HOSTNAME; + break; ++ case 'o': ++ output_path = optarg; ++ break; + case 'p': /* fill buffer with user pattern */ + options |= F_PINGFILLED; + fill((char *)datap, optarg); +@@ -768,10 +777,10 @@ main(int argc, char *argv[]) + } + + if (options & F_HOSTNAME) { +- if (pledge("stdio inet dns", NULL) == -1) ++ if (pledge("stdio inet dns wpath cpath", NULL) == -1) + err(1, "pledge"); + } else { +- if (pledge("stdio inet", NULL) == -1) ++ if (pledge("stdio inet wpath cpath", NULL) == -1) + err(1, "pledge"); + } + +@@ -960,8 +969,11 @@ main(int argc, char *argv[]) + } + } + continue; +- } else ++ } else { ++ if (output_path != NULL) ++ output(output_path, packet, cc); + pr_pack(packet, cc, &m); ++ } + + if (npackets && nreceived >= npackets) + break; +@@ -2274,3 +2286,29 @@ usage(void) + } + exit(1); + } ++ ++void ++output(char *path, u_char *pack, int len) ++{ ++ size_t bsz, off; ++ ssize_t nw; ++ int fd; ++ char *fname; ++ ++ bsz = len; ++ if (asprintf(&fname, "%s/ping_%lld_%d.out", path, time(NULL), ++ getpid()) == -1) ++ err(1, NULL); ++ ++ fd = open(fname, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | ++ S_IROTH); ++ free(fname); ++ ++ if (fd == -1) ++ err(1, "open"); ++ ++ for (off = 0; off < bsz; off += nw) ++ if ((nw = write(fd, pack + off, bsz - off)) == 0 || nw == -1) ++ err(1, "write"); ++ close(fd); ++} +#+end_src + +After building and installing our hacked version of =ping(8)= we can +create sample input data for afl thusly: +#+begin_src shell + while :; do + ping -o ./in/ -w 1 -c 1 \ + $(jot -r 0 255 | head -4 | tr '\n' '.' | sed 's/.$//') + done +#+end_src +=jot= creates a stream of random numbers between 0 and 255, we get the +first four, concatenate them with '.' and cut of the trailing +dot. Voilà we have a bunch of random IPv4 addresses. We then send a +single ping and wait for one second. The ICMP reply is written to +=./in/=. + +** Fuzzing =pr_pack()= +At this point I wrote a =main()= function that accepts a file name as +argument, and reads it into a buffer. I then ripped =pr_pack()= out of +=ping(8)= and fed it the file contents. + +Of course compiling fails quite spectacularly at this point. So I +added a bunch of missing functions, defines and global variables. It +gets pretty close now. We don't have the =msghdr= from =recvfrom(2)= so +we need to =#if 0= some code. We also need to get rid of the +validation of the data packet using =SipHash= because the whole point +is that the data does not validate and =SipHash= would short circuit. + +Oh yeah, and the thing is legacy IP only at this point. + +So [[file:fuzzing-ping/afl_ping.c][here (=afl_ping.c=)]] it is, it is quite terrible. It would probably make more sense +to copy all of =ping(8)= and slap on a new =main()= function. Maybe. + +Anyway, at this point I was 30 minutes in, from reading about afl for +the first time until firing up =afl-fuzz= on my hacked +=pr_pack()=. Not too bad. It was now time for dinner and I left the +thing running. + +** The promised bug +I came back after dinner and afl found zero crashes. That's +disappointing. Or good. Depending on how you look at it. But it found +hangs. Running =afl_ping= on one of the reproducers, it printed +=unknown option 20= forever. + +The problem is in this part of the code: +#+begin_src C + for (; hlen > (int)sizeof(struct ip); --hlen, ++cp) { + /* [...] */ + switch (*cp) { + /* [...] */ + default: + printf("\nunknown option %x", *cp); + hlen = hlen - (cp[IPOPT_OLEN] - 1); + cp = cp + (cp[IPOPT_OLEN] - 1); + break; + } + } +#+end_src +=cp= is untrusted data and if =cp[IPOPT_OLEN]= is zero we would +increase =hlen= by one and the for loop would subtract one, same for +=cp=. We never make any progress and spin forever. + +The diff is fairly simple: +#+begin_src diff +diff --git ping.c ping.c +index fb31365ad31..6019c87d8db 100644 +--- ping.c ++++ ping.c +@@ -1525,8 +1525,11 @@ pr_ipopt(int hlen, u_char *buf) + break; + default: + printf("\nunknown option %x", *cp); +- hlen = hlen - (cp[IPOPT_OLEN] - 1); +- cp = cp + (cp[IPOPT_OLEN] - 1); ++ if (cp[IPOPT_OLEN] > 0 && (cp[IPOPT_OLEN] - 1) <= hlen) { ++ hlen = hlen - (cp[IPOPT_OLEN] - 1); ++ cp = cp + (cp[IPOPT_OLEN] - 1); ++ } else ++ hlen = 0; + break; + } + } +#+end_src + +I foolishly tweaked the diff after collecting OKs and of course the +tweak was wrong. Note to self: Never do this. So it's spread out over +two commits: [[https://cvsweb.openbsd.org/src/sbin/ping/ping.c#rev1.247][ping.c, Revision 1.247]] and [[https://cvsweb.openbsd.org/src/sbin/ping/ping.c#rev1.248][ping.c, Revision 1.248]]. + +This bug was introduced April 3rd, 1998 in [[https://cvsweb.openbsd.org/src/sbin/ping/ping.c#rev1.30][revision 1.30]], over 24 +years ago. + +* Epilogue +Afl uses files to feed data to programs to get them to crash or +otherwise misbehave. I had wondered for a few years how I could use +afl with things that talk to the network. Because that's what I mostly +work on. In hindsight it's quite obvious. You identify the main +parsing function, wrap it in a new =main()= function and Robert is +your father's nearest male relative. + +The two main takeaways from this are: One, if someone messes up +somewhere, go look if you messed up in the same or similar way +somewhere else. Two, afl is pretty easy to use, even for network +programs. 30 minutes from reading about afl for the first time to +finding a bug in a real world program is pretty neat. diff --git a/fuzzing-ping/afl_ping.c b/fuzzing-ping/afl_ping.c new file mode 100644 index 0000000..90a26e2 --- /dev/null +++ b/fuzzing-ping/afl_ping.c @@ -0,0 +1,892 @@ +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Mike Muuss. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Using the InterNet Control Message Protocol (ICMP) "ECHO" facility, + * measure round-trip-delays and packet loss across network paths. + * + * Author - + * Mike Muuss + * U. S. Army Ballistic Research Laboratory + * December, 1983 + * + * Status - + * Public Domain. Distribution Unlimited. + * Bugs - + * More statistics could always be gathered. + * This program has to run SUID to ROOT to access the ICMP socket. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define F_FLOOD 0x0001 +#define F_INTERVAL 0x0002 +#define F_HOSTNAME 0x0004 +#define F_PINGFILLED 0x0008 +#define F_QUIET 0x0010 +#define F_RROUTE 0x0020 +#define F_SO_DEBUG 0x0040 +#define F_SHOWCHAR 0x0080 +#define F_VERBOSE 0x0100 +/* 0x0200 */ +#define F_HDRINCL 0x0400 +#define F_TTL 0x0800 +#define F_TOS 0x1000 +#define F_AUD_RECV 0x2000 +#define F_AUD_MISS 0x4000 + + +#define ECHOLEN 8 /* icmp echo header len excluding time */ +#define ECHOTMLEN sizeof(struct payload) +#define DEFDATALEN (64 - ECHOLEN) /* default data length */ +#define MAXIPLEN 60 +#define MAXICMPLEN 76 +#define MAXPAYLOAD (IP_MAXPACKET - MAXIPLEN - ECHOLEN) +#define IP6LEN 40 +#define EXTRA 256 /* for AH and various other headers. weird. */ +#define MAXPAYLOAD6 IPV6_MAXPACKET - IP6LEN - ECHOLEN +#define MAXWAIT_DEFAULT 10 /* secs to wait for response */ +#define NROUTES 9 /* number of record route slots */ + +struct tv64 { + u_int64_t tv64_sec; + u_int64_t tv64_nsec; +}; + +struct payload { + struct tv64 tv64; + u_int8_t mac[SIPHASH_DIGEST_LENGTH]; +}; + +const char *pr_addr(struct sockaddr *, socklen_t); +void pr_pack(u_char *, int, struct msghdr *); +/* IPv4 specific functions */ +void pr_ipopt(int, u_char *); +int in_cksum(u_short *, int); +void pr_icmph(struct icmp *); +void pr_retip(struct ip *); +void pr_iph(struct ip *); +int map_tos(char *, int *); + +int v6flag = 0; +int options = F_VERBOSE; + +char BSPACE = '\b'; /* characters written for flood */ +char DOT = '.'; +int datalen = DEFDATALEN; + +int64_t npackets; /* max packets to transmit */ +int64_t nreceived; /* # of packets we got back */ +int64_t nrepeats; /* number of duplicates */ +int64_t ntransmitted; /* sequence # for outbound packets = #sent */ +int64_t nmissedmax = 1; /* max value of ntransmitted - nreceived - 1 */ +struct timeval interval = {1, 0}; /* interval between packets */ + +/* timing */ +int timing; /* flag to do timing */ +int timinginfo; +unsigned int maxwait = MAXWAIT_DEFAULT; /* max seconds to wait for response */ +double tmin = 999999999.0; /* minimum round trip time */ +double tmax; /* maximum round trip time */ +double tsum; /* sum of all times, for doing average */ +double tsumsq; /* sum of all times squared, for std. dev. */ + +struct tv64 tv64_offset; + +/* + * MAX_DUP_CHK is the number of bits in received table, i.e. the maximum + * number of received sequence numbers we can keep track of. Change 128 + * to 8192 for complete accuracy... + */ +#define MAX_DUP_CHK (8 * 8192) +int mx_dup_ck = MAX_DUP_CHK; +char rcvd_tbl[MAX_DUP_CHK / 8]; + +#define A(bit) rcvd_tbl[(bit)>>3] /* identify byte in array */ +#define B(bit) (1 << ((bit) & 0x07)) /* identify bit in byte */ +#define SET(bit) (A(bit) |= B(bit)) +#define CLR(bit) (A(bit) &= (~B(bit))) +#define TST(bit) (A(bit) & B(bit)) + + +int +main(int argc, char **argv) +{ + FILE *f; + size_t fsize; + uint8_t *buf; + + f = fopen(argv[1], "rb"); + fseek(f, 0, SEEK_END); + fsize = ftell(f); + rewind(f); + + buf = malloc(fsize + 1); + if (buf == NULL) + err(1, NULL); + fread(buf, fsize, 1, f); + fclose(f); + + pr_pack(buf, fsize, NULL); +} + +void +pr_pack(u_char *buf, int cc, struct msghdr *mhdr) +{ + struct ip *ip = NULL; + struct icmp *icp = NULL; + struct icmp6_hdr *icp6 = NULL; + struct timespec ts, tp; + struct payload payload; + struct sockaddr *from; + socklen_t fromlen; + double triptime = 0; + int i, dupflag; + int hlen = -1, hoplim = -1, echo_reply = 0; + u_int16_t seq; + u_char *cp, *dp; + char* pkttime; + + if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) + err(1, "clock_gettime(CLOCK_MONOTONIC)"); + + if (v6flag) { +#if 0 + if (!mhdr || !mhdr->msg_name || + mhdr->msg_namelen != sizeof(struct sockaddr_in6) || + ((struct sockaddr *)mhdr->msg_name)->sa_family != + AF_INET6) { + if (options & F_VERBOSE) + warnx("invalid peername"); + return; + } + from = (struct sockaddr *)mhdr->msg_name; + fromlen = mhdr->msg_namelen; + + if (cc < sizeof(struct icmp6_hdr)) { + if (options & F_VERBOSE) + warnx("packet too short (%d bytes) from %s", cc, + pr_addr(from, fromlen)); + return; + } + icp6 = (struct icmp6_hdr *)buf; + + if ((hoplim = get_hoplim(mhdr)) == -1) { + warnx("failed to get receiving hop limit"); + return; + } + + if (icp6->icmp6_type == ICMP6_ECHO_REPLY) { + if (icp6->icmp6_id != ident) + return; /* 'Twas not our ECHO */ + seq = icp6->icmp6_seq; + echo_reply = 1; + pkttime = (char *)(icp6 + 1); + } +#endif + } else { +#if 0 + if (!mhdr || !mhdr->msg_name || + mhdr->msg_namelen != sizeof(struct sockaddr_in) || + ((struct sockaddr *)mhdr->msg_name)->sa_family != AF_INET) { + if (options & F_VERBOSE) + warnx("invalid peername"); + return; + } + from = (struct sockaddr *)mhdr->msg_name; + fromlen = mhdr->msg_namelen; +#endif + /* Check the IP header */ + ip = (struct ip *)buf; + hlen = ip->ip_hl << 2; + if (cc < hlen + ICMP_MINLEN) { + if (options & F_VERBOSE) + warnx("packet too short (%d bytes) from %s", cc, + pr_addr(from, fromlen)); + return; + } + + /* Now the ICMP part */ + cc -= hlen; + icp = (struct icmp *)(buf + hlen); + if (icp->icmp_type == ICMP_ECHOREPLY) { +#if 0 + if (icp->icmp_id != ident) + return; /* 'Twas not our ECHO */ +#endif + seq = icp->icmp_seq; + echo_reply = 1; + pkttime = (char *)icp->icmp_data; + } + } + + if (echo_reply) { + ++nreceived; + if (cc >= ECHOLEN + ECHOTMLEN) { + SIPHASH_CTX ctx; + struct tv64 *tv64; + u_int8_t mac[SIPHASH_DIGEST_LENGTH]; + + memcpy(&payload, pkttime, sizeof(payload)); + tv64 = &payload.tv64; + +#if 0 + SipHash24_Init(&ctx, &mac_key); + SipHash24_Update(&ctx, tv64, sizeof(*tv64)); + SipHash24_Update(&ctx, &ident, sizeof(ident)); + SipHash24_Update(&ctx, &seq, sizeof(seq)); + SipHash24_Final(mac, &ctx); + + if (timingsafe_memcmp(mac, &payload.mac, + sizeof(mac)) != 0) { + printf("signature mismatch from %s: " + "icmp_seq=%u\n", pr_addr(from, fromlen), + ntohs(seq)); + --nreceived; + return; + } +#endif + timinginfo=1; + + tp.tv_sec = betoh64(tv64->tv64_sec) - + tv64_offset.tv64_sec; + tp.tv_nsec = betoh64(tv64->tv64_nsec) - + tv64_offset.tv64_nsec; + + timespecsub(&ts, &tp, &ts); + triptime = ((double)ts.tv_sec) * 1000.0 + + ((double)ts.tv_nsec) / 1000000.0; + tsum += triptime; + tsumsq += triptime * triptime; + if (triptime < tmin) + tmin = triptime; + if (triptime > tmax) + tmax = triptime; + } + + if (TST(ntohs(seq) % mx_dup_ck)) { + ++nrepeats; + --nreceived; + dupflag = 1; + } else { + SET(ntohs(seq) % mx_dup_ck); + dupflag = 0; + } + + if (options & F_QUIET) + return; + + if (options & F_FLOOD) + write(STDOUT_FILENO, &BSPACE, 1); + + else if (options & F_SHOWCHAR) { + if (dupflag) + putchar('D'); + else if (cc - ECHOLEN < datalen) + putchar('T'); + else + putchar('!'); + } else { + printf("%d bytes from %s: icmp_seq=%u", cc, + pr_addr(from, fromlen), ntohs(seq)); + if (v6flag) + printf(" hlim=%d", hoplim); + else + printf(" ttl=%d", ip->ip_ttl); + if (cc >= ECHOLEN + ECHOTMLEN) + printf(" time=%.3f ms", triptime); + if (dupflag) + printf(" (DUP!)"); + /* check the data */ + if (cc - ECHOLEN < datalen) + printf(" (TRUNC!)"); + if (v6flag) + cp = buf + ECHOLEN + ECHOTMLEN; + else + cp = (u_char *)&icp->icmp_data[ECHOTMLEN]; +#if 0 + dp = &outpack[ECHOLEN + ECHOTMLEN]; + for (i = ECHOLEN + ECHOTMLEN; + i < cc && i < datalen; + ++i, ++cp, ++dp) { + if (*cp != *dp) { + printf("\nwrong data byte #%d " + "should be 0x%x but was 0x%x", + i - ECHOLEN, *dp, *cp); + if (v6flag) + cp = buf + ECHOLEN; + else + cp = (u_char *) + &icp->icmp_data[0]; + for (i = ECHOLEN; i < cc && i < datalen; + ++i, ++cp) { + if ((i % 32) == 8) + printf("\n\t"); + printf("%x ", *cp); + } + break; + } + } +#endif + } + } else { + /* We've got something other than an ECHOREPLY */ + if (!(options & F_VERBOSE)) + return; + printf("%d bytes from %s: ", cc, pr_addr(from, fromlen)); +#if 0 + if (v6flag) + pr_icmph6(icp6, buf + cc); + else +#endif + pr_icmph(icp); + } + + /* Display any IP options */ + if (!v6flag && hlen > sizeof(struct ip)) + pr_ipopt(hlen, buf); + + if (!(options & F_FLOOD)) { + if (!(options & F_SHOWCHAR)) { + putchar('\n'); +#if 0 + if (v6flag && (options & F_VERBOSE)) + pr_exthdrs(mhdr); +#endif + } + fflush(stdout); + if (options & F_AUD_RECV) + fputc('\a', stderr); + } +} + +void +pr_ipopt(int hlen, u_char *buf) +{ + static int old_rrlen; + static char old_rr[MAX_IPOPTLEN]; + struct sockaddr_in s_in; + in_addr_t l; + u_int i, j; + u_char *cp; + + cp = buf + sizeof(struct ip); + + s_in.sin_len = sizeof(s_in); + s_in.sin_family = AF_INET; + + for (; hlen > (int)sizeof(struct ip); --hlen, ++cp) { + switch (*cp) { + case IPOPT_EOL: + hlen = 0; + break; + case IPOPT_LSRR: + printf("\nLSRR: "); + hlen -= 2; + j = *++cp; + ++cp; + i = 0; + if (j > IPOPT_MINOFF) { + for (;;) { + l = *++cp; + l = (l<<8) + *++cp; + l = (l<<8) + *++cp; + l = (l<<8) + *++cp; + if (l == 0) + printf("\t0.0.0.0"); + else { + s_in.sin_addr.s_addr = ntohl(l); + printf("\t%s", + pr_addr((struct sockaddr*) + &s_in, sizeof(s_in))); + } + hlen -= 4; + j -= 4; + i += 4; + if (j <= IPOPT_MINOFF) + break; + if (i >= MAX_IPOPTLEN) { + printf("\t(truncated route)"); + break; + } + putchar('\n'); + } + } + break; + case IPOPT_RR: + j = *++cp; /* get length */ + i = *++cp; /* and pointer */ + hlen -= 2; + if (i > j) + i = j; + i -= IPOPT_MINOFF; + if (i <= 0) + continue; + if (i == old_rrlen && + cp == buf + sizeof(struct ip) + 2 && + !memcmp(cp, old_rr, i) && + !(options & F_FLOOD)) { + printf("\t(same route)"); + i = (i + 3) & ~0x3; + hlen -= i; + cp += i; + break; + } + if (i < MAX_IPOPTLEN) { + old_rrlen = i; + memcpy(old_rr, cp, i); + } else + old_rrlen = 0; + + printf("\nRR: "); + j = 0; + for (;;) { + l = *++cp; + l = (l<<8) + *++cp; + l = (l<<8) + *++cp; + l = (l<<8) + *++cp; + if (l == 0) + printf("\t0.0.0.0"); + else { + s_in.sin_addr.s_addr = ntohl(l); + printf("\t%s", + pr_addr((struct sockaddr*)&s_in, + sizeof(s_in))); + } + hlen -= 4; + i -= 4; + j += 4; + if (i <= 0) + break; + if (j >= MAX_IPOPTLEN) { + printf("\t(truncated route)"); + break; + } + putchar('\n'); + } + break; + case IPOPT_NOP: + printf("\nNOP"); + break; + default: + printf("\nunknown option %x", *cp); + if (cp[IPOPT_OLEN] > 0 && (cp[IPOPT_OLEN] - 1) <= hlen) { + hlen = hlen - (cp[IPOPT_OLEN] - 1); + cp = cp + (cp[IPOPT_OLEN] - 1); + } else + hlen = 0; + break; + } + } +} + +/* + * pr_addr -- + * Return address in numeric form or a host name + */ +const char * +pr_addr(struct sockaddr *addr, socklen_t addrlen) +{ + static char buf[NI_MAXHOST]; + int flag = 0; + + return "not implemented"; + + if (!(options & F_HOSTNAME)) + flag |= NI_NUMERICHOST; + + if (getnameinfo(addr, addrlen, buf, sizeof(buf), NULL, 0, flag) == 0) + return (buf); + else + return "?"; +} + +/* + * pr_icmph -- + * Print a descriptive string about an ICMP header. + */ +void +pr_icmph(struct icmp *icp) +{ + switch(icp->icmp_type) { + case ICMP_ECHOREPLY: + printf("Echo Reply\n"); + /* XXX ID + Seq + Data */ + break; + case ICMP_UNREACH: + switch(icp->icmp_code) { + case ICMP_UNREACH_NET: + printf("Destination Net Unreachable\n"); + break; + case ICMP_UNREACH_HOST: + printf("Destination Host Unreachable\n"); + break; + case ICMP_UNREACH_PROTOCOL: + printf("Destination Protocol Unreachable\n"); + break; + case ICMP_UNREACH_PORT: + printf("Destination Port Unreachable\n"); + break; + case ICMP_UNREACH_NEEDFRAG: + if (icp->icmp_nextmtu != 0) + printf("frag needed and DF set (MTU %d)\n", + ntohs(icp->icmp_nextmtu)); + else + printf("frag needed and DF set\n"); + break; + case ICMP_UNREACH_SRCFAIL: + printf("Source Route Failed\n"); + break; + case ICMP_UNREACH_NET_UNKNOWN: + printf("Network Unknown\n"); + break; + case ICMP_UNREACH_HOST_UNKNOWN: + printf("Host Unknown\n"); + break; + case ICMP_UNREACH_ISOLATED: + printf("Source Isolated\n"); + break; + case ICMP_UNREACH_NET_PROHIB: + printf("Dest. Net Administratively Prohibited\n"); + break; + case ICMP_UNREACH_HOST_PROHIB: + printf("Dest. Host Administratively Prohibited\n"); + break; + case ICMP_UNREACH_TOSNET: + printf("Destination Net Unreachable for TOS\n"); + break; + case ICMP_UNREACH_TOSHOST: + printf("Destination Host Unreachable for TOS\n"); + break; + case ICMP_UNREACH_FILTER_PROHIB: + printf("Route administratively prohibited\n"); + break; + case ICMP_UNREACH_HOST_PRECEDENCE: + printf("Host Precedence Violation\n"); + break; + case ICMP_UNREACH_PRECEDENCE_CUTOFF: + printf("Precedence Cutoff\n"); + break; + default: + printf("Dest Unreachable, Unknown Code: %d\n", + icp->icmp_code); + break; + } + /* Print returned IP header information */ + pr_retip((struct ip *)icp->icmp_data); + break; + case ICMP_SOURCEQUENCH: + printf("Source Quench\n"); + pr_retip((struct ip *)icp->icmp_data); + break; + case ICMP_REDIRECT: + switch(icp->icmp_code) { + case ICMP_REDIRECT_NET: + printf("Redirect Network"); + break; + case ICMP_REDIRECT_HOST: + printf("Redirect Host"); + break; + case ICMP_REDIRECT_TOSNET: + printf("Redirect Type of Service and Network"); + break; + case ICMP_REDIRECT_TOSHOST: + printf("Redirect Type of Service and Host"); + break; + default: + printf("Redirect, Unknown Code: %d", icp->icmp_code); + break; + } + printf("(New addr: %s)\n", + inet_ntoa(icp->icmp_gwaddr)); + pr_retip((struct ip *)icp->icmp_data); + break; + case ICMP_ECHO: + printf("Echo Request\n"); + /* XXX ID + Seq + Data */ + break; + case ICMP_ROUTERADVERT: + /* RFC1256 */ + printf("Router Discovery Advertisement\n"); + printf("(%d entries, lifetime %d seconds)\n", + icp->icmp_num_addrs, ntohs(icp->icmp_lifetime)); + break; + case ICMP_ROUTERSOLICIT: + /* RFC1256 */ + printf("Router Discovery Solicitation\n"); + break; + case ICMP_TIMXCEED: + switch(icp->icmp_code) { + case ICMP_TIMXCEED_INTRANS: + printf("Time to live exceeded\n"); + break; + case ICMP_TIMXCEED_REASS: + printf("Frag reassembly time exceeded\n"); + break; + default: + printf("Time exceeded, Unknown Code: %d\n", + icp->icmp_code); + break; + } + pr_retip((struct ip *)icp->icmp_data); + break; + case ICMP_PARAMPROB: + switch(icp->icmp_code) { + case ICMP_PARAMPROB_OPTABSENT: + printf("Parameter problem, required option " + "absent: pointer = 0x%02x\n", + ntohs(icp->icmp_hun.ih_pptr)); + break; + default: + printf("Parameter problem: pointer = 0x%02x\n", + ntohs(icp->icmp_hun.ih_pptr)); + break; + } + pr_retip((struct ip *)icp->icmp_data); + break; + case ICMP_TSTAMP: + printf("Timestamp\n"); + /* XXX ID + Seq + 3 timestamps */ + break; + case ICMP_TSTAMPREPLY: + printf("Timestamp Reply\n"); + /* XXX ID + Seq + 3 timestamps */ + break; + case ICMP_IREQ: + printf("Information Request\n"); + /* XXX ID + Seq */ + break; + case ICMP_IREQREPLY: + printf("Information Reply\n"); + /* XXX ID + Seq */ + break; + case ICMP_MASKREQ: + printf("Address Mask Request\n"); + break; + case ICMP_MASKREPLY: + printf("Address Mask Reply (Mask 0x%08x)\n", + ntohl(icp->icmp_mask)); + break; + default: + printf("Unknown ICMP type: %d\n", icp->icmp_type); + } +} + +/* + * pr_iph -- + * Print an IP header with options. + */ +void +pr_iph(struct ip *ip) +{ + int hlen; + u_char *cp; + + hlen = ip->ip_hl << 2; + cp = (u_char *)ip + 20; /* point to options */ + + printf("Vr HL TOS Len ID Flg off TTL Pro cks Src Dst Data\n"); + printf(" %1x %1x %02x %04x %04x", + ip->ip_v, ip->ip_hl, ip->ip_tos, ip->ip_len, ip->ip_id); + printf(" %1x %04x", ((ip->ip_off) & 0xe000) >> 13, + (ip->ip_off) & 0x1fff); + printf(" %02x %02x %04x", ip->ip_ttl, ip->ip_p, ip->ip_sum); + printf(" %s ", inet_ntoa(*(struct in_addr *)&ip->ip_src.s_addr)); + printf(" %s ", inet_ntoa(*(struct in_addr *)&ip->ip_dst.s_addr)); + /* dump and option bytes */ + while (hlen-- > 20) { + printf("%02x", *cp++); + } + putchar('\n'); +} + +/* + * pr_retip -- + * Dump some info on a returned (via ICMP) IP packet. + */ +void +pr_retip(struct ip *ip) +{ + int hlen; + u_char *cp; + + pr_iph(ip); + hlen = ip->ip_hl << 2; + cp = (u_char *)ip + hlen; + + if (ip->ip_p == 6) + printf("TCP: from port %u, to port %u (decimal)\n", + (*cp * 256 + *(cp + 1)), (*(cp + 2) * 256 + *(cp + 3))); + else if (ip->ip_p == 17) + printf("UDP: from port %u, to port %u (decimal)\n", + (*cp * 256 + *(cp + 1)), (*(cp + 2) * 256 + *(cp + 3))); +} + +#ifndef SMALL +int +map_tos(char *key, int *val) +{ + /* DiffServ Codepoints and other TOS mappings */ + const struct toskeywords { + const char *keyword; + int val; + } *t, toskeywords[] = { + { "af11", IPTOS_DSCP_AF11 }, + { "af12", IPTOS_DSCP_AF12 }, + { "af13", IPTOS_DSCP_AF13 }, + { "af21", IPTOS_DSCP_AF21 }, + { "af22", IPTOS_DSCP_AF22 }, + { "af23", IPTOS_DSCP_AF23 }, + { "af31", IPTOS_DSCP_AF31 }, + { "af32", IPTOS_DSCP_AF32 }, + { "af33", IPTOS_DSCP_AF33 }, + { "af41", IPTOS_DSCP_AF41 }, + { "af42", IPTOS_DSCP_AF42 }, + { "af43", IPTOS_DSCP_AF43 }, + { "critical", IPTOS_PREC_CRITIC_ECP }, + { "cs0", IPTOS_DSCP_CS0 }, + { "cs1", IPTOS_DSCP_CS1 }, + { "cs2", IPTOS_DSCP_CS2 }, + { "cs3", IPTOS_DSCP_CS3 }, + { "cs4", IPTOS_DSCP_CS4 }, + { "cs5", IPTOS_DSCP_CS5 }, + { "cs6", IPTOS_DSCP_CS6 }, + { "cs7", IPTOS_DSCP_CS7 }, + { "ef", IPTOS_DSCP_EF }, + { "inetcontrol", IPTOS_PREC_INTERNETCONTROL }, + { "lowdelay", IPTOS_LOWDELAY }, + { "netcontrol", IPTOS_PREC_NETCONTROL }, + { "reliability", IPTOS_RELIABILITY }, + { "throughput", IPTOS_THROUGHPUT }, + { NULL, -1 }, + }; + + for (t = toskeywords; t->keyword != NULL; t++) { + if (strcmp(key, t->keyword) == 0) { + *val = t->val; + return (1); + } + } + + return (0); +} +#endif /* SMALL */ + +#if 0 +void +pr_exthdrs(struct msghdr *mhdr) +{ + struct cmsghdr *cm; + + for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm; + cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) { + if (cm->cmsg_level != IPPROTO_IPV6) + continue; + + switch (cm->cmsg_type) { + case IPV6_HOPOPTS: + printf(" HbH Options: "); + pr_ip6opt(CMSG_DATA(cm)); + break; + case IPV6_DSTOPTS: + case IPV6_RTHDRDSTOPTS: + printf(" Dst Options: "); + pr_ip6opt(CMSG_DATA(cm)); + break; + case IPV6_RTHDR: + printf(" Routing: "); + pr_rthdr(CMSG_DATA(cm)); + break; + } + } +} +#endif diff --git a/htmlize.css b/htmlize.css new file mode 100644 index 0000000..1061937 --- /dev/null +++ b/htmlize.css @@ -0,0 +1,2455 @@ +/* Generated from (org-html-htmlize-generate-css) with minimum +packages loaded and default light theme */ + +body { + color: #000000; + background-color: #ffffff; +} +.org-alert-high { + /* alert-high-face */ + color: #ff8c00; + font-weight: bold; +} +.org-alert-low { + /* alert-low-face */ + color: #00008b; +} +.org-alert-moderate { + /* alert-moderate-face */ + color: #ffd700; + font-weight: bold; +} +.org-alert-normal { +} +.org-alert-saved-fringe { + /* alert-saved-fringe-face */ + background-color: #f2f2f2; +} +.org-alert-trivial { + /* alert-trivial-face */ + color: Dark Purple; +} +.org-alert-urgent { + /* alert-urgent-face */ + color: #ff0000; + font-weight: bold; +} +.org-anzu-match-1 { + /* anzu-match-1 */ + color: #000000; + background-color: #7fffd4; +} +.org-anzu-match-2 { + /* anzu-match-2 */ + color: #000000; + background-color: #00ff7f; +} +.org-anzu-match-3 { + /* anzu-match-3 */ + color: #000000; + background-color: #ffff00; +} +.org-anzu-mode-line { + /* anzu-mode-line */ + color: #008b00; + font-weight: bold; +} +.org-anzu-mode-line-no-match { + /* anzu-mode-line-no-match */ + color: #008b00; + font-weight: bold; +} +.org-anzu-replace-highlight { + /* anzu-replace-highlight */ + color: #b0e2ff; + background-color: #cd00cd; +} +.org-anzu-replace-to { + /* anzu-replace-to */ + color: #ff0000; +} +.org-bbdb-field-name { + /* bbdb-field-name */ + color: #a0522d; +} +.org-bbdb-name { + /* bbdb-name */ + color: #0000ff; +} +.org-bbdb-organization { + /* bbdb-organization */ + color: #b22222; +} +.org-beacon-fallback-background { + /* beacon-fallback-background */ + background-color: #000000; +} +.org-biblio-detail-header { +} +.org-biblio-results-header { + /* biblio-results-header-face */ + color: #483d8b; + font-size: 150%; + font-weight: bold; +} +.org-bold { + /* bold */ + font-weight: bold; +} +.org-bold-italic { + /* bold-italic */ + font-weight: bold; + font-style: italic; +} +.org-bookmark-menu-bookmark { + /* bookmark-menu-bookmark */ + font-weight: bold; +} +.org-bookmark-menu-heading { + /* bookmark-menu-heading */ + color: #228b22; +} +.org-border { +} +.org-buffer-menu-buffer { + /* buffer-menu-buffer */ + font-weight: bold; +} +.org-builtin { + /* font-lock-builtin-face */ + color: #483d8b; +} +.org-button { + /* button */ + color: #3a5fcd; + text-decoration: underline; +} +.org-c-annotation { + /* c-annotation-face */ + color: #008b8b; +} +.org-cal-china-x-general-holiday { + /* cal-china-x-general-holiday-face */ + background-color: #228b22; +} +.org-cal-china-x-important-holiday { + /* cal-china-x-important-holiday-face */ + background-color: #8b0000; +} +.org-calendar-iso-week { + /* calendar-iso-week-face */ + color: #ffc0cb; + font-weight: bold; +} +.org-calendar-iso-week-header { + /* calendar-iso-week-header-face */ + color: #00ffff; +} +.org-calendar-month-header { + /* calendar-month-header */ + color: #0000ff; +} +.org-calendar-today { + /* calendar-today */ + text-decoration: underline; +} +.org-calendar-weekday-header { + /* calendar-weekday-header */ + color: #008b8b; +} +.org-calendar-weekend-header { + /* calendar-weekend-header */ + color: #b22222; +} +.org-comint-highlight-input { + /* comint-highlight-input */ + font-weight: bold; +} +.org-comint-highlight-prompt { + /* comint-highlight-prompt */ + color: #0000cd; +} +.org-comment { + /* font-lock-comment-face */ + color: #b22222; +} +.org-comment-delimiter { + /* font-lock-comment-delimiter-face */ + color: #b22222; +} +.org-compilation-column-number { + /* compilation-column-number */ + color: #8b2252; +} +.org-compilation-error { + /* compilation-error */ + color: #ff0000; + font-weight: bold; +} +.org-compilation-info { + /* compilation-info */ + color: #228b22; + font-weight: bold; +} +.org-compilation-line-number { + /* compilation-line-number */ + color: #a020f0; +} +.org-compilation-mode-line-exit { + /* compilation-mode-line-exit */ + color: #228b22; + font-weight: bold; +} +.org-compilation-mode-line-fail { + /* compilation-mode-line-fail */ + color: #ff0000; + font-weight: bold; +} +.org-compilation-mode-line-run { + /* compilation-mode-line-run */ + color: #ff8c00; + font-weight: bold; +} +.org-compilation-warning { + /* compilation-warning */ + color: #ff8c00; + font-weight: bold; +} +.org-completions-annotations { + /* completions-annotations */ + font-style: italic; +} +.org-completions-common-part { +} +.org-completions-first-difference { + /* completions-first-difference */ + font-weight: bold; +} +.org-constant { + /* font-lock-constant-face */ + color: #008b8b; +} +.org-cursor { + /* cursor */ + background-color: #eead0e; +} +.org-custom-button { + /* custom-button */ + color: #000000; + background-color: #d3d3d3; +} +.org-custom-button-mouse { + /* custom-button-mouse */ + color: #000000; + background-color: #e5e5e5; +} +.org-custom-button-pressed { + /* custom-button-pressed */ + color: #000000; + background-color: #d3d3d3; +} +.org-custom-button-pressed-unraised { + /* custom-button-pressed-unraised */ + color: #8b008b; + text-decoration: underline; +} +.org-custom-button-unraised { + /* custom-button-unraised */ + text-decoration: underline; +} +.org-custom-changed { + /* custom-changed */ + color: #ffffff; + background-color: #0000ff; +} +.org-custom-comment { + /* custom-comment */ + background-color: #d9d9d9; +} +.org-custom-comment-tag { + /* custom-comment-tag */ + color: #00008b; +} +.org-custom-documentation { +} +.org-custom-face-tag { + /* custom-face-tag */ + color: #0000ff; + font-weight: bold; +} +.org-custom-group-subtitle { + /* custom-group-subtitle */ + font-weight: bold; +} +.org-custom-group-tag { + /* custom-group-tag */ + color: #0000ff; + font-size: 120%; + font-weight: bold; +} +.org-custom-group-tag-1 { + /* custom-group-tag-1 */ + color: #ff0000; + font-size: 120%; + font-weight: bold; +} +.org-custom-invalid { + /* custom-invalid */ + color: #ffff00; + background-color: #ff0000; +} +.org-custom-link { + /* custom-link */ + color: #3a5fcd; + text-decoration: underline; +} +.org-custom-modified { + /* custom-modified */ + color: #ffffff; + background-color: #0000ff; +} +.org-custom-rogue { + /* custom-rogue */ + color: #ffc0cb; + background-color: #000000; +} +.org-custom-saved { + /* custom-saved */ + text-decoration: underline; +} +.org-custom-set { + /* custom-set */ + color: #0000ff; + background-color: #ffffff; +} +.org-custom-state { + /* custom-state */ + color: #006400; +} +.org-custom-themed { + /* custom-themed */ + color: #ffffff; + background-color: #0000ff; +} +.org-custom-variable-button { + /* custom-variable-button */ + font-weight: bold; + text-decoration: underline; +} +.org-custom-variable-tag { + /* custom-variable-tag */ + color: #0000ff; + font-weight: bold; +} +.org-custom-visibility { + /* custom-visibility */ + color: #3a5fcd; + font-size: 80%; + text-decoration: underline; +} +.org-diary { + /* diary */ + color: #ff0000; +} +.org-diary-anniversary { + /* diary-anniversary */ + color: #a020f0; +} +.org-diary-button { +} +.org-diary-time { + /* diary-time */ + color: #a0522d; +} +.org-dired-async-failures { + /* dired-async-failures */ + color: #ff0000; +} +.org-dired-async-message { + /* dired-async-message */ + color: #ffff00; +} +.org-dired-async-mode-message { + /* dired-async-mode-message */ + color: #ffd700; +} +.org-dired-directory { + /* dired-directory */ + color: #0000ff; +} +.org-dired-flagged { + /* dired-flagged */ + color: #ff0000; + font-weight: bold; +} +.org-dired-header { + /* dired-header */ + color: #228b22; +} +.org-dired-ignored { + /* dired-ignored */ + color: #7f7f7f; +} +.org-dired-mark { + /* dired-mark */ + color: #008b8b; +} +.org-dired-marked { + /* dired-marked */ + color: #ff8c00; + font-weight: bold; +} +.org-dired-perm-write { + /* dired-perm-write */ + color: #b22222; +} +.org-dired-symlink { + /* dired-symlink */ + color: #a020f0; +} +.org-dired-warning { + /* dired-warning */ + color: #ff0000; + font-weight: bold; +} +.org-doc { + /* font-lock-doc-face */ + color: #8b2252; +} +.org-eldoc-highlight-function-argument { + /* eldoc-highlight-function-argument */ + font-weight: bold; +} +.org-epa-field-body { + /* epa-field-body */ + font-style: italic; +} +.org-epa-field-name { + /* epa-field-name */ + font-weight: bold; +} +.org-epa-mark { + /* epa-mark */ + color: #ff0000; + font-weight: bold; +} +.org-epa-string { + /* epa-string */ + color: #00008b; +} +.org-epa-validity-disabled { + /* epa-validity-disabled */ + font-style: italic; +} +.org-epa-validity-high { + /* epa-validity-high */ + font-weight: bold; +} +.org-epa-validity-low { + /* epa-validity-low */ + font-style: italic; +} +.org-epa-validity-medium { + /* epa-validity-medium */ + font-style: italic; +} +.org-error { + /* error */ + color: #ff0000; + font-weight: bold; +} +.org-escape-glyph { + /* escape-glyph */ + color: #a52a2a; +} +.org-evil-ex-commands { + /* evil-ex-commands */ + font-style: italic; + text-decoration: underline; +} +.org-evil-ex-info { + /* evil-ex-info */ + color: #ff0000; + font-style: italic; +} +.org-evil-ex-lazy-highlight { + /* evil-ex-lazy-highlight */ + background-color: #afeeee; +} +.org-evil-ex-search { + /* evil-ex-search */ + color: #b0e2ff; + background-color: #cd00cd; +} +.org-evil-ex-substitute-matches { + /* evil-ex-substitute-matches */ + background-color: #afeeee; +} +.org-evil-ex-substitute-replacement { + /* evil-ex-substitute-replacement */ + color: #ff0000; + text-decoration: underline; +} +.org-ffap { + /* ffap */ + background-color: #b4eeb4; +} +.org-file-name-shadow { + /* file-name-shadow */ + color: #7f7f7f; +} +.org-fixed-pitch { +} +.org-fixed-pitch-serif { +} +.org-flycheck-error { + /* flycheck-error */ + text-decoration: underline; +} +.org-flycheck-error-list-checker-name { + /* flycheck-error-list-checker-name */ + color: #0000ff; +} +.org-flycheck-error-list-column-number { + /* flycheck-error-list-column-number */ + color: #008b8b; +} +.org-flycheck-error-list-error { + /* flycheck-error-list-error */ + color: #ff0000; + font-weight: bold; +} +.org-flycheck-error-list-filename { + /* flycheck-error-list-filename */ + color: #a0522d; +} +.org-flycheck-error-list-highlight { + /* flycheck-error-list-highlight */ + background-color: #b4eeb4; +} +.org-flycheck-error-list-id { + /* flycheck-error-list-id */ + color: #228b22; +} +.org-flycheck-error-list-id-with-explainer { + /* flycheck-error-list-id-with-explainer */ + color: #228b22; +} +.org-flycheck-error-list-info { + /* flycheck-error-list-info */ + color: #228b22; + font-weight: bold; +} +.org-flycheck-error-list-line-number { + /* flycheck-error-list-line-number */ + color: #008b8b; +} +.org-flycheck-error-list-warning { + /* flycheck-error-list-warning */ + color: #ff8c00; + font-weight: bold; +} +.org-flycheck-fringe-error { + /* flycheck-fringe-error */ + color: #ff0000; + font-weight: bold; +} +.org-flycheck-fringe-info { + /* flycheck-fringe-info */ + color: #228b22; + font-weight: bold; +} +.org-flycheck-fringe-warning { + /* flycheck-fringe-warning */ + color: #ff8c00; + font-weight: bold; +} +.org-flycheck-info { + /* flycheck-info */ + text-decoration: underline; +} +.org-flycheck-warning { + /* flycheck-warning */ + text-decoration: underline; +} +.org-flyspell-duplicate { + /* flyspell-duplicate */ + text-decoration: underline; +} +.org-flyspell-incorrect { + /* flyspell-incorrect */ + text-decoration: underline; +} +.org-fringe { + /* fringe */ + background-color: #f2f2f2; +} +.org-function-name { + /* font-lock-function-name-face */ + color: #0000ff; +} +.org-glyphless-char { + /* glyphless-char */ + font-size: 60%; +} +.org-golden-ratio-scroll-highlight-line { + /* golden-ratio-scroll-highlight-line-face */ + color: #ffffff; + background-color: #53868b; + font-weight: bold; +} +.org-header-line { + /* header-line */ + color: #333333; + background-color: #e5e5e5; +} +.org-helm-action { + /* helm-action */ + text-decoration: underline; +} +.org-helm-bookmark-addressbook { + /* helm-bookmark-addressbook */ + color: #ff6347; +} +.org-helm-bookmark-directory { + /* helm-bookmark-directory */ + color: #8b0000; + background-color: #d3d3d3; +} +.org-helm-bookmark-file { + /* helm-bookmark-file */ + color: #00b2ee; +} +.org-helm-bookmark-file-not-found { + /* helm-bookmark-file-not-found */ + color: #6c7b8b; +} +.org-helm-bookmark-gnus { + /* helm-bookmark-gnus */ + color: #ff00ff; +} +.org-helm-bookmark-info { + /* helm-bookmark-info */ + color: #00ff00; +} +.org-helm-bookmark-man { + /* helm-bookmark-man */ + color: #8b5a00; +} +.org-helm-bookmark-w3m { + /* helm-bookmark-w3m */ + color: #ffff00; +} +.org-helm-buffer-archive { + /* helm-buffer-archive */ + color: #ffd700; +} +.org-helm-buffer-directory { + /* helm-buffer-directory */ + color: #8b0000; + background-color: #d3d3d3; +} +.org-helm-buffer-file { + /* helm-buffer-file */ + color: #483d8b; +} +.org-helm-buffer-modified { + /* helm-buffer-modified */ + color: #b22222; +} +.org-helm-buffer-not-saved { + /* helm-buffer-not-saved */ + color: #ee6363; +} +.org-helm-buffer-process { + /* helm-buffer-process */ + color: #cd6839; +} +.org-helm-buffer-saved-out { + /* helm-buffer-saved-out */ + color: #ff0000; + background-color: #000000; +} +.org-helm-buffer-size { + /* helm-buffer-size */ + color: #708090; +} +.org-helm-candidate-number { + /* helm-candidate-number */ + color: #000000; + background-color: #faffb5; +} +.org-helm-candidate-number-suspended { + /* helm-candidate-number-suspended */ + color: #000000; + background-color: #faffb5; +} +.org-helm-delete-async-message { + /* helm-delete-async-message */ + color: #ffff00; +} +.org-helm-etags-file { + /* helm-etags-file */ + color: #8b814c; + text-decoration: underline; +} +.org-helm-ff-denied { + /* helm-ff-denied */ + color: #ff0000; + background-color: #000000; +} +.org-helm-ff-directory { + /* helm-ff-directory */ + color: #8b0000; + background-color: #d3d3d3; +} +.org-helm-ff-dirs { + /* helm-ff-dirs */ + color: #0000ff; +} +.org-helm-ff-dotted-directory { + /* helm-ff-dotted-directory */ + color: #000000; + background-color: #696969; +} +.org-helm-ff-dotted-symlink-directory { + /* helm-ff-dotted-symlink-directory */ + color: #ff8c00; + background-color: #696969; +} +.org-helm-ff-executable { + /* helm-ff-executable */ + color: #00ff00; +} +.org-helm-ff-file { + /* helm-ff-file */ + color: #483d8b; +} +.org-helm-ff-invalid-symlink { + /* helm-ff-invalid-symlink */ + color: #000000; + background-color: #ff0000; +} +.org-helm-ff-pipe { + /* helm-ff-pipe */ + color: #ffff00; + background-color: #000000; +} +.org-helm-ff-prefix { + /* helm-ff-prefix */ + color: #000000; + background-color: #ffff00; +} +.org-helm-ff-socket { + /* helm-ff-socket */ + color: #ff1493; +} +.org-helm-ff-suid { + /* helm-ff-suid */ + color: #ffffff; + background-color: #ff0000; +} +.org-helm-ff-symlink { + /* helm-ff-symlink */ + color: #b22222; +} +.org-helm-ff-truename { + /* helm-ff-truename */ + color: #8b2252; +} +.org-helm-grep-cmd-line { + /* helm-grep-cmd-line */ + color: #228b22; +} +.org-helm-grep-file { + /* helm-grep-file */ + color: #8a2be2; + text-decoration: underline; +} +.org-helm-grep-finish { + /* helm-grep-finish */ + color: #00ff00; +} +.org-helm-grep-lineno { + /* helm-grep-lineno */ + color: #ff7f00; +} +.org-helm-grep-match { + /* helm-grep-match */ + color: #b00000; +} +.org-helm-header { + /* helm-header */ + color: #333333; + background-color: #e5e5e5; +} +.org-helm-header-line-left-margin { + /* helm-header-line-left-margin */ + color: #000000; + background-color: #ffff00; +} +.org-helm-helper { + /* helm-helper */ + color: #333333; + background-color: #e5e5e5; +} +.org-helm-history-deleted { + /* helm-history-deleted */ + color: #000000; + background-color: #ff0000; +} +.org-helm-history-remote { + /* helm-history-remote */ + color: #ff6a6a; +} +.org-helm-lisp-completion-info { + /* helm-lisp-completion-info */ + color: #ff0000; +} +.org-helm-lisp-show-completion { + /* helm-lisp-show-completion */ + background-color: #2f4f4f; +} +.org-helm-locate-finish { + /* helm-locate-finish */ + color: #00ff00; +} +.org-helm-m-x-key { + /* helm-M-x-key */ + color: #ffa500; + text-decoration: underline; +} +.org-helm-match { + /* helm-match */ + color: #b00000; +} +.org-helm-match-item { + /* helm-match-item */ + color: #b0e2ff; + background-color: #cd00cd; +} +.org-helm-minibuffer-prompt { + /* helm-minibuffer-prompt */ + color: #0000cd; +} +.org-helm-moccur-buffer { + /* helm-moccur-buffer */ + color: #00ced1; + text-decoration: underline; +} +.org-helm-non-file-buffer { + /* helm-non-file-buffer */ + font-style: italic; +} +.org-helm-prefarg { + /* helm-prefarg */ + color: #ff0000; +} +.org-helm-resume-need-update { + /* helm-resume-need-update */ + background-color: #ff0000; +} +.org-helm-selection { + /* helm-selection */ + background-color: #097209; +} +.org-helm-selection-line { + /* helm-selection-line */ + background-color: #b4eeb4; +} +.org-helm-separator { + /* helm-separator */ + color: #ffbfb5; +} +.org-helm-source-header { + /* helm-source-header */ + color: #000000; + background-color: #abd7f0; + font-size: 130%; + font-weight: bold; +} +.org-helm-visible-mark { + /* helm-visible-mark */ + background-color: #d1f5ea; +} +.org-help-argument-name { + /* help-argument-name */ + font-style: italic; +} +.org-highlight { + /* highlight */ + background-color: #b4eeb4; +} +.org-highlight-indent-guides-character { + /* highlight-indent-guides-character-face */ + color: #e6e6e6; +} +.org-highlight-indent-guides-even { + /* highlight-indent-guides-even-face */ + background-color: #e6e6e6; +} +.org-highlight-indent-guides-odd { + /* highlight-indent-guides-odd-face */ + background-color: #f3f3f3; +} +.org-highlight-indent-guides-stack-character { + /* highlight-indent-guides-stack-character-face */ + color: #cccccc; +} +.org-highlight-indent-guides-stack-even { + /* highlight-indent-guides-stack-even-face */ + background-color: #cccccc; +} +.org-highlight-indent-guides-stack-odd { + /* highlight-indent-guides-stack-odd-face */ + background-color: #d9d9d9; +} +.org-highlight-indent-guides-top-character { + /* highlight-indent-guides-top-character-face */ + color: #b3b3b3; +} +.org-highlight-indent-guides-top-even { + /* highlight-indent-guides-top-even-face */ + background-color: #b3b3b3; +} +.org-highlight-indent-guides-top-odd { + /* highlight-indent-guides-top-odd-face */ + background-color: #c0c0c0; +} +.org-highlight-numbers-number { + /* highlight-numbers-number */ + color: #008b8b; +} +.org-hl-line { + /* hl-line */ + background-color: #b4eeb4; +} +.org-holiday { + /* holiday */ + background-color: #ffc0cb; +} +.org-hydra-face-amaranth { + /* hydra-face-amaranth */ + color: #E52B50; + font-weight: bold; +} +.org-hydra-face-blue { + /* hydra-face-blue */ + color: #0000FF; + font-weight: bold; +} +.org-hydra-face-pink { + /* hydra-face-pink */ + color: #FF6EB4; + font-weight: bold; +} +.org-hydra-face-red { + /* hydra-face-red */ + color: #FF0000; + font-weight: bold; +} +.org-hydra-face-teal { + /* hydra-face-teal */ + color: #367588; + font-weight: bold; +} +.org-ido-first-match { + /* ido-first-match */ + font-weight: bold; +} +.org-ido-incomplete-regexp { + /* ido-incomplete-regexp */ + color: #ff0000; + font-weight: bold; +} +.org-ido-indicator { + /* ido-indicator */ + color: #ffff00; + background-color: #ff0000; +} +.org-ido-only-match { + /* ido-only-match */ + color: #228b22; +} +.org-ido-subdir { + /* ido-subdir */ + color: #ff0000; +} +.org-ido-virtual { + /* ido-virtual */ + color: #483d8b; +} +.org-info-header-node { + /* info-header-node */ + color: #a52a2a; + font-weight: bold; + font-style: italic; +} +.org-info-header-xref { + /* info-header-xref */ + color: #3a5fcd; + text-decoration: underline; +} +.org-info-index-match { + /* info-index-match */ + background-color: #ffff00; +} +.org-info-menu-header { + /* info-menu-header */ + font-weight: bold; +} +.org-info-menu-star { + /* info-menu-star */ + color: #ff0000; +} +.org-info-node { + /* info-node */ + color: #a52a2a; + font-weight: bold; + font-style: italic; +} +.org-info-quoted { +} +.org-info-title-1 { + /* info-title-1 */ + font-size: 172%; + font-weight: bold; +} +.org-info-title-2 { + /* info-title-2 */ + font-size: 144%; + font-weight: bold; +} +.org-info-title-3 { + /* info-title-3 */ + font-size: 120%; + font-weight: bold; +} +.org-info-title-4 { + /* info-title-4 */ + font-weight: bold; +} +.org-info-xref { + /* info-xref */ + color: #3a5fcd; + text-decoration: underline; +} +.org-isearch { + /* isearch */ + color: #b0e2ff; + background-color: #cd00cd; +} +.org-isearch-fail { + /* isearch-fail */ + background-color: #ffc1c1; +} +.org-italic { + /* italic */ + font-style: italic; +} +.org-keyword { + /* font-lock-keyword-face */ + color: #a020f0; +} +.org-lazy-highlight { + /* lazy-highlight */ + background-color: #afeeee; +} +.org-link { + /* link */ + color: #3a5fcd; + text-decoration: underline; +} +.org-link-visited { + /* link-visited */ + color: #8b008b; + text-decoration: underline; +} +.org-lv-separator { + /* lv-separator */ + background-color: #cccccc; +} +.org-match { + /* match */ + background-color: #ffff00; +} +.org-mcXcursor { +} +.org-mcXcursor-bar { + /* mc/cursor-bar-face */ + background-color: #000000; +} +.org-mcXregion { + /* mc/region-face */ + background-color: gtk_selection_bg_color; +} +.org-me-dired-dim-0 { + /* me-dired-dim-0 */ + color: #b3b3b3; +} +.org-me-dired-dim-1 { + /* me-dired-dim-1 */ + color: #7f7f7f; +} +.org-me-dired-executable { + /* me-dired-executable */ + color: #00ff00; +} +.org-menu { +} +.org-message-cited-text { + /* message-cited-text */ + color: #ff0000; +} +.org-message-header-cc { + /* message-header-cc */ + color: #191970; +} +.org-message-header-name { + /* message-header-name */ + color: #6495ed; +} +.org-message-header-newsgroups { + /* message-header-newsgroups */ + color: #00008b; + font-weight: bold; + font-style: italic; +} +.org-message-header-other { + /* message-header-other */ + color: #4682b4; +} +.org-message-header-subject { + /* message-header-subject */ + color: #000080; + font-weight: bold; +} +.org-message-header-to { + /* message-header-to */ + color: #191970; + font-weight: bold; +} +.org-message-header-xheader { + /* message-header-xheader */ + color: #0000ff; +} +.org-message-mml { + /* message-mml */ + color: #228b22; +} +.org-message-separator { + /* message-separator */ + color: #a52a2a; +} +.org-minibuffer-prompt { + /* minibuffer-prompt */ + color: #0000cd; +} +.org-mm-command-output { + /* mm-command-output */ + color: #cd0000; +} +.org-mode-line { + /* mode-line */ + color: #000000; + background-color: #bfbfbf; +} +.org-mode-line-buffer-id { + /* mode-line-buffer-id */ + font-weight: bold; +} +.org-mode-line-buffer-id-inactive { + /* mode-line-buffer-id-inactive */ + font-weight: bold; +} +.org-mode-line-emphasis { + /* mode-line-emphasis */ + font-weight: bold; +} +.org-mode-line-highlight { +} +.org-mode-line-inactive { + /* mode-line-inactive */ + color: #333333; + background-color: #e5e5e5; +} +.org-mouse { +} +.org-mu4e-attach-number { + /* mu4e-attach-number-face */ + color: #a0522d; + font-weight: bold; +} +.org-mu4e-cited-1 { + /* mu4e-cited-1-face */ + color: #483d8b; + font-style: italic; +} +.org-mu4e-cited-2 { + /* mu4e-cited-2-face */ + color: #5cacee; + font-style: italic; +} +.org-mu4e-cited-3 { + /* mu4e-cited-3-face */ + color: #a0522d; + font-style: italic; +} +.org-mu4e-cited-4 { + /* mu4e-cited-4-face */ + color: #a020f0; + font-style: italic; +} +.org-mu4e-cited-5 { + /* mu4e-cited-5-face */ + color: #b22222; + font-style: italic; +} +.org-mu4e-cited-6 { + /* mu4e-cited-6-face */ + color: #b22222; + font-style: italic; +} +.org-mu4e-cited-7 { + /* mu4e-cited-7-face */ + color: #228b22; + font-style: italic; +} +.org-mu4e-compose-header { + /* mu4e-compose-header-face */ + color: #a52a2a; + font-style: italic; +} +.org-mu4e-compose-separator { + /* mu4e-compose-separator-face */ + color: #a52a2a; + font-style: italic; +} +.org-mu4e-contact { + /* mu4e-contact-face */ + color: #a0522d; +} +.org-mu4e-context { + /* mu4e-context-face */ + color: #006400; + font-weight: bold; +} +.org-mu4e-draft { + /* mu4e-draft-face */ + color: #8b2252; +} +.org-mu4e-flagged { + /* mu4e-flagged-face */ + color: #008b8b; + font-weight: bold; +} +.org-mu4e-footer { + /* mu4e-footer-face */ + color: #b22222; +} +.org-mu4e-forwarded { + /* mu4e-forwarded-face */ + color: #483d8b; +} +.org-mu4e-header { + /* mu4e-header-face */ + color: #000000; + background-color: #ffffff; +} +.org-mu4e-header-highlight { + /* mu4e-header-highlight-face */ + background-color: #000000; + font-weight: bold; + text-decoration: underline; +} +.org-mu4e-header-key { + /* mu4e-header-key-face */ + color: #6495ed; + font-weight: bold; +} +.org-mu4e-header-marks { + /* mu4e-header-marks-face */ + color: #483d8b; +} +.org-mu4e-header-title { + /* mu4e-header-title-face */ + color: #228b22; +} +.org-mu4e-header-value { + /* mu4e-header-value-face */ + color: #228b22; +} +.org-mu4e-highlight { + /* mu4e-highlight-face */ + background-color: #b4eeb4; +} +.org-mu4e-link { + /* mu4e-link-face */ + color: #3a5fcd; + text-decoration: underline; +} +.org-mu4e-modeline { + /* mu4e-modeline-face */ + color: #8b4500; + font-weight: bold; +} +.org-mu4e-moved { + /* mu4e-moved-face */ + color: #b22222; + font-style: italic; +} +.org-mu4e-ok { + /* mu4e-ok-face */ + color: #b22222; + font-weight: bold; +} +.org-mu4e-region-code { + /* mu4e-region-code */ + background-color: #2f4f4f; +} +.org-mu4e-replied { + /* mu4e-replied-face */ + color: #483d8b; +} +.org-mu4e-special-header-value { + /* mu4e-special-header-value-face */ + color: #483d8b; +} +.org-mu4e-system { + /* mu4e-system-face */ + color: #b22222; + font-style: italic; +} +.org-mu4e-title { + /* mu4e-title-face */ + color: #228b22; + font-weight: bold; +} +.org-mu4e-trashed { + /* mu4e-trashed-face */ + color: #b22222; + text-decoration: line-through; +} +.org-mu4e-unread { + /* mu4e-unread-face */ + color: #a020f0; + font-weight: bold; +} +.org-mu4e-url-number { + /* mu4e-url-number-face */ + color: #008b8b; + font-weight: bold; +} +.org-mu4e-view-body { + /* mu4e-view-body-face */ + color: #000000; + background-color: #ffffff; +} +.org-mu4e-warning { + /* mu4e-warning-face */ + color: #ff0000; + font-weight: bold; +} +.org-negation-char { +} +.org-next-error { + /* next-error */ + background-color: gtk_selection_bg_color; +} +.org-nobreak-space { + /* nobreak-space */ + color: #a52a2a; + text-decoration: underline; +} +.org-org-agenda-calendar-event { + /* org-agenda-calendar-event */ + color: #000000; + background-color: #ffffff; +} +.org-org-agenda-calendar-sexp { + /* org-agenda-calendar-sexp */ + color: #000000; + background-color: #ffffff; +} +.org-org-agenda-clocking { + /* org-agenda-clocking */ + background-color: #ffff00; +} +.org-org-agenda-column-dateline { + /* org-agenda-column-dateline */ + background-color: #e5e5e5; +} +.org-org-agenda-current-time { + /* org-agenda-current-time */ + color: #b8860b; +} +.org-org-agenda-date { + /* org-agenda-date */ + color: #0000ff; +} +.org-org-agenda-date-today { + /* org-agenda-date-today */ + color: #0000ff; + font-weight: bold; + font-style: italic; +} +.org-org-agenda-date-weekend { + /* org-agenda-date-weekend */ + color: #0000ff; + font-weight: bold; +} +.org-org-agenda-diary { + /* org-agenda-diary */ + color: #000000; + background-color: #ffffff; +} +.org-org-agenda-dimmed-todo { + /* org-agenda-dimmed-todo-face */ + color: #7f7f7f; +} +.org-org-agenda-done { + /* org-agenda-done */ + color: #228b22; +} +.org-org-agenda-filter-category { + /* org-agenda-filter-category */ + color: #000000; + background-color: #bfbfbf; +} +.org-org-agenda-filter-effort { + /* org-agenda-filter-effort */ + color: #000000; + background-color: #bfbfbf; +} +.org-org-agenda-filter-regexp { + /* org-agenda-filter-regexp */ + color: #000000; + background-color: #bfbfbf; +} +.org-org-agenda-filter-tags { + /* org-agenda-filter-tags */ + color: #000000; + background-color: #bfbfbf; +} +.org-org-agenda-restriction-lock { + /* org-agenda-restriction-lock */ + background-color: #eeeeee; +} +.org-org-agenda-structure { + /* org-agenda-structure */ + color: #0000ff; +} +.org-org-archived { + /* org-archived */ + color: #7f7f7f; +} +.org-org-beamer-tag { +} +.org-org-block { + /* org-block */ + color: #7f7f7f; +} +.org-org-block-begin-line { + /* org-block-begin-line */ + color: #b22222; +} +.org-org-block-end-line { + /* org-block-end-line */ + color: #b22222; +} +.org-org-checkbox { + /* org-checkbox */ + font-weight: bold; +} +.org-org-checkbox-statistics-done { + /* org-checkbox-statistics-done */ + color: #228b22; + font-weight: bold; +} +.org-org-checkbox-statistics-todo { + /* org-checkbox-statistics-todo */ + color: #ff0000; + font-weight: bold; +} +.org-org-clock-overlay { + /* org-clock-overlay */ + color: #000000; + background-color: #d3d3d3; +} +.org-org-code { + /* org-code */ + color: #7f7f7f; +} +.org-org-column { + /* org-column */ + background-color: #e5e5e5; +} +.org-org-column-title { + /* org-column-title */ + background-color: #e5e5e5; + font-weight: bold; + text-decoration: underline; +} +.org-org-date { + /* org-date */ + color: #bfaf87; + text-decoration: underline; +} +.org-org-date-selected { + /* org-date-selected */ + color: #ff0000; +} +.org-org-default { + /* org-default */ + color: #000000; + background-color: #ffffff; +} +.org-org-document-info { + /* org-document-info */ + color: #191970; +} +.org-org-document-info-keyword { + /* org-document-info-keyword */ + color: #7f7f7f; +} +.org-org-document-title { + /* org-document-title */ + color: #191970; + font-weight: bold; +} +.org-org-done { + /* org-done */ + color: #228b22; + font-weight: bold; +} +.org-org-drawer { + /* org-drawer */ + color: #0000ff; +} +.org-org-ellipsis { + /* org-ellipsis */ + color: #b8860b; + text-decoration: underline; +} +.org-org-footnote { + /* org-footnote */ + color: #96b4cd; + text-decoration: underline; +} +.org-org-formula { + /* org-formula */ + color: #b22222; +} +.org-org-habit-alert { + /* org-habit-alert-face */ + background-color: #f5f946; +} +.org-org-habit-alert-future { + /* org-habit-alert-future-face */ + background-color: #fafca9; +} +.org-org-habit-clear { + /* org-habit-clear-face */ + background-color: #8270f9; +} +.org-org-habit-clear-future { + /* org-habit-clear-future-face */ + background-color: #d6e4fc; +} +.org-org-habit-overdue { + /* org-habit-overdue-face */ + background-color: #f9372d; +} +.org-org-habit-overdue-future { + /* org-habit-overdue-future-face */ + background-color: #fc9590; +} +.org-org-habit-ready { + /* org-habit-ready-face */ + background-color: #4df946; +} +.org-org-habit-ready-future { + /* org-habit-ready-future-face */ + background-color: #acfca9; +} +.org-org-headline-done { + /* org-headline-done */ + color: #bc8f8f; +} +.org-org-hide { + /* org-hide */ + color: #ffffff; +} +.org-org-latex-and-related { + /* org-latex-and-related */ + color: #8b4513; +} +.org-org-level-1 { + /* org-level-1 */ + color: #edd1c5; +} +.org-org-level-2 { + /* org-level-2 */ + color: #ebebb7; +} +.org-org-level-3 { + /* org-level-3 */ + color: #cce8cc; +} +.org-org-level-4 { + /* org-level-4 */ + color: #c9deec; +} +.org-org-level-5 { + /* org-level-5 */ + color: #dce3e8; +} +.org-org-level-6 { + /* org-level-6 */ + color: #dde6dd; +} +.org-org-level-7 { + /* org-level-7 */ + color: #e8e8ce; +} +.org-org-level-8 { + /* org-level-8 */ + color: #e8dedb; +} +.org-org-link { + /* org-link */ + color: #c5d2dc; + text-decoration: underline; +} +.org-org-list-dt { + /* org-list-dt */ + font-weight: bold; +} +.org-org-macro { + /* org-macro */ + color: #8b4513; +} +.org-org-meta-line { + /* org-meta-line */ + color: #b22222; +} +.org-org-mode-line-clock { + /* org-mode-line-clock */ + color: #000000; + background-color: #bfbfbf; +} +.org-org-mode-line-clock-overrun { + /* org-mode-line-clock-overrun */ + color: #000000; + background-color: #ff0000; +} +.org-org-priority { + /* org-priority */ + color: #a020f0; +} +.org-org-property-value { +} +.org-org-quote { + /* org-quote */ + color: #7f7f7f; +} +.org-org-ref-acronym { + /* org-ref-acronym-face */ + color: #ee7600; + text-decoration: underline; +} +.org-org-ref-cite { + /* org-ref-cite-face */ + color: #c3d5c3; + text-decoration: underline; +} +.org-org-ref-glossary { + /* org-ref-glossary-face */ + color: #8968cd; + text-decoration: underline; +} +.org-org-ref-label { + /* org-ref-label-face */ + color: #8b008b; + text-decoration: underline; +} +.org-org-ref-ref { + /* org-ref-ref-face */ + color: #e1cc96; + text-decoration: underline; +} +.org-org-scheduled { + /* org-scheduled */ + color: #006400; +} +.org-org-scheduled-previously { + /* org-scheduled-previously */ + color: #b22222; +} +.org-org-scheduled-today { + /* org-scheduled-today */ + color: #006400; +} +.org-org-sexp-date { + /* org-sexp-date */ + color: #a020f0; +} +.org-org-special-keyword { + /* org-special-keyword */ + color: #88949f; +} +.org-org-table { + /* org-table */ + color: #0000ff; +} +.org-org-tag { + /* org-tag */ + font-weight: bold; +} +.org-org-tag-group { + /* org-tag-group */ + font-weight: bold; +} +.org-org-target { + /* org-target */ + text-decoration: underline; +} +.org-org-time-grid { + /* org-time-grid */ + color: #b8860b; +} +.org-org-todo { + /* org-todo */ + color: #ff0000; + font-weight: bold; +} +.org-org-upcoming-deadline { + /* org-upcoming-deadline */ + color: #b22222; +} +.org-org-verbatim { + /* org-verbatim */ + color: #7f7f7f; +} +.org-org-verse { + /* org-verse */ + color: #7f7f7f; +} +.org-org-warning { + /* org-warning */ + color: #ff0000; + font-weight: bold; +} +.org-outline-1 { + /* outline-1 */ + color: #0000ff; +} +.org-outline-2 { + /* outline-2 */ + color: #a0522d; +} +.org-outline-3 { + /* outline-3 */ + color: #a020f0; +} +.org-outline-4 { + /* outline-4 */ + color: #b22222; +} +.org-outline-5 { + /* outline-5 */ + color: #228b22; +} +.org-outline-6 { + /* outline-6 */ + color: #008b8b; +} +.org-outline-7 { + /* outline-7 */ + color: #483d8b; +} +.org-outline-8 { + /* outline-8 */ + color: #8b2252; +} +.org-package-description { + /* package-description */ + color: #000000; + background-color: #ffffff; +} +.org-package-name { + /* package-name */ + color: #3a5fcd; + text-decoration: underline; +} +.org-package-status-avail-obso { + /* package-status-avail-obso */ + color: #b22222; +} +.org-package-status-available { + /* package-status-available */ + color: #000000; + background-color: #ffffff; +} +.org-package-status-built-in { + /* package-status-built-in */ + color: #483d8b; +} +.org-package-status-dependency { + /* package-status-dependency */ + color: #b22222; +} +.org-package-status-disabled { + /* package-status-disabled */ + color: #ff0000; + font-weight: bold; +} +.org-package-status-external { + /* package-status-external */ + color: #483d8b; +} +.org-package-status-held { + /* package-status-held */ + color: #008b8b; +} +.org-package-status-incompat { + /* package-status-incompat */ + color: #b22222; +} +.org-package-status-installed { + /* package-status-installed */ + color: #b22222; +} +.org-package-status-unsigned { + /* package-status-unsigned */ + color: #ff0000; + font-weight: bold; +} +.org-pdf-isearch-batch { + /* pdf-isearch-batch */ + background-color: #ffff00; +} +.org-pdf-isearch-lazy { + /* pdf-isearch-lazy */ + background-color: #afeeee; +} +.org-pdf-isearch-match { + /* pdf-isearch-match */ + color: #b0e2ff; + background-color: #cd00cd; +} +.org-pdf-occur-document { + /* pdf-occur-document-face */ + color: #8b2252; +} +.org-pdf-occur-page { + /* pdf-occur-page-face */ + color: #228b22; +} +.org-pdf-view-rectangle { + /* pdf-view-rectangle */ + background-color: #b4eeb4; +} +.org-pdf-view-region { + /* pdf-view-region */ + background-color: gtk_selection_bg_color; +} +.org-powerline-active0 { + /* powerline-active0 */ + color: #000000; + background-color: #bfbfbf; +} +.org-powerline-active1 { + /* powerline-active1 */ + color: #ffffff; + background-color: #2b2b2b; +} +.org-powerline-active2 { + /* powerline-active2 */ + color: #ffffff; + background-color: #666666; +} +.org-powerline-inactive0 { + /* powerline-inactive0 */ + color: #333333; + background-color: #e5e5e5; +} +.org-powerline-inactive1 { + /* powerline-inactive1 */ + color: #333333; + background-color: #1c1c1c; +} +.org-powerline-inactive2 { + /* powerline-inactive2 */ + color: #333333; + background-color: #333333; +} +.org-preprocessor { + /* font-lock-preprocessor-face */ + color: #483d8b; +} +.org-query-replace { + /* query-replace */ + color: #b0e2ff; + background-color: #cd00cd; +} +.org-rainbow-delimiters-base { +} +.org-rainbow-delimiters-depth-1 { + /* rainbow-delimiters-depth-1-face */ + color: #ffdead; +} +.org-rainbow-delimiters-depth-2 { + /* rainbow-delimiters-depth-2-face */ + color: #00bfff; +} +.org-rainbow-delimiters-depth-3 { + /* rainbow-delimiters-depth-3-face */ + color: #ffdead; +} +.org-rainbow-delimiters-depth-4 { + /* rainbow-delimiters-depth-4-face */ + color: #00bfff; +} +.org-rainbow-delimiters-depth-5 { + /* rainbow-delimiters-depth-5-face */ + color: #ffdead; +} +.org-rainbow-delimiters-depth-6 { + /* rainbow-delimiters-depth-6-face */ + color: #00bfff; +} +.org-rainbow-delimiters-depth-7 { + /* rainbow-delimiters-depth-7-face */ + color: #ffdead; +} +.org-rainbow-delimiters-depth-8 { + /* rainbow-delimiters-depth-8-face */ + color: #00bfff; +} +.org-rainbow-delimiters-depth-9 { + /* rainbow-delimiters-depth-9-face */ + color: #ffdead; +} +.org-rainbow-delimiters-unmatched { + /* rainbow-delimiters-unmatched-face */ + color: #88090B; +} +.org-reb-match-0 { + /* reb-match-0 */ + background-color: #add8e6; +} +.org-reb-match-1 { + /* reb-match-1 */ + background-color: #7fffd4; +} +.org-reb-match-2 { + /* reb-match-2 */ + background-color: #00ff7f; +} +.org-reb-match-3 { + /* reb-match-3 */ + background-color: #ffff00; +} +.org-rectangle-preview { + /* rectangle-preview */ + background-color: gtk_selection_bg_color; +} +.org-regexp-grouping-backslash { + /* font-lock-regexp-grouping-backslash */ + font-weight: bold; +} +.org-regexp-grouping-construct { + /* font-lock-regexp-grouping-construct */ + font-weight: bold; +} +.org-region { + /* region */ + background-color: gtk_selection_bg_color; +} +.org-scroll-bar { +} +.org-secondary-selection { + /* secondary-selection */ + background-color: #ffff00; +} +.org-semantic-highlight-edits { + /* semantic-highlight-edits-face */ + background-color: #e5e5e5; +} +.org-semantic-highlight-func-current-tag { + /* semantic-highlight-func-current-tag-face */ + background-color: #e5e5e5; +} +.org-semantic-unmatched-syntax { + /* semantic-unmatched-syntax-face */ + text-decoration: underline; +} +.org-sgml-namespace { + /* sgml-namespace */ + color: #483d8b; +} +.org-sh-escaped-newline { + /* sh-escaped-newline */ + color: #8b2252; +} +.org-sh-heredoc { + /* sh-heredoc */ + color: #eeee00; +} +.org-sh-quoted-exec { + /* sh-quoted-exec */ + color: #ff00ff; +} +.org-shadow { + /* shadow */ + color: #7f7f7f; +} +.org-show-paren-match { + /* show-paren-match */ + background-color: #40e0d0; +} +.org-show-paren-mismatch { + /* show-paren-mismatch */ + color: #ffffff; + background-color: #a020f0; +} +.org-sp-pair-overlay { + /* sp-pair-overlay-face */ + background-color: #b4eeb4; +} +.org-sp-show-pair-enclosing { + /* sp-show-pair-enclosing */ + background-color: #b4eeb4; +} +.org-sp-show-pair-match { + /* sp-show-pair-match-face */ + background-color: #40e0d0; +} +.org-sp-show-pair-match-content { +} +.org-sp-show-pair-mismatch { + /* sp-show-pair-mismatch-face */ + color: #ffffff; + background-color: #a020f0; +} +.org-sp-wrap-overlay { + /* sp-wrap-overlay-face */ + background-color: #b4eeb4; +} +.org-sp-wrap-overlay-closing-pair { + /* sp-wrap-overlay-closing-pair */ + color: #ff0000; + background-color: #b4eeb4; +} +.org-sp-wrap-overlay-opening-pair { + /* sp-wrap-overlay-opening-pair */ + color: #00ff00; + background-color: #b4eeb4; +} +.org-sp-wrap-tag-overlay { + /* sp-wrap-tag-overlay-face */ + background-color: #b4eeb4; +} +.org-spaceline-flycheck-error { + /* spaceline-flycheck-error */ + color: #FC5C94; + background-color: #333333; +} +.org-spaceline-flycheck-info { + /* spaceline-flycheck-info */ + color: #8DE6F7; + background-color: #333333; +} +.org-spaceline-flycheck-warning { + /* spaceline-flycheck-warning */ + color: #F3EA98; + background-color: #333333; +} +.org-spaceline-python-venv { + /* spaceline-python-venv */ + color: #ffbbff; +} +.org-speedbar-button { + /* speedbar-button-face */ + color: #008b00; +} +.org-speedbar-directory { + /* speedbar-directory-face */ + color: #00008b; +} +.org-speedbar-file { + /* speedbar-file-face */ + color: #008b8b; +} +.org-speedbar-highlight { + /* speedbar-highlight-face */ + background-color: #00ff00; +} +.org-speedbar-selected { + /* speedbar-selected-face */ + color: #ff0000; + text-decoration: underline; +} +.org-speedbar-separator { + /* speedbar-separator-face */ + color: #ffffff; + background-color: #0000ff; + text-decoration: overline; +} +.org-speedbar-tag { + /* speedbar-tag-face */ + color: #a52a2a; +} +.org-string { + /* font-lock-string-face */ + color: #8b2252; +} +.org-subscript { +} +.org-success { + /* success */ + color: #228b22; + font-weight: bold; +} +.org-superscript { +} +.org-table-cell { + /* table-cell */ + color: #e5e5e5; + background-color: #0000ff; +} +.org-tex-math { + /* tex-math */ + color: #8b2252; +} +.org-tex-verbatim { +} +.org-tool-bar { + /* tool-bar */ + color: #000000; + background-color: #bfbfbf; +} +.org-tooltip { + /* tooltip */ + color: #000000; + background-color: #ffffe0; +} +.org-trailing-whitespace { + /* trailing-whitespace */ + background-color: #ff0000; +} +.org-tty-menu-disabled { + /* tty-menu-disabled-face */ + color: #d3d3d3; + background-color: #0000ff; +} +.org-tty-menu-enabled { + /* tty-menu-enabled-face */ + color: #ffff00; + background-color: #0000ff; + font-weight: bold; +} +.org-tty-menu-selected { + /* tty-menu-selected-face */ + background-color: #ff0000; +} +.org-type { + /* font-lock-type-face */ + color: #228b22; +} +.org-underline { + /* underline */ + text-decoration: underline; +} +.org-undo-tree-visualizer-active-branch { + /* undo-tree-visualizer-active-branch-face */ + color: #000000; + font-weight: bold; +} +.org-undo-tree-visualizer-current { + /* undo-tree-visualizer-current-face */ + color: #ff0000; +} +.org-undo-tree-visualizer-default { + /* undo-tree-visualizer-default-face */ + color: #bebebe; +} +.org-undo-tree-visualizer-register { + /* undo-tree-visualizer-register-face */ + color: #ffff00; +} +.org-undo-tree-visualizer-unmodified { + /* undo-tree-visualizer-unmodified-face */ + color: #00ffff; +} +.org-variable-name { + /* font-lock-variable-name-face */ + color: #a0522d; +} +.org-variable-pitch { +} +.org-vc-conflict-state { +} +.org-vc-edited-state { +} +.org-vc-locally-added-state { +} +.org-vc-locked-state { +} +.org-vc-missing-state { +} +.org-vc-needs-update-state { +} +.org-vc-removed-state { +} +.org-vc-state-base { +} +.org-vc-up-to-date-state { +} +.org-vertical-border { +} +.org-vhlXdefault { + /* vhl/default-face */ + background-color: #ffff00; +} +.org-warning { + /* warning */ + color: #ff8c00; + font-weight: bold; +} +.org-warning-1 { + /* font-lock-warning-face */ + color: #ff0000; + font-weight: bold; +} +.org-wgrep { + /* wgrep-face */ + color: #ffffff; + background-color: #228b22; +} +.org-wgrep-delete { + /* wgrep-delete-face */ + color: #ffc0cb; + background-color: #228b22; +} +.org-wgrep-done { + /* wgrep-done-face */ + color: #0000ff; +} +.org-wgrep-file { + /* wgrep-file-face */ + color: #ffffff; + background-color: #228b22; +} +.org-wgrep-reject { + /* wgrep-reject-face */ + color: #ff0000; + font-weight: bold; +} +.org-which-key-command-description { + /* which-key-command-description-face */ + color: #0000ff; +} +.org-which-key-docstring { + /* which-key-docstring-face */ + color: #b22222; +} +.org-which-key-group-description { + /* which-key-group-description-face */ + color: #a020f0; +} +.org-which-key-highlighted-command { + /* which-key-highlighted-command-face */ + color: #0000ff; + text-decoration: underline; +} +.org-which-key-key { + /* which-key-key-face */ + color: #008b8b; +} +.org-which-key-local-map-description { + /* which-key-local-map-description-face */ + color: #0000ff; +} +.org-which-key-note { + /* which-key-note-face */ + color: #b22222; +} +.org-which-key-separator { + /* which-key-separator-face */ + color: #b22222; +} +.org-which-key-special-key { + /* which-key-special-key-face */ + color: #008b8b; + font-weight: bold; +} +.org-whitespace-big-indent { + /* whitespace-big-indent */ + color: #b22222; + background-color: #ff0000; +} +.org-whitespace-empty { + /* whitespace-empty */ + color: #b22222; + background-color: #ffff00; +} +.org-whitespace-hspace { + /* whitespace-hspace */ + color: #d3d3d3; + background-color: #cdc9a5; +} +.org-whitespace-indentation { + /* whitespace-indentation */ + color: #b22222; + background-color: #ffff00; +} +.org-whitespace-line { + /* whitespace-line */ + color: #ee82ee; + background-color: #333333; +} +.org-whitespace-newline { + /* whitespace-newline */ + color: #d3d3d3; +} +.org-whitespace-space { + /* whitespace-space */ + color: #d3d3d3; + background-color: #ffffe0; +} +.org-whitespace-space-after-tab { + /* whitespace-space-after-tab */ + color: #b22222; + background-color: #ffff00; +} +.org-whitespace-space-before-tab { + /* whitespace-space-before-tab */ + color: #b22222; + background-color: #ff8c00; +} +.org-whitespace-tab { + /* whitespace-tab */ + color: #d3d3d3; + background-color: #f5f5dc; +} +.org-whitespace-trailing { + /* whitespace-trailing */ + color: #ffff00; + background-color: #ff0000; + font-weight: bold; +} +.org-widget-button { + /* widget-button */ + font-weight: bold; +} +.org-widget-button-pressed { + /* widget-button-pressed */ + color: #ff0000; +} +.org-widget-documentation { + /* widget-documentation */ + color: #006400; +} +.org-widget-field { + /* widget-field */ + background-color: #d9d9d9; +} +.org-widget-inactive { + /* widget-inactive */ + color: #7f7f7f; +} +.org-widget-single-line-field { + /* widget-single-line-field */ + background-color: #d9d9d9; +} +.org-window-divider { + /* window-divider */ + color: #999999; +} +.org-window-divider-first-pixel { + /* window-divider-first-pixel */ + color: #cccccc; +} +.org-window-divider-last-pixel { + /* window-divider-last-pixel */ + color: #666666; +} +.org-yas--field-debug { +} + +.org-diff-added { + /* diff-added */ + color: #657827; + background-color: #efeac7; +} +.org-diff-changed { + /* diff-changed */ + background-color: #b0c4de; +} +.org-diff-context { + /* diff-context */ + color: #333333; +} +.org-diff-file-header { + /* diff-file-header */ + background-color: #fdf6e3; + color: #657b83; + font-weight: bold; +} +.org-diff-function { + /* diff-function */ + background-color: #eee8d5; +} +.org-diff-header { + /* diff-header */ + background-color: #eee8d5; +} +.org-diff-hunk-header { + /* diff-hunk-header */ + background-color: #eee8d5; +} +.org-diff-index { + /* diff-index */ + background-color: #fdf6e3; + color: #657b83; + font-weight: bold; +} +.org-diff-indicator-added { + /* diff-indicator-added */ + color: #859900; +} +.org-diff-indicator-changed { + /* diff-indicator-changed */ + font-weight: bold; +} +.org-diff-indicator-removed { + /* diff-indicator-removed */ + color: #dc322f; +} +.org-diff-nonexistent { + /* diff-nonexistent */ + background-color: #fdf6e3; + color: #657b83; + font-weight: bold; +} +.org-diff-refine-added { + /* diff-refine-added */ + color: #5b6e35; + background-color: #dbdb9c; +} +.org-diff-refine-changed { + /* diff-refine-changed */ + background-color: #ffff55; +} +.org-diff-refine-removed { + /* diff-refine-removed */ + color: #8e433d; + background-color: #ffb9a1; +} +.org-diff-removed { + /* diff-removed */ + color: #a33c35; + background-color: #ffdec8; +} diff --git a/index.org b/index.org new file mode 100644 index 0000000..23899ed --- /dev/null +++ b/index.org @@ -0,0 +1,19 @@ +* Ramblings +- [[file:fuzzing-ping.org][2022-12-01: Fuzzing ping(8)]] +- [[file:algorithm-roll.org][2022-06-08: DNSSEC algorithm roll-over]] +- [[file:nsd-unbound-update.org][2020-12-07: nsd(8) / unbound(8) update]] +- [[file:secrets-manager.org][2019-10-20: Secrets Manager]] +- [[file:ports-hints.org][2014-12-21: ports hints]] +* External Writings & Presentations +- [[http://undeadly.org/cgi?action=article&sid=20131025090233][2013-10-25, undeadly: b2k13 hackathon report: Florian Obser (florian@) on nginx.conf(5), slowcgi]] +- [[http://undeadly.org/cgi?action=article&sid=20140721125020][2014-07-21, undeadly: g2k14: Florian Obser in IPv6 land]] +- [[http://undeadly.org/cgi?action=article&sid=20150805151453][2015-08-05, undeadly: c2k15: florian@ on building the hackathon network, httpd and pflow]] +- [[http://undeadly.org/cgi?action=article&sid=20151113082512][2015-11-16, undeadly: u2k15: florian@ on IPv6 hackery]] +- [[http://undeadly.org/cgi?action=article&sid=20160911000052][2016-09-10, undeadly: g2k16 Hackathon Report: Florian Obser on httpd, networking, acme-client, and more]] +- [[https://undeadly.org/cgi?action=article;sid=20170609013548][2017-07-09, undeadly: d2k17 Hackathon Report: Florian Obser on slaacd(8)]] +- [[https://undeadly.org/cgi?action=article;sid=20171113235334][2017-11-13, undeadly: p2k17 Hackathon report: Florian Obser on network stack progress, kernel relinking and more]] +- [[http://www.openbsd.org/papers/florian_slaacd_bsdcan2018.pdf][2018-06-09, BSDCan: slaacd(8) - A privilege separated and sandboxed IPv6 Stateless Address AutoConfiguration Daemon]], [[https://www.youtube.com/watch?v=tBQXZYotKvI][video]] +- [[https://undeadly.org/cgi?action=article;sid=20190413023608][2019-04-12, undeadly: t2k19 Hackathon Report: unwinding in Taipei]] +- [[http://www.openbsd.org/papers/bsdcan2019_unwind.pdf][2019-05-17, BSDCan: unwind(8) a privilege-separated, validating DNS recursive nameserver for every laptop]], [[https://www.youtube.com/watch?v=88SoI49nO4o][video]] +- [[https://archive.fosdem.org/2020/schedule/event/dns_unwind/][2020-02-01, FOSDEM: unwind(8) a privilege-separated, validating DNS recursive nameserver for every laptop]] +- [[https://undeadly.org/cgi?action=article;sid=20200922090542][2020-09-21, undeadly: k2k20 hackathon report: Florian Obser on DNS]] diff --git a/nsd-unbound-update.org b/nsd-unbound-update.org new file mode 100644 index 0000000..9d9f05e --- /dev/null +++ b/nsd-unbound-update.org @@ -0,0 +1,48 @@ +#+TITLE: nsd(8) / unbound(8) update +#+DATE: 2020-12-07 + +How to update =nsd(8)= and =unbound(8)= in OpenBSD base from NLnetLabs +upstream. + +* nsd(8) +git clone from the upstream repository on [[https://github.com/NLnetLabs/nsd][github]]. +#+begin_src shell + git pull + git diff NSD_4_3_6_REL..NSD_4_3_7_REL . ':!.cirrus.yml' ':!tpkg/*' \ + ':!contrib/*' ':!compat/' ':!README.md' ':!.gitignore' \ + ':!.buildkite/*' ':!makedist.sh' > ~/nsd_4.3.7_upstream.diff + cd /usr/src/usr.sbin/nsd + patch -Ep0 < ~/nsd_4.3.7_upstream.diff + autoheader-2.69 + autoconf-2.69 + make -f Makefile.bsd-wrapper obj + make -f Makefile.bsd-wrapper clean + make -f Makefile.bsd-wrapper -j4 +#+end_src +We also need to update the version numbers in the man pages. For that +we download the release tar ball and generate a diff: +#+begin_src shell + diff -ru . /home/florian/nsd-4.3.7/ | fgrep -v Only > sync.diff +#+end_src +The diff then needs to be partially applied, some changes are +intentional. + +* unbound(8) +I haven't done an unbound update in some time, this is probably +outdated. +git clone from the upstream repository on [[https://github.com/NLnetLabs/unbound][github]]. +#+begin_src shell + git pull + git diff release-1.15.0..release-1.16.0 . \ + ':!contrib/*' ':!compat/' ':!README.md' ':!.gitignore' \ + ':!pythonmod/' ':!testdata/' ':!util/configlexer.c' \ + ':!util/configparser.c' ':!util/configparser.h' \ + ':!.buildkite/*' ':!makedist.sh' > ~/unbound_1.16.0_upstream.diff + cd /usr/src/usr.sbin/unbound + patch -Ep0 < ~/unbound_1.16.0_upstream.diff + autoheader-2.69 + autoconf-2.69 + make -f Makefile.bsd-wrapper obj + make -f Makefile.bsd-wrapper clean + make -f Makefile.bsd-wrapper -j4 +#+end_src diff --git a/ports-hints.org b/ports-hints.org new file mode 100644 index 0000000..5ecdc87 --- /dev/null +++ b/ports-hints.org @@ -0,0 +1,22 @@ +#+TITLE: ports hints +#+SUBTITLE: Stuff about port building I always forget. +#+DATE: 2014-12-21 + +See also [[https://man.openbsd.org/bsd.port.mk][bsd.port.mk(5)]]. + +* Environment variables ++ FETCH​_PACKAGES :: Instruct the package target to download packages + missing, only building them if no suitable packages are + found. Defaults to *No*. + + For example: src_shell[:exports code]{make FETCH_PACKAGES=-Dsnap package} + +* Make targets ++ makesum :: Creates the checksum file. ++ checksum :: Checks the upstream distribution tar ball (or other + archives) against the checksum file. ++ extract :: Extracts the tar ball. ++ build, all :: Build the port. ++ fake :: Do a fake port installation. ++ plist :: Create / update the plist file. ++ package :: Do all the things to create a package. diff --git a/publish.el b/publish.el new file mode 100755 index 0000000..e7af178 --- /dev/null +++ b/publish.el @@ -0,0 +1,48 @@ +#!/usr/local/bin/emacs --script + +(require 'package) + +(package-initialize) + +(setq package-archives '(("melpa" . "https://melpa.org/packages/") + ("elpa" . "https://elpa.gnu.org/packages/") + ("org" . "http://orgmode.org/elpa/"))) + +(unless package-archive-contents + (package-refresh-contents)) + +(unless (package-installed-p 'use-package) + (package-install 'use-package)) +(require 'use-package) +(setq use-package-always-ensure t) + +(use-package htmlize) + +(require 'ox-publish) +(require 'ox-html) +(require 'htmlize) +(require 'org) + +(setq org-html-htmlize-output-type 'css) + +(setq org-html-validation-link nil) +(setq org-publish-project-alist + '(("tlakh" + :base-directory "/var/www/htdocs/" + :publishing-function org-html-publish-to-html + :publishing-directory "/var/www/htdocs/" + :section-numbers nil + :with-author nil + :with-email nil + :with-timestamps nil + :with-toc nil + :with-creator: nil + :html-head-include-default-style: nil + :html-head " + "))) + +(org-publish "tlakh") diff --git a/secrets-manager.org b/secrets-manager.org new file mode 100644 index 0000000..208da8f --- /dev/null +++ b/secrets-manager.org @@ -0,0 +1,51 @@ +#+TITLE: Secrets Manager +#+DATE: 2019-10-20 +* Intro +It seems like everyone eventually writes their own password +manager. This is my take on it. ++ Simple. ++ Reasonable chance of it still working in 20 years. ++ No dependency on fancy language du jour. +Secrets are stored in files. One file per secret. The file name is +used to identify the secret. Secrets are encrypted / decrypted using +[[https://humungus.tedunangst.com/r/reop][=reop(1)=]]. =reop(1)= is available in packages on OpenBSD and in homebrew +on macOS. +* Scripts +** encrypt +#+begin_src shell + #!/bin/sh + j="$@" + reop -E -m - -x "$j" +#+end_src +** decrypt +#+begin_src shell + #!/bin/sh + echo $1 + reop -D -m - -x "$1" +#+end_src +** 2fa +As a bonus here is a script for two factor authentication. +[[https://www.nongnu.org/oath-toolkit/man-oathtool.html][=oathtool(1)=]] is available in packages on OpenBSD and homebrew as +=oath-toolkit=. Whether this is safe depends on your threat model. +#+begin_src shell + #!/bin/sh + /usr/local/bin/oathtool --totp --base32 `reop -D -m - -x "$1"` +#+end_src +* Epilogue +Storing secrets in files, one file per secret, lets us organise our +secrets in a file system hierarchy. This is a thing most people are +already familiar with. The file system hierarchy can be backuped and +tracked in a version control system. + +When tracking the secrets in a version control system it is beneficial +to store one secret per file. One can track when the secret got +created and changed. This enables us to revert back to an old version. + +When secrets are stored in one big encrypted container changes are +opaque to the version control system. Some change happened, but you +can't find out what changed. This might be a good thing. + +A crypto container only tells you: here are some secrets. A secret per +file leaks meta information. If you get access to my secret storage +you can tell that I'm [[https://bsd.network/@florian][@florian@bsd.network]]. But you will not be able +to log in. diff --git a/simple.min.css b/simple.min.css new file mode 100644 index 0000000..52b98ba --- /dev/null +++ b/simple.min.css @@ -0,0 +1 @@ +:root{--sans-font:-apple-system,BlinkMacSystemFont,"Avenir Next",Avenir,"Nimbus Sans L",Roboto,"Noto Sans","Segoe UI",Arial,Helvetica,"Helvetica Neue",sans-serif;--mono-font:Consolas,Menlo,Monaco,"Andale Mono","Ubuntu Mono",monospace;--bg:#fff;--accent-bg:#f5f7ff;--text:#212121;--text-light:#585858;--border:#898EA4;--accent:#0d47a1;--code:#212121;--preformatted:#444;--marked:#ffdd33;--disabled:#efefef}@media (prefers-color-scheme:dark){:root{color-scheme:dark;--bg:#212121;--accent-bg:#2b2b2b;--text:#dcdcdc;--text-light:#ababab;--accent:#ffb300;--code:#f06292;--preformatted:#ccc;--disabled:#111}img,video{opacity:.8}}*,::after,::before{box-sizing:border-box}input,progress,select,textarea{appearance:none;-webkit-appearance:none;-moz-appearance:none}html{font-family:var(--sans-font);scroll-behavior:smooth}body{color:var(--text);background-color:var(--bg);font-size:1.15rem;line-height:1.5;display:grid;grid-template-columns:1fr min(45rem,90%) 1fr;margin:0}body>*{grid-column:2}body>header{background-color:var(--accent-bg);border-bottom:1px solid var(--border);text-align:center;padding:0 .5rem 2rem .5rem;grid-column:1/-1}body>header h1{max-width:1200px;margin:1rem auto}body>header p{max-width:40rem;margin:1rem auto}main{padding-top:1.5rem}body>footer{margin-top:4rem;padding:2rem 1rem 1.5rem 1rem;color:var(--text-light);font-size:.9rem;text-align:center;border-top:1px solid var(--border)}h1{font-size:3rem}h2{font-size:2.6rem;margin-top:3rem}h3{font-size:2rem;margin-top:3rem}h4{font-size:1.44rem}h5{font-size:1.15rem}h6{font-size:.96rem}h1,h2,h3,h4,h5,h6,p{overflow-wrap:break-word}h1,h2,h3{line-height:1.1}@media only screen and (max-width:720px){h1{font-size:2.5rem}h2{font-size:2.1rem}h3{font-size:1.75rem}h4{font-size:1.25rem}}a,a:visited{color:var(--accent)}a:hover{text-decoration:none}[role=button],button,input[type=button],input[type=reset],input[type=submit],label[type=button]{border:none;border-radius:5px;background-color:var(--accent);font-size:1rem;color:var(--bg);padding:.7rem .9rem;margin:.5rem 0}[role=button][aria-disabled=true],button[disabled],input[type=button][disabled],input[type=checkbox][disabled],input[type=radio][disabled],input[type=reset][disabled],input[type=submit][disabled],select[disabled]{opacity:.5;cursor:not-allowed}input:disabled,select:disabled,textarea:disabled{cursor:not-allowed;background-color:var(--disabled)}input[type=range]{padding:0}abbr[title]{cursor:help;text-decoration-line:underline;text-decoration-style:dotted}[role=button]:focus,[role=button]:not([aria-disabled=true]):hover,button:enabled:hover,button:focus,input[type=button]:enabled:hover,input[type=button]:focus,input[type=reset]:enabled:hover,input[type=reset]:focus,input[type=submit]:enabled:hover,input[type=submit]:focus,label[type=button]:focus,label[type=button]:hover{filter:brightness(1.4);cursor:pointer}header>nav{font-size:1rem;line-height:2;padding:1rem 0 0 0}header>nav ol,header>nav ul{align-content:space-around;align-items:center;display:flex;flex-direction:row;flex-wrap:wrap;justify-content:center;list-style-type:none;margin:0;padding:0}header>nav ol li,header>nav ul li{display:inline-block}header>nav a,header>nav a:visited{margin:0 .5rem 1rem .5rem;border:1px solid var(--border);border-radius:5px;color:var(--text);display:inline-block;padding:.1rem 1rem;text-decoration:none}header>nav a:hover{border-color:var(--accent);color:var(--accent);cursor:pointer}@media only screen and (max-width:720px){header>nav a{border:none;padding:0;text-decoration:underline;line-height:1}}aside,details,pre,progress{background-color:var(--accent-bg);border:1px solid var(--border);border-radius:5px;margin-bottom:1rem}aside{font-size:1rem;width:30%;padding:0 15px;margin-left:15px;float:right}@media only screen and (max-width:720px){aside{width:100%;float:none;margin-left:0}}article,fieldset{border:1px solid var(--border);padding:1rem;border-radius:5px;margin-bottom:1rem}article h2:first-child,section h2:first-child{margin-top:1rem}section{border-top:1px solid var(--border);border-bottom:1px solid var(--border);padding:2rem 1rem;margin:3rem 0}section+section,section:first-child{border-top:0;padding-top:0}section:last-child{border-bottom:0;padding-bottom:0}details{padding:.7rem 1rem}summary{cursor:pointer;font-weight:700;padding:.7rem 1rem;margin:-.7rem -1rem;word-break:break-all}details[open]>summary+*{margin-top:0}details[open]>summary{margin-bottom:.5rem}details[open]>:last-child{margin-bottom:0}table{border-collapse:collapse;display:block;margin:1.5rem 0;overflow:auto;width:100%}td,th{border:1px solid var(--border);text-align:left;padding:.5rem}th{background-color:var(--accent-bg);font-weight:700}tr:nth-child(even){background-color:var(--accent-bg)}table caption{font-weight:700;margin-bottom:.5rem}input,select,textarea{font-size:inherit;font-family:inherit;padding:.5rem;margin-bottom:.5rem;color:var(--text);background-color:var(--bg);border:1px solid var(--border);border-radius:5px;box-shadow:none;max-width:100%;display:inline-block}label{display:block}textarea:not([cols]){width:100%}select:not([multiple]){background-image:linear-gradient(45deg,transparent 49%,var(--text) 51%),linear-gradient(135deg,var(--text) 51%,transparent 49%);background-position:calc(100% - 15px),calc(100% - 10px);background-size:5px 5px,5px 5px;background-repeat:no-repeat;padding-right:25px}input[type=checkbox],input[type=radio]{vertical-align:middle;position:relative;width:min-content}input[type=checkbox]+label,input[type=radio]+label{display:inline-block}input[type=radio]{border-radius:100%}input[type=checkbox]:checked,input[type=radio]:checked{background-color:var(--accent)}input[type=checkbox]:checked::after{content:" ";width:.18em;height:.32em;border-radius:0;position:absolute;top:.05em;left:.17em;background-color:transparent;border-right:solid var(--bg) .08em;border-bottom:solid var(--bg) .08em;font-size:1.8em;transform:rotate(45deg)}input[type=radio]:checked::after{content:" ";width:.25em;height:.25em;border-radius:100%;position:absolute;top:.125em;background-color:var(--bg);left:.125em;font-size:32px}@media only screen and (max-width:720px){input,select,textarea{width:100%}}input[type=color]{height:2.5rem;padding:.2rem}input[type=file]{border:0}hr{border:none;height:1px;background:var(--border);margin:1rem auto}mark{padding:2px 5px;border-radius:4px;background-color:var(--marked)}img,video{max-width:100%;height:auto;border-radius:5px}figure{margin:0;text-align:center}figcaption{font-size:.9rem;color:var(--text-light);margin-bottom:1rem}blockquote{margin:2rem 0 2rem 2rem;padding:.4rem .8rem;border-left:.35rem solid var(--accent);color:var(--text-light);font-style:italic}cite{font-size:.9rem;color:var(--text-light);font-style:normal}dt{color:var(--text-light)}code,kbd,pre,pre span,samp{font-family:var(--mono-font);color:var(--code)}kbd{color:var(--preformatted);border:1px solid var(--preformatted);border-bottom:3px solid var(--preformatted);border-radius:5px;padding:.1rem .4rem}pre{padding:1rem 1.4rem;max-width:100%;overflow:auto;color:var(--preformatted)}pre code{color:var(--preformatted);background:0 0;margin:0;padding:0}progress{width:100%}progress:indeterminate{background-color:var(--accent-bg)}progress::-webkit-progress-bar{border-radius:5px;background-color:var(--accent-bg)}progress::-webkit-progress-value{border-radius:5px;background-color:var(--accent)}progress::-moz-progress-bar{border-radius:5px;background-color:var(--accent);transition-property:width;transition-duration:.3s}progress:indeterminate::-moz-progress-bar{background-color:var(--accent-bg)}