<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>May Contain Traces of Bolts</title>
	<atom:link href="https://blog.des.no/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.des.no</link>
	<description>Thinking out loud about cars, computers and security</description>
	<lastBuildDate>Sun, 21 Jun 2026 09:08:58 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.1.2</generator>
	<item>
		<title>pkgbase: what can go wrong?</title>
		<link>https://blog.des.no/2026/06/pkgbase-what-can-go-wrong/</link>
					<comments>https://blog.des.no/2026/06/pkgbase-what-can-go-wrong/#respond</comments>
		
		<dc:creator><![CDATA[Dag-Erling Smørgrav]]></dc:creator>
		<pubDate>Tue, 16 Jun 2026 14:19:37 +0000</pubDate>
				<category><![CDATA[English]]></category>
		<category><![CDATA[FreeBSD]]></category>
		<category><![CDATA[tech]]></category>
		<guid isPermaLink="false">https://blog.des.no/?p=1513</guid>

					<description><![CDATA[Yesterday I wrote about how I ended up manually converting a FreeBSD 15 server and the eight jails it hosts to packaged base manually. I dashed that post off in a bit of a hurry because I knew that if I put it off until later I would probably never get around to it. 20 &#8230; <a href="https://blog.des.no/2026/06/pkgbase-what-can-go-wrong/" class="more-link">Continue reading<span class="screen-reader-text"> "pkgbase: what can go wrong?"</span></a>]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph"><a href="https://blog.des.no/2026/06/pkgbasify/" data-type="post" data-id="1505">Yesterday </a>I wrote about how I ended up manually converting a FreeBSD 15 server and the eight jails it hosts to packaged base manually. I dashed that post off in a bit of a hurry because I knew that if I put it off until later I would probably never get around to it. 20 or so hours later, here&#8217;s a followup with some caveats and some tips on how to ensure the conversion goes well.</p>



<span id="more-1513"></span>



<p class="wp-block-paragraph">First, I should point out that the procedure outlined in yesterday&#8217;s post has no guardrails and should not be attempted unless you are very comfortable with FreeBSD system administration and willing and able to fix things if they go awry.</p>



<p class="wp-block-paragraph">Second, perhaps I should elaborate on why I (mostly) skipped 15.0. We (the FreeBSD project collectively) have been working on packaged base for over a decade. At some point we thought 14.0 was when it would finally land, but that did not pan out. Then it was going to be 15.0, and there was a massive push to get everything ready, both in base and in <a href="https://github.com/freebsd/pkg" data-type="link" data-id="https://github.com/freebsd/pkg">pkg</a>&#8230; and we still failed: packaged base in FreeBSD 15 is officially a technology preview, and FreeBSD 16 is when we will finally transition. As a result, the pre-release churn on the <code>stable/15</code> branch was much higher than for a normal major release and a number of things fell through the cracks (including some that had nothing to do with packaged base). The bottom line is that I did not feel that 15.0 was production-ready when it came out, but I worked hard to get most of the issues I was aware of sorted out for 15.1, and I feel much better about 15.1 than I did about 15.0.</p>



<p class="wp-block-paragraph">Third, I left out a couple of steps for brevity. Most importantly, the systems I converted were all on ZFS (eight jails and their host, as previously mentioned) which allowed me to take a snapshot of the root filesystem (which in a standard FreeBSD install includes <code>/var</code> and <code>/usr/local</code>) so if something had gone wrong I could simply have reverted to that, or rebooted to the boot environment that <code>freebsd-update</code> created when it upgraded my system to 15.1.</p>



<p class="wp-block-paragraph">My case is also atypical because I have my own package repositories, including for packaged base. I converted the host to packaged base using the official <code>FreeBSD-base</code> repository first, then switched to my own before running <code>pkg upgrade -fy</code>; I then converted the jails directly to my own repository without passing through <code>FreeBSD-base</code>. This is somewhat risky because my base packages are built with non-standard options and do not match FreeBSD distribution sets perfectly, but I know exactly where they differ and how to deal with it.</p>



<p class="wp-block-paragraph">Assuming your system meets the prerequisites (recently updated binary install of 15.0 or 15.1), the worst thing that can happen is that you forget to install a set and end up with unregistered files (e.g. you had <code>tests.txz</code> installed on your system but left out <code>FreeBSD-set-tests</code> from your <code>pkg install --register-only</code> command line). This is easily remedied, even after the fact, by registering that set and then removing it:</p>



<pre class="wp-block-preformatted"># pkg install --register-only -y FreeBSD-set-tests<br># pkg remove -fy FreeBSD-set-tests<br># pkg autoremove -y</pre>



<p class="wp-block-paragraph">But watch out! <code>FreeBSD-set-tests</code> depends on <code>FreeBSD-set-base</code> which depends on <code>FreeBSD-set-minimal</code> and <code>FreeBSD-set-optional</code>, so if you had already trimmed your system down to e.g. <code>FreeBSD-set-minimal-jail</code> you will have to remove those extra sets again:</p>



<pre class="wp-block-preformatted"># pkg remove -fy FreeBSD-set-{base,minimal,optional}<br># pkg autoremove -y</pre>



<p class="wp-block-paragraph">Since we used <code>--register-only</code>, one thing that <em>can&#8217;t</em> happen is that <code>pkg</code> replaces a modified configuration file with its stock version, saving the modified version with a <code>.pkgsave</code> extension. On the other hand, it is possible that <code>pkg upgrade -fy</code> fails to install a file because a directory of the same name exists. I&#8217;ve had that happen exactly once due to a discrepancy in <code>/usr/src</code> (I&#8217;m not sure why but <code>freebsd-update(8)</code> has never been entirely reliable when it came to patching the source tree). So you may want to run the following after converting:</p>



<pre class="wp-block-preformatted"># find -xs / -name '*.pkgnew'</pre>



<p class="wp-block-paragraph">If you get any hits, there will usually be an empty directory of the same name (without the <code>.pkgnew</code> suffix) which you can remove before manually renaming the file.</p>



<p class="wp-block-paragraph">Another useful post-conversion command is:</p>



<pre class="wp-block-preformatted"># find -xs / \( -name var -prune \) -or -not -type d -print0 |<br>    xargs -0 pkg which 2&gt;&amp;1 | grep 'not found' | less</pre>



<p class="wp-block-paragraph">This will give you a list of files on the root filesystem which <code>pkg</code> does not know about. You should be able to identify most of them (configuration files, the trust store, miscellaneous generated files such as <code>/etc/spwd.db</code>).</p>



<p class="wp-block-paragraph">Finally, look for empty directories on the root filesystem:</p>



<pre class="wp-block-preformatted"># find -xs / -type d -empty</pre>



<p class="wp-block-paragraph">There will usually be a few in <code>/usr/lib/debug</code> and <code>/usr/tests</code> which you can remove if you did not choose to install debugging symbols or tests.</p>



<p class="wp-block-paragraph">And my final piece of advice, if you want minimum hassle at the cost of having the machine do some pointless work that immediately gets reverted, just register <em>all</em> the sets, then remove the ones you don&#8217;t have or don&#8217;t want. You&#8217;ll get errors from <code>autoremove</code> about missing files, but that (and the few dozen extra seconds the process will take) is about the only downside.</p>



<p class="wp-block-paragraph"></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.des.no/2026/06/pkgbase-what-can-go-wrong/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>pkgbasify</title>
		<link>https://blog.des.no/2026/06/pkgbasify/</link>
					<comments>https://blog.des.no/2026/06/pkgbasify/#respond</comments>
		
		<dc:creator><![CDATA[Dag-Erling Smørgrav]]></dc:creator>
		<pubDate>Mon, 15 Jun 2026 17:57:10 +0000</pubDate>
				<category><![CDATA[English]]></category>
		<category><![CDATA[FreeBSD]]></category>
		<category><![CDATA[tech]]></category>
		<guid isPermaLink="false">https://blog.des.no/?p=1505</guid>

					<description><![CDATA[How to easily convert your FreeBSD 15 system to packaged base]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">I just spent the day catching up on FreeBSD email and events after a week of marshaling, and upgrading various systems to FreeBSD 15.1. Most of my various systems (servers, VMs, and jails) are still running 14.3 or 14.4 because, in my opinion, 15.0 shipped with too many unresolved warts, but now that 15.1 is out (albeit not yet announced) it is high time to not only upgrade everything to 15.1 but also make the switch to packaged base (which I was so far only using on one VM and one jail).</p>



<p class="wp-block-paragraph">After a brief look at the FreeBSD Foundation&#8217;s pkgbasify script I came to the conclusion that I do not trust it to work correctly, so I developed my own method for converting a system from distribution sets to packaged base.</p>



<span id="more-1505"></span>



<p class="wp-block-paragraph">Assuming a full install (including debug symbols, source tree, and tests) of FreeBSD 15.0-RELEASE or 15.1-RELEASE with pkg 2.7.5 recently updated to the latest patch level (if any), you can convert to packaged base with a single command:</p>



<pre class="wp-block-preformatted"># pkg install -r FreeBSD-base --register-only FreeBSD-set-{base,lib32,kernels}{,-dbg} FreeBSD-set-{src,tests}</pre>



<p class="wp-block-paragraph">Note 1: I&#8217;m assuming that you are using bash or zsh or some other shell that supports curly brace notation; FreeBSD&#8217;s <code>/bin/sh</code> does not.</p>



<p class="wp-block-paragraph">Note 2: the <code>pkg-install(8)</code> manual page claims that you can abbreviate <code>--register-only</code> to <code>-X</code>, but you can&#8217;t, although that will be <a href="https://github.com/freebsd/pkg/pull/2701">fixed</a> in the next version.</p>



<p class="wp-block-paragraph">There may be minor discrepancies between what the installer and <code>freebsd-update(8)</code> produced and what the packages contain, which you can usually fix with a forced upgrade:</p>



<pre class="wp-block-preformatted"># pkg upgrade -r FreeBSD-base -fy</pre>



<p class="wp-block-paragraph">If you do not have a full install, you should trim down the <code>pkg install</code> command line to only the sets that correspond to what you have; otherwise, the subsequent <code>pkg upgrade</code> will install what was missing. Particularly, you should not install <code>FreeBSD-set-src</code> if <code>/usr/src</code> is already managed by Git.</p>



<p class="wp-block-paragraph">Once you&#8217;re done, you can start trimming down your system by removing sets you don&#8217;t need, then autoremoving their contents. For instance, if you&#8217;ve decided that you no longer need tests or debugging symbols:</p>



<pre class="wp-block-preformatted"># pkg remove -fg FreeBSD-set-\*-dbg FreeBSD-set-tests<br># pkg autoremove</pre>



<p class="wp-block-paragraph">Note that package sets are marked vital so you <em>must</em> use <code>-f</code> when removing them.</p>



<p class="wp-block-paragraph">Now is the time to enable the <code>FreeBSD-base</code> repository, by the way. Manually specifying it with <code>-r FreeBSD-base</code> temporarily enables it for the current command, but you&#8217;ll want it permanently enabled:</p>



<pre class="wp-block-preformatted"># mkdir -p /usr/local/etc/pkg/repos<br># echo 'FreeBSD-base: { enabled: yes }' &gt;/usr/local/etc/pkg/repos/FreeBSD-base.conf</pre>



<p class="wp-block-paragraph">Finally, if on bare metal or a VM, create a boot environment of your converted system:</p>



<pre class="wp-block-preformatted"># bectl create $(pkg query %v FreeBSD-runtime)</pre>



<p class="wp-block-paragraph">The only issue I&#8217;ve noticed after converting one bare-metal server and the eight jails it hosts is that <code>pkg leaf</code> does not take shared library dependencies into account:</p>



<pre class="wp-block-preformatted"># sudo pkg -j myjail leaf<br>FreeBSD-bluetooth-lib-15.1<br>FreeBSD-set-base-jail-15.1<br>FreeBSD-ufs-lib-15.1<br>FreeBSD-zfs-lib-15.1<br>pkg-2.7.5</pre>



<p class="wp-block-paragraph">Those three <code>-lib</code> packages provide libraries which are used by other base packages, but the dependencies are all implicit, so they show up as leaves despite not actually being removable.</p>



<p class="wp-block-paragraph">In closing, I would like to thank Baptiste Daroussin and Lexi Winter for their suggestions while I was working out how I was going to do this, and to Emmanuel Vadot for implementing the <code>--register-only</code> option.</p>



<p class="wp-block-paragraph">Addendum: <a href="https://blog.des.no/2026/06/pkgbase-what-can-go-wrong/" data-type="post" data-id="1513">follow-up</a></p>



<p class="wp-block-paragraph"></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.des.no/2026/06/pkgbasify/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>I did a thing</title>
		<link>https://blog.des.no/2026/03/i-did-a-thing/</link>
					<comments>https://blog.des.no/2026/03/i-did-a-thing/#respond</comments>
		
		<dc:creator><![CDATA[Dag-Erling Smørgrav]]></dc:creator>
		<pubDate>Sat, 14 Mar 2026 16:27:42 +0000</pubDate>
				<category><![CDATA[English]]></category>
		<category><![CDATA[vroom]]></category>
		<guid isPermaLink="false">https://blog.des.no/?p=1474</guid>

					<description><![CDATA[This afternoon, I graduated from “has not yet owned an Alfa Romeo” to “currently owns an Alfa Romeo”.]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Anyone who knows me will tell you I&#8217;m a car guy. And any car guy (as opposed to a Porsche guy or a Corvette guy or a Miata guy) will tell you that every car guy ought to <em>have owned</em> an Alfa Romeo. The problem is that in order to <em>have owned</em> an Alfa Romeo, you must first <em>own</em> an Alfa Romeo; and then, presumably, either you get rid of it or it gets rid of you, or you both get rid of each other. And until today, I had <em>not yet owned</em> an Alfa Romeo.</p>



<p class="wp-block-paragraph">This afternoon, I graduated from “has not yet owned an Alfa Romeo” to “currently owns an Alfa Romeo”. Specifically, a 2007 Alfa Romeo 147 1.6&nbsp;TS. At some point in the future, I will move on from “currently owns an Alfa Romeo” to “has owned an Alfa Romeo”, thereby completing my car guy journey; but that will take a lot of work and a bit of money, although in theory I should be able to flip it for a decent profit.</p>



<p class="wp-block-paragraph">Yes, it&#8217;s <a href="https://en.wikipedia.org/wiki/List_of_international_auto_racing_colours#Major_competitors" data-type="link" data-id="https://en.wikipedia.org/wiki/List_of_international_auto_racing_colours#Major_competitors">red</a>, and yes, it has little Italian flags all over.</p>



<p class="wp-block-paragraph">Currently planned work: </p>



<ul class="wp-block-list">
<li>Install “24h Le Mans” sticker on trunk lid for immediate 5 bhp boost</li>



<li>Change all fluids and filters</li>



<li>Replace rear wiper blade</li>



<li>Polish headlights</li>



<li>Investigate lifter tick</li>



<li>Replace clutch pump and / or follower and / or hydraulic line</li>



<li>Replace passenger side window regulator</li>



<li>Replace driver side window and mirror controls</li>



<li>Replace trunk lid lock actuator</li>



<li>Fix driver&#8217;s seat release</li>



<li>Fix or replace various bits of interior trim</li>



<li>Replace gear shift lever knob, possibly with a shorter one</li>



<li>Replace whip antenna with either bee sting or shark fin</li>
</ul>



<p class="wp-block-paragraph">Maybe I&#8217;ll even remember to post updates.</p>



<p class="wp-block-paragraph"><strong>Update:</strong> 5 bhp boost unlocked</p>



<figure class="wp-block-image size-large"><img fetchpriority="high" decoding="async" width="1024" height="771" src="https://blog.des.no/wp-content/uploads/2026/03/PXL_20260314_171206340-1024x771.jpg" alt="Close-up of the trunk lid of a red Alfa Romeo 147 1.6 TS sporting a white decal showing the outline of the Circuit de la Sarthe with the text “24h Le Mans”." class="wp-image-1483" srcset="https://blog.des.no/wp-content/uploads/2026/03/PXL_20260314_171206340-1024x771.jpg 1024w, https://blog.des.no/wp-content/uploads/2026/03/PXL_20260314_171206340-300x226.jpg 300w, https://blog.des.no/wp-content/uploads/2026/03/PXL_20260314_171206340-150x113.jpg 150w, https://blog.des.no/wp-content/uploads/2026/03/PXL_20260314_171206340-768x578.jpg 768w, https://blog.des.no/wp-content/uploads/2026/03/PXL_20260314_171206340-1536x1157.jpg 1536w, https://blog.des.no/wp-content/uploads/2026/03/PXL_20260314_171206340-2048x1542.jpg 2048w, https://blog.des.no/wp-content/uploads/2026/03/PXL_20260314_171206340-1200x904.jpg 1200w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></figure>



<p class="wp-block-paragraph"><strong>Update:</strong> <em>of course</em> my Italian car has electrical gremlins.</p>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="771" src="https://blog.des.no/wp-content/uploads/2026/03/PXL_20260314_175426846-1024x771.jpg" alt="Inside view of the raised trunk lid of my Alfa Romeo 147 with the lining removed. The trunk lock is disconnected and black and red multimeter probes are inserted into the plug. I am holding the multimeter in my left hand; it is set to 20 V and the display is showing12.04." class="wp-image-1485" srcset="https://blog.des.no/wp-content/uploads/2026/03/PXL_20260314_175426846-1024x771.jpg 1024w, https://blog.des.no/wp-content/uploads/2026/03/PXL_20260314_175426846-300x226.jpg 300w, https://blog.des.no/wp-content/uploads/2026/03/PXL_20260314_175426846-150x113.jpg 150w, https://blog.des.no/wp-content/uploads/2026/03/PXL_20260314_175426846-768x578.jpg 768w, https://blog.des.no/wp-content/uploads/2026/03/PXL_20260314_175426846-1536x1157.jpg 1536w, https://blog.des.no/wp-content/uploads/2026/03/PXL_20260314_175426846-2048x1542.jpg 2048w, https://blog.des.no/wp-content/uploads/2026/03/PXL_20260314_175426846-1200x904.jpg 1200w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></figure>



<p class="wp-block-paragraph"><strong>Update 2026-03-16:</strong> I had low washer nozzle pressure and assumed the pump might need changing. Only after ordering a replacement pump from a breaker did I realize that the real issue was that the washer hose was getting pinched when I closed the hood. Cutting the cable ties that tied it to the hood strut solved the issue.</p>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="771" src="https://blog.des.no/wp-content/uploads/2026/03/PXL_20260316_150449793-1024x771.jpg" alt="View of the front of a red Alfa Romeo 147 from right above / next to the passenger window. The hood is open and there are traces of washer fluid on it. A multimeter is propped up against the hood so that it is visible from the driver's seat. A ratchet is lying on top of the engine, which is visible through the gap between the rear edge of the open hood and the body." class="wp-image-1493" srcset="https://blog.des.no/wp-content/uploads/2026/03/PXL_20260316_150449793-1024x771.jpg 1024w, https://blog.des.no/wp-content/uploads/2026/03/PXL_20260316_150449793-300x226.jpg 300w, https://blog.des.no/wp-content/uploads/2026/03/PXL_20260316_150449793-150x113.jpg 150w, https://blog.des.no/wp-content/uploads/2026/03/PXL_20260316_150449793-768x578.jpg 768w, https://blog.des.no/wp-content/uploads/2026/03/PXL_20260316_150449793-1536x1157.jpg 1536w, https://blog.des.no/wp-content/uploads/2026/03/PXL_20260316_150449793-2048x1542.jpg 2048w, https://blog.des.no/wp-content/uploads/2026/03/PXL_20260316_150449793-1200x904.jpg 1200w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></figure>



<p class="wp-block-paragraph"><strong>Update 2026-03-19:</strong> It passed inspection today, with a slew of minor defects but little I wasn&#8217;t already aware of and nothing I can&#8217;t fix. </p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.des.no/2026/03/i-did-a-thing/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>What year is it, NUUG?</title>
		<link>https://blog.des.no/2024/07/what-year-is-it-nuug/</link>
					<comments>https://blog.des.no/2024/07/what-year-is-it-nuug/#respond</comments>
		
		<dc:creator><![CDATA[Dag-Erling Smørgrav]]></dc:creator>
		<pubDate>Fri, 12 Jul 2024 16:18:14 +0000</pubDate>
				<category><![CDATA[English]]></category>
		<category><![CDATA[Unix]]></category>
		<category><![CDATA[wtf]]></category>
		<guid isPermaLink="false">https://blog.des.no/?p=1435</guid>

					<description><![CDATA[The Norwegian Unix User Group is celebrating its 40th anniversary on August 10. I was invited to speak at the event and initially accepted, but after learning of the schedule for the event, which was not communicated to me at the time, I have decided to withdraw.]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">The <a href="https://nuug.no/" class="ek-link">Norwegian Unix User Group</a> was founded in 1984, and is celebrating its 40th anniversary on August 10.  A short while ago, I was approached by a member of the organizing team (whom I shall not name) and asked to speak at the event as a representative of the Norwegian BSD community.  I was given no information about the event beyond what was expected of me (a 30-minute presentation on the topic of my choice) and the names of some of the other speakers. After some hesitation, as I was having a hard time coming up with a topic that I felt would fit the occasion, I initially accepted.</p>



<p class="wp-block-paragraph">One thing I found odd was that <a href="https://nuug.no/adict/" class="ek-link">NUUG&#8217;s own event calendar</a> (<a href="https://archive.is/t67XT" class="ek-link">archive</a>) has no information about the event beyond a time and a place. I get that the list of speakers is not yet finalized, even though there&#8217;s less than a month to go, but there is literally nothing beyond “more information to come”. All the links just point back to the same page.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="640" height="545" src="https://blog.des.no/wp-content/uploads/2024/07/image-3.png" alt="" class="wp-image-1439" srcset="https://blog.des.no/wp-content/uploads/2024/07/image-3.png 640w, https://blog.des.no/wp-content/uploads/2024/07/image-3-300x255.png 300w, https://blog.des.no/wp-content/uploads/2024/07/image-3-150x128.png 150w" sizes="auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 984px) 61vw, (max-width: 1362px) 45vw, 600px" /><figcaption class="wp-element-caption">Screenshot of NUUG&#8217;s event calendar as of 2024-07-12</figcaption></figure>
</div>


<p class="wp-block-paragraph">This morning, someone pointed out to me that there is a <a href="https://www.letsreg.com/no/register/NUUG40ar#/" class="ek-link">registration page</a> (<a href="https://archive.is/zgT5a" class="ek-link">archive</a>) for the event (which, again, NUUG&#8217;s own website does not link to or even mention!) with extensive information about the event. And that information&#8230; is not good.</p>


<div class="wp-block-image">
<figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="420" height="1024" src="https://blog.des.no/wp-content/uploads/2024/07/image-4-420x1024.png" alt="Screenshot of a portion of the registration page for NUUG's 40th anniversary celebration, which includes the finale of Miss Norway 2024 and an opportunity to take photos with the contestants." class="wp-image-1440" srcset="https://blog.des.no/wp-content/uploads/2024/07/image-4-420x1024.png 420w, https://blog.des.no/wp-content/uploads/2024/07/image-4-123x300.png 123w, https://blog.des.no/wp-content/uploads/2024/07/image-4-61x150.png 61w, https://blog.des.no/wp-content/uploads/2024/07/image-4.png 556w" sizes="auto, (max-width: 420px) 85vw, 420px" /><figcaption class="wp-element-caption">Screenshot of a portion of the registration page as of 2024-07-12</figcaption></figure>
</div>


<p class="wp-block-paragraph">tl;dr: the event is collocated with the Miss Norway 2024 finals and attendees are promised opportunities to have their pictures taken with the winners and runners-up.</p>



<p class="wp-block-paragraph">WHAT THE EVERLOVING FUCK, NUUG?</p>



<p class="wp-block-paragraph">It goes without saying that I will not be speaking at this event. I will try to turn my presentation (which I&#8217;d only outlined, not written yet) into a blog post, but no promises. It would have been a reflection on what “Unix” actually means (beyond the simple fact of the trademark) and how that has changed over the years.</p>



<p class="wp-block-paragraph">If you&#8217;re a member (and perhaps even if you&#8217;re not), I encourage you to <a href="https://www.nuug.no/kontakt.shtml" class="ek-link">contact NUUG</a> and let them know your thoughts on this matter.</p>



<p class="wp-block-paragraph"><em>EDIT: I have written to NUUG to ask them to either change their plans for the event, in which case I will be happy to attend and speak, or cancel my membership. I will update this post again when (if) they respond.</em></p>



<p class="wp-block-paragraph"><em>EDIT 2024-08-07: I have yet to receive an official response from NUUG. I&#8217;ve been told out-of-band that my email has been received and my membership canceled, but I appear to still be on the mailing list. In the meantime, Norwegian magazine kode24 has written <a href="https://www.kode24.no/artikkel/nuug-feirer-bursdag-med-miss-norway-show-kvalmt/81769594">a piece on the topic</a>, citing <a href="https://twitter.com/desdotdev/status/1811798917551476951">my tweet</a> and this blog post, which kicked up a bit of a fuss on Twitter. Knut Yrvin chose to respond directly to my month-old tweet with <a href="https://twitter.com/Knut_Yrvin/status/1821107730960052557">a strawman</a> and <a href="https://twitter.com/Knut_Yrvin/status/1821109610217976062">insults</a> while Malin Bruland rode to his defense with <a href="https://twitter.com/malinkbruland/status/1821137070884094320">the same strawman</a>. I am not impressed.</em> </p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.des.no/2024/07/what-year-is-it-nuug/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>DNS over TLS in FreeBSD with Quad9</title>
		<link>https://blog.des.no/2023/06/dns-over-tls-in-freebsd-with-quad9/</link>
					<comments>https://blog.des.no/2023/06/dns-over-tls-in-freebsd-with-quad9/#respond</comments>
		
		<dc:creator><![CDATA[Dag-Erling Smørgrav]]></dc:creator>
		<pubDate>Tue, 13 Jun 2023 18:26:03 +0000</pubDate>
				<category><![CDATA[English]]></category>
		<category><![CDATA[DNS]]></category>
		<category><![CDATA[FreeBSD]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[tech]]></category>
		<category><![CDATA[Unbound]]></category>
		<guid isPermaLink="false">https://blog.des.no/?p=1426</guid>

					<description><![CDATA[It has come to my attention that Quad9 have a blog post providing incorrect instructions for how to set up a FreeBSD system to use their service. I have attempted to get in touch with the author and get him to correct it but have received no response. So here, for the benefit of the &#8230; <a href="https://blog.des.no/2023/06/dns-over-tls-in-freebsd-with-quad9/" class="more-link">Continue reading<span class="screen-reader-text"> "DNS over TLS in FreeBSD with Quad9"</span></a>]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">It has come to my attention that Quad9 have a blog post providing incorrect instructions for how to set up a FreeBSD system to use their service. I have attempted to get in touch with the author and get him to correct it but have received no response. So here, for the benefit of the Great Search Engine Gods, is the correct procedure; see <a href="/2018/10/dns-over-tls-in-freebsd-12" class="ek-link">my earlier post on the topic</a> for more details on how it works.</p>



<pre class="wp-block-preformatted"># cat >/etc/rc.conf.d/local_unbound &lt;&lt;EOF
local_unbound_enable="yes"
local_unbound_tls="yes"
local_unbound_forwarders="9.9.9.9@853#dns.quad9.net 149.112.112.112@853#dns.quad9.net 2620:fe::fe@853#dns.quad9.net 2620:fe::9@853#dns.quad9.net"
EOF
# service local_unbound setup
# service local_unbound restart</pre>



<p class="wp-block-paragraph">No need to reboot.</p>



<p class="wp-block-paragraph">Note that if you only have IPv4, you may experience slightly degraded performance unless you leave out the IPv6 addresses from the <code>local_unbound_forwarders</code> line (and vice versa in the unlikely scenario where you only have IPv6).</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.des.no/2023/06/dns-over-tls-in-freebsd-with-quad9/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Automatic Let&#8217;s Encrypt certificates in Apache with mod_md</title>
		<link>https://blog.des.no/2021/10/lets-encrypt-apache-mod-md/</link>
					<comments>https://blog.des.no/2021/10/lets-encrypt-apache-mod-md/#respond</comments>
		
		<dc:creator><![CDATA[Dag-Erling Smørgrav]]></dc:creator>
		<pubDate>Sun, 10 Oct 2021 18:19:35 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[FreeBSD]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[tech]]></category>
		<guid isPermaLink="false">https://blog.des.no/?p=1385</guid>

					<description><![CDATA[Since 2.4.30, Apache comes with experimental support for ACME certificates (Let&#8217;s Encrypt et al.) in the form of mod_md (short for “managed domains”). It&#8217;s kind of a pain but it&#8217;s still better than what I had before, i.e. a mess of shell and Perl scripts based on Crypt::LE, and if your use case is limited &#8230; <a href="https://blog.des.no/2021/10/lets-encrypt-apache-mod-md/" class="more-link">Continue reading<span class="screen-reader-text"> "Automatic Let&#8217;s Encrypt certificates in Apache with mod_md"</span></a>]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Since 2.4.30, Apache comes with experimental support for ACME certificates (<a href="https://letsencrypt.org/" class="ek-link">Let&#8217;s Encrypt</a> et al.) in the form of <a href="https://httpd.apache.org/docs/trunk/mod/mod_md.html" class="ek-link">mod_md</a> (short for “managed domains”). It&#8217;s kind of a pain but it&#8217;s still better than what I had before, i.e. a mess of shell and Perl scripts based on <a href="https://metacpan.org/pod/Crypt::LE" class="ek-link">Crypt::LE</a>, and if your use case is limited to Apache, it appears to be simpler than <a href="https://certbot.eff.org/" class="ek-link">Certbot</a> as well. Unfortunately for me, it&#8217;s not very well documented and I wasted a considerable amount of time figuring out how to use it. Fortunately for you, I then decided to blog about it so you don&#8217;t have to repeat my mistakes.</p>



<p class="wp-block-paragraph"><em>Edit: the author of mod_md, Stefan Eissing, got in touch and pointed me to <a href="https://github.com/icing/mod_md" class="ek-link">his own documentation</a>, which is far superior to the one available from Apache.</em> </p>



<span id="more-1385"></span>



<p class="wp-block-paragraph">My starting point is a freshly installed <a href="https://www.freebsd.org/releases/13.0R/" class="ek-link">FreeBSD 13.0</a> server with Apache 2.4, but this isn&#8217;t really OS dependent.</p>



<p class="wp-block-paragraph">First, you will need mod_ssl (of course) and a session cache, and you will need to tweak the TLS parameters, as the defaults are <a href="https://wiki.mozilla.org/Security/Server_Side_TLS" class="ek-link">far from fine</a>.</p>



<pre id="block-21da00d1-1b56-4c10-aa5c-26223f5a84e5" class="wp-block-preformatted has-small-font-size">LoadModule ssl_module libexec/apache24/mod_ssl.so
SSLProtocol +TLSv1.3 +TLSv1.2
SSLCipherSuite TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
SSLHonorCipherOrder off
SSLCompression off

LoadModule socache_dbm_module libexec/apache24/mod_socache_dbm.so
SSLSessionCache dbm:/var/db/httpd_ssl_cache.db</pre>



<p class="wp-block-paragraph">You will also need to load mod_md, of course, and mod_watchdog, which mod_md needs to function.</p>



<pre class="wp-block-preformatted has-small-font-size">LoadModule watchdog_module libexec/apache24/mod_watchdog.so
LoadModule md_module libexec/apache24/mod_md.so
MDCertificateAgreement accepted
MDContactEmail acme@example.com</pre>



<p class="wp-block-paragraph">The <code>MDCertificateAgreement</code> directive indicates that you have read and accepted <a href="https://letsencrypt.org/repository/" class="ek-link">Let&#8217;s Encrypt&#8217;s subscriber agreement</a>, while <code>MDContactEmail</code> is the email address that you used to sign up to Let&#8217;s Encrypt.</p>



<p class="wp-block-paragraph">You will also need mod_rewrite to redirect HTTP requests to HTTPS and mod_headers for HSTS.</p>



<pre class="wp-block-preformatted has-small-font-size">LoadModule rewrite_module libexec/apache24/mod_rewrite.so
LoadModule headers_module libexec/apache24/mod_headers.so</pre>



<p class="wp-block-paragraph">By default, Apache only listens on port 80, so you&#8217;ll need an extra <code>Listen</code> directive for port 443.</p>



<pre class="wp-block-preformatted has-small-font-size">Listen 443</pre>



<p class="wp-block-paragraph">And as always with Apache, you should probably set <code>ServerName</code> and <code>ServerAdmin</code> to sensible values.</p>



<pre class="wp-block-preformatted has-small-font-size">ServerName server.example.com
ServerAdmin www@example.com</pre>



<p class="wp-block-paragraph">Next, set up an HTTP-only virtual host that you can use to check the status of mod_md.</p>



<pre class="wp-block-preformatted has-small-font-size">&lt;VirtualHost *:80&gt;
  ServerName localhost
  &lt;Location /&gt;
    Require ip 127.0.0.1/8 ::1
  &lt;/Location&gt;
  &lt;Location "/md-status"&gt;
    SetHandler md-status
  &lt;/Location&gt;
&lt;/VirtualHost&gt;</pre>



<p class="wp-block-paragraph">(Once Apache is running, you will be able to query it at any time as  <a href="http://localhost/md-status" class="ek-link">http://localhost/md-status</a>.)</p>



<p class="wp-block-paragraph">On to the actual website. First, you need to tell mod_md to manage certificates for it.</p>



<pre id="block-766690c3-84a9-4000-a0e9-a7f4d230a658" class="wp-block-preformatted has-small-font-size">MDomain site.example.com</pre>



<p class="wp-block-paragraph">Next, set up a redirect from HTTP to HTTPS for everything except ACME challenge tokens.</p>



<pre class="wp-block-preformatted has-small-font-size">&lt;VirtualHost localhost:80&gt;
  ServerName site.example.com
  RewriteEngine on
  RewriteRule "^/(?!.well-known/acme-challenge)(.*)" https://site.example.com/$1 [R=301,L]
  ErrorLog /www/site.example.com/logs/http-error.log
  CustomLog /www/site.example.com/logs/http-access.log combined
&lt;/VirtualHost&gt;</pre>



<p class="wp-block-paragraph">And finally, the site itself, including HSTS and <a href="/2020/11/configuring-strict-sni-with-apache-httpd-2-4/" class="ek-link">strict SNI</a>:</p>



<pre id="block-766690c3-84a9-4000-a0e9-a7f4d230a658" class="wp-block-preformatted has-small-font-size">&lt;VirtualHost *:443&gt;
  ServerName site.example.com
  SSLEngine on
  SSLStrictSNIVHostCheck On
  Header always set Strict-Transport-Security "max-age=15552000; includeSubdomains;"
  DocumentRoot /www/site.example.com/data
  IncludeOptional /www/site.example.com/etc/*.conf
  ErrorLog /www/site.example.com/logs/https-error.log
  CustomLog /www/site.example.com/logs/https-access.log combined
&lt;/VirtualHost&gt;</pre>



<p class="wp-block-paragraph">Now start Apache and monitor the error log. You should see something like this pretty quickly:</p>



<pre class="wp-block-preformatted has-small-font-size">[Sun Oct 10 16:15:27.450401 2021] [md:notice] [pid 12345] AH10059: The Managed Domain site.example.com has been setup and changes will be activated on next (graceful) server restart.</pre>



<p class="wp-block-paragraph">Once you do as it says (<code>apachectl graceful</code>), your site will be up and running and you can head over to the <a href="https://www.ssllabs.com/ssltest/index.html" class="ek-link">Qualys SSL Server Test</a> and admire your solid A+.</p>



<p class="wp-block-paragraph"><em>Download <a href="/wp-content/uploads/2021/10/apache-md-example.txt" class="ek-link">the sample configuration</a> and try it out yourself.</em></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.des.no/2021/10/lets-encrypt-apache-mod-md/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Configuring strict SNI with Apache httpd 2.4</title>
		<link>https://blog.des.no/2020/11/configuring-strict-sni-with-apache-httpd-2-4/</link>
					<comments>https://blog.des.no/2020/11/configuring-strict-sni-with-apache-httpd-2-4/#respond</comments>
		
		<dc:creator><![CDATA[Dag-Erling Smørgrav]]></dc:creator>
		<pubDate>Mon, 09 Nov 2020 22:40:36 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">https://blog.des.no/?p=1357</guid>

					<description><![CDATA[Imagine the following scenario: Your web server hosts both www.example.com and www.example.net using Apache httpd with name-based virtual hosts, and the configuration is structured such that httpd sees the former before the latter. Each vhost has its own non-wildcard certificate. A user tries to access www.example.net using an old browser which does not support SNI. &#8230; <a href="https://blog.des.no/2020/11/configuring-strict-sni-with-apache-httpd-2-4/" class="more-link">Continue reading<span class="screen-reader-text"> "Configuring strict SNI with Apache httpd 2.4"</span></a>]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Imagine the following scenario:</p>



<ol class="wp-block-list"><li>Your web server hosts both <code>www.example.com</code> and <code>www.example.net</code> using Apache httpd with name-based virtual hosts, and the configuration is structured such that httpd sees the former before the latter. Each vhost has its own non-wildcard certificate.</li><li>A user tries to access <code>www.example.net</code> using an old browser which does not support SNI.</li><li>Since httpd cannot see the <code>Host</code> header without first performing a TLS handshake, and cannot perform a TLS handshake without a key and certificate, it needs to pick one blindly. In accordance with its <a href="https://httpd.apache.org/docs/2.4/vhosts/details.html" class="ek-link">virtual host matching algorithm</a>, it defaults to the first configured vhost, i.e. <code>www.example.com</code>.</li><li>The browser receives a certificate wit a CN which does not match the name of the host it is trying to access, and either throws up a scary warning or simply refuses to connect.</li></ol>



<p class="wp-block-paragraph">You might say that this acceptable — after all, it only affects a minuscule proportion of users using very old clients — but TLS validators such as <a href="https://www.ssllabs.com/ssltest/index.html" class="ek-link">Qualys SSL labs</a> have started testing non-SNI requests, and while they don&#8217;t yet penalize servers for this issue, they might very well start doing so soon.</p>



<p class="wp-block-paragraph">Apache httpd has an option called <code><a href="https://httpd.apache.org/docs/2.4/mod/mod_ssl.html#sslstrictsnivhostcheck" class="ek-link">SSLStrictSNIVHostCheck</a></code> which, in theory, should take care of this. But I haven&#8217;t had much luck with it (to put it bluntly: it does not seem to have any effect at all), and it appears from various discussions on Reddit, StackExchange, etc. that I am not alone. The solution I have found is to create a dummy vhost with a dummy, self-signed certificate, and ensure that it is loaded first.</p>



<p class="wp-block-paragraph">The first step is to create a dummy certificate for  <code>localhost</code> with a 100-year lifespan (unless you feel like setting up a cron job that regenerates a 90-day certificate every 30 days or so):</p>



<pre class="wp-block-preformatted">$ openssl genrsa -out localhost.key 2048
$ openssl req -new -key localhost.key -subj /CN=localhost -out localhost.csr
$ echo subjectAltName=DNS:localhost | openssl x509 \
    -in localhost.csr -out localhost.crt -req -signkey localhost.key -days 36525 -extfile -
<a rel="noreferrer noopener" href="https://blog.des.no/#facebook" target="_blank"></a></pre>



<p class="wp-block-paragraph">Next, create a vhost configuration which uses that certificate:</p>



<pre class="wp-block-preformatted">&lt;VirtualHost *:443>
  ServerName localhost
  SSLEngine On
  SSLStrictSNIVHostCheck On
  SSLCertificateKeyFile /path/to/localhost.key
  SSLCertificateFile /path/to/localhost.crt
  &lt;Location />
    Require all denied
  &lt;/Location>
&lt;/VirtualHost></pre>



<p class="wp-block-paragraph">This must be placed in a location where it will be read before any other vhost configuration, e.g. <code>00localhost.conf</code> in your server&#8217;s <code>Includes</code> directory.</p>



<p class="wp-block-paragraph">TLS connections without a server name will now be directed to your dummy vhost and fail, and Qualys will report that any site hosted on your server “works only in browsers with SNI support”.</p>



<p class="wp-block-paragraph">As a footnote, my TLS configuration (derived from <a href="https://wiki.mozilla.org/Security/Server_Side_TLS" class="ek-link">the Mozilla project&#8217;s recommendations</a>) looks like this:</p>



<pre class="wp-block-preformatted">SSLProtocol +TLSv1.3 +TLSv1.2
SSLCipherSuite TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
SSLHonorCipherOrder off
SSLCompression off</pre>



<p class="wp-block-paragraph">Between that, strict SNI, <a href="https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security" class="ek-link">HSTS</a>, and <a href="https://en.wikipedia.org/wiki/DNS_Certification_Authority_Authorization" class="ek-link">CAA</a>, you will easily achieve an <a href="https://www.ssllabs.com/ssltest/analyze.html?d=blog.des.no" class="ek-link">A+ score</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.des.no/2020/11/configuring-strict-sni-with-apache-httpd-2-4/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>wtf, zsh</title>
		<link>https://blog.des.no/2020/09/wtf-zsh/</link>
					<comments>https://blog.des.no/2020/09/wtf-zsh/#comments</comments>
		
		<dc:creator><![CDATA[Dag-Erling Smørgrav]]></dc:creator>
		<pubDate>Tue, 22 Sep 2020 13:11:22 +0000</pubDate>
				<category><![CDATA[English]]></category>
		<category><![CDATA[tech]]></category>
		<category><![CDATA[wtf]]></category>
		<guid isPermaLink="false">https://blog.des.no/?p=1333</guid>

					<description><![CDATA[wtf, zsh]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">wtf, zsh</p>



<pre class="wp-block-preformatted">% uname -sr
FreeBSD 12.1-RELEASE-p10
% for sh in sh csh bash zsh ; do printf "%-8s" $sh ; $sh -c 'echo \\x21' ; done 
sh      \x21
csh     \x21
bash    \x21
zsh     !
% cowsay wtf, zsh       
 __________ 
&lt; wtf, zsh &gt;
 ---------- 
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
</pre>



<p class="wp-block-paragraph">I mean. Bruh. I know it&#8217;s intentional &amp; documented &amp; can be turned off, but every other shell defaults to POSIX semantics&#8230;</p>



<p class="wp-block-paragraph">BTW:</p>



<pre class="wp-block-preformatted">% ln -s =zsh /tmp/sh
% /tmp/sh -c 'echo \x21'
\x21</pre>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.des.no/2020/09/wtf-zsh/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Netlink, auditing, and counting bytes</title>
		<link>https://blog.des.no/2020/08/netlink-auditing-and-counting-bytes/</link>
					<comments>https://blog.des.no/2020/08/netlink-auditing-and-counting-bytes/#respond</comments>
		
		<dc:creator><![CDATA[Dag-Erling Smørgrav]]></dc:creator>
		<pubDate>Fri, 21 Aug 2020 16:33:54 +0000</pubDate>
				<category><![CDATA[English]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[tech]]></category>
		<category><![CDATA[wtf]]></category>
		<guid isPermaLink="false">https://blog.des.no/?p=1296</guid>

					<description><![CDATA[In which we find bugs in both the kernel and userspace parts of the Linux audit subsystem.]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">I&#8217;ve been messing around with Linux auditing lately, because of reasons, and ended up having to replicate most of libaudit, because of other reasons, and in the process I found bugs in both the kernel and userspace parts of the Linux audit subsystem.</p>



<span id="more-1296"></span>



<p class="wp-block-paragraph">Let us start with what Netlink is, for readers who aren&#8217;t very familiar with Linux: it is a mechanism for communicating directly with kernel subsystems using the BSD socket API, rather than by opening device nodes or files in a synthetic filesystem such as  <code>/proc</code>. It has pros and cons, but mostly pros, especially as a replacement for <code>ioctl(2)</code>, since Netlink sockets are buffered, can be <code>poll(2)</code>ed, and can more easily accommodate variable-length messages and partial reads.</p>



<p class="has-small-font-size wp-block-paragraph">Note: all links to source code in this post point to the versions used in Ubuntu 18.04 as of 2020-08-21: kernel 5.4, userspace 2.8.2.</p>



<p class="wp-block-paragraph">Netlink messages start with a 16-byte header which looks like this: <sup>(<a class="ek-link ek-link" href="https://github.com/linux-audit/audit-kernel/blob/stable-5.4/include/uapi/linux/netlink.h#L44">source</a>, <a class="ek-link" href="https://man7.org/linux/man-pages/man7/netlink.7.html">man page</a>)</sup></p>



<pre title="<a href=&quot;https://github.com/linux-audit/audit-kernel/blob/stable-5.4/include/uapi/linux/netlink.h#L44&quot;&gt;source</a&gt;" class="wp-block-code"><code lang="c" class="language-c">struct nlmsghdr {
	__u32		nlmsg_len;	/* Length of message including header */
	__u16		nlmsg_type;	/* Message content */
	__u16		nlmsg_flags;	/* Additional flags */
	__u32		nlmsg_seq;	/* Sequence number */
	__u32		nlmsg_pid;	/* Sending process port ID */
};
</code></pre>



<p class="wp-block-paragraph">The same header also provides a few macros to help populate and interpret Netlink messages: <sup>(<a href="https://github.com/linux-audit/audit-kernel/blob/stable-5.4/include/uapi/linux/netlink.h#L89" class="ek-link">source</a>, <a href="https://man7.org/linux/man-pages/man3/netlink.3.html" class="ek-link">man page</a>)</sup></p>



<pre title="<a href=&quot;https://github.com/linux-audit/audit-kernel/blob/stable-5.4/include/uapi/linux/netlink.h#L89&quot;&gt;source</a&gt;" class="wp-block-code"><code lang="c" class="language-c">#define NLMSG_ALIGNTO	4U
#define NLMSG_ALIGN(len) ( ((len)+NLMSG_ALIGNTO-1) &amp; ~(NLMSG_ALIGNTO-1) )
#define NLMSG_HDRLEN	 ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr)))
#define NLMSG_LENGTH(len) ((len) + NLMSG_HDRLEN)
#define NLMSG_SPACE(len) NLMSG_ALIGN(NLMSG_LENGTH(len))
#define NLMSG_DATA(nlh)  ((void*)(((char*)nlh) + NLMSG_LENGTH(0)))
#define NLMSG_NEXT(nlh,len)	 ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \
				  (struct nlmsghdr*)(((char*)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len)))
#define NLMSG_OK(nlh,len) ((len) >= (int)sizeof(struct nlmsghdr) &amp;&amp; \
			   (nlh)->nlmsg_len >= sizeof(struct nlmsghdr) &amp;&amp; \
			   (nlh)->nlmsg_len &lt;= (len))
#define NLMSG_PAYLOAD(nlh,len) ((nlh)->nlmsg_len - NLMSG_SPACE((len)))
</code></pre>



<p class="wp-block-paragraph">Going by these definitions and the documentation, it is clear that the length field of the message header reflects the total length of the message, header included. What is somewhat less clear is that Netlink messages are supposed to be padded out to a multiple of four bytes before transmission or storage.</p>



<p class="wp-block-paragraph">The Linux audit subsystem not only breaks these rules, but does not even agree with itself on precisely <em>how</em> to break them.</p>



<p class="wp-block-paragraph">The userspace tools (<code>auditctl(8)</code>, <code>auditd(8)</code>&#8230;) all use libaudit to communicate with the kernel audit subsystem. When passing a message of length <em><code>size</code> </em>to the kernel, libaudit copies the payload into a large pre-zeroed buffer, sets the type, flags, and sequence number fields to the appropriate values, sets the pid field to zero (which is probably a bad idea but, strictly speaking, permitted), and finally sets the length field to <code>NLMSG_SPACE(<em>size</em>)</code>, which evaluates to <code>sizeof(struct nlmsghdr) + </code><em><code>size</code> </em>rounded up to a multiple of four. It then writes that exact number of bytes to the socket.</p>



<p class="wp-block-paragraph"><strong>Bug #1:</strong> The length field should not be rounded up; the purpose of the <code>NLMSG_SPACE()</code> and <code>NLMSG_NEXT()</code> macros is to ensure proper alignment of subsequent message headers when multiple messages are stored or transmitted consecutively. The length field should be computed using <code>NLMSG_LENGTH()</code>, which simply adds the length of the header to its single argument.</p>



<p class="has-small-font-size wp-block-paragraph">Note: to my understanding, Netlink supports sending multiple messages in a single send / receive provided that they are correctly aligned, that they all have the <code>NLM_F_MULTI</code> flag set, and that the last message in the sequence is a zero-length message of type <code>NLMSG_DONE</code>. The audit subsystem does not use this feature.</p>



<p class="wp-block-paragraph">Moving on: <code>NETLINK_AUDIT</code> messages essentially fall into one of four categories:</p>



<ol class="wp-block-list"><li>Requests from userspace; for instance, an <code>AUDIT_GET</code> message which requests the current status of the audit subsystem, an <code>AUDIT_SET</code> message which changes parameters, or an <code>AUDIT_LIST_RULES</code> message which requests a list of currently active auditing rules.</li><li>Responses from the kernel; these usually have the same type as the request. For instance, the kernel will respond to an <code>AUDIT_GET</code> request with a message of the same type containing a <code>struct audit_status</code>, and to an <code>AUDIT_LIST_RULES</code> request with a sequence of messages of the same type each containing a single <code>struct audit_rule_data</code>.</li><li>Errors and acknowledgements. These use standard Netlink message types: <code>NLMSG_ERROR</code> in response to an invalid request (or a valid request with the <code>NLM_F_ACK</code> flag set), or <code>NLMSG_DONE</code> at the end of a multi-part response.</li><li>Audit data. Every event that matches an auditing rule will trigger a series of messages with varying types: usually one which describes the system call that triggered the event, one each for every file or directory affected by the call, one or more describing the process, etc. Each message consists of a header of the form <code>audit(<em>timestamp</em>:<em>serial</em>):␣</code> which uniquely identifies the event, followed by a space-separated list of key-value pairs. The final message has the type <code>AUDIT_EOE</code> and has the same header, trailing space included, but no data.</li></ol>



<p class="wp-block-paragraph">The kernel pads responses, errors and acknowledgements, but does not include that padding in the length reported in the message header. So far, so good. However&#8230;</p>



<p class="wp-block-paragraph"><strong>Bug #2:</strong> Audit data messages are sent from the kernel without padding.</p>



<p class="wp-block-paragraph">This is not critical, but it does mean that an implementation that batches up incoming messages and stores them consecutively must take extra care to keep them properly aligned.</p>



<p class="wp-block-paragraph"><strong>Bug #3:</strong> The length field on audit data messages does not include the length of the header.</p>



<p class="wp-block-paragraph">This is jaw-dropping. It is so <em>fundamentally</em> wrong. It means that anyone who wants to talk to the audit subsystem using their own code instead of libaudit will have to add a workaround to the Netlink layer of their stack to either fix or ignore the error, and apply that workaround <em>only for certain message types</em>.</p>



<p class="wp-block-paragraph">How has this gone unnoticed? Well, libaudit doesn&#8217;t do much input validation. It relies on the <code>NLMSG_OK()</code> macro, which checks only three things:</p>



<ol class="wp-block-list"><li>That the length of the buffer (as returned by <code>recvfrom(2)</code>, for instance) is no less than the length of a Netlink message header.</li><li>That the length field in the message header is no less than the length of a Netlink message header.</li><li>That the length field in the message header is less than or equal to the length of the buffer.</li></ol>



<p class="wp-block-paragraph">Since every audit data message, even the empty <code>AUDIT_EOE</code> message, begins with a timestamp and serial number, the length of the payload is never less than 25-30 bytes, and <code>NLMSG_OK()</code> is always satisfied. And since the audit subsystem never sends multiple messages in a single send / receive, it does not matter that <code>NLMSG_NEXT()</code> will be off by 16 bytes.</p>



<p class="wp-block-paragraph">Consumers of libaudit don&#8217;t notice either because they never look at the header; libaudit wraps the message in its own <code>struct audit_reply</code> with its own length and type fields and pointers of the appropriate types for messages that contain binary data (this is a bad idea for entirely different reasons which we won&#8217;t go into here). The only case in which the caller needs to know the length of the message is for audit events, when the length field just happens to be the length of the payload, just like the caller expects.</p>



<p class="wp-block-paragraph">The odds of these bugs getting fixed is approximately zero, because existing applications will break in interesting ways if the kernel starts setting the length field correctly.</p>



<p class="wp-block-paragraph">Turing wept.</p>



<p class="wp-block-paragraph"><strong>THIS IS WHY WE CAN&#8217;T HAVE NICE THINGS</strong></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.des.no/2020/08/netlink-auditing-and-counting-bytes/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>On dinosaurs and context</title>
		<link>https://blog.des.no/2020/08/on-dinosaurs-and-context/</link>
					<comments>https://blog.des.no/2020/08/on-dinosaurs-and-context/#respond</comments>
		
		<dc:creator><![CDATA[Dag-Erling Smørgrav]]></dc:creator>
		<pubDate>Sun, 02 Aug 2020 05:02:48 +0000</pubDate>
				<category><![CDATA[English]]></category>
		<category><![CDATA[books]]></category>
		<category><![CDATA[science fiction]]></category>
		<guid isPermaLink="false">https://blog.des.no/?p=1282</guid>

					<description><![CDATA[Some of you may know that the 2020 Hugo Award ceremony was held last night¹ and that it was hosted by George R. R. Martin. Some of you may have heard that it did not go well. Some of you may already know what happened, more or less. I watched it live, and unsurprisingly, I &#8230; <a href="https://blog.des.no/2020/08/on-dinosaurs-and-context/" class="more-link">Continue reading<span class="screen-reader-text"> "On dinosaurs and context"</span></a>]]></description>
										<content:encoded><![CDATA[
<div class="wp-block-image"><figure class="alignright is-resized"><img loading="lazy" decoding="async" src="https://upload.wikimedia.org/wikipedia/en/thumb/0/00/Hugo_Award_Logo.svg/512px-Hugo_Award_Logo.svg.png" alt="" width="128" height="192"/></figure></div>



<p class="wp-block-paragraph">Some of you may know that the <a href="http://www.thehugoawards.org/hugo-history/2020-hugo-awards/">2020 Hugo Award ceremony</a> was held last night<a href="#fn1">¹</a> and that it was hosted by George R. R. Martin. Some of you may have heard that it did not go well. Some of you may already know what happened, more or less. I watched it live, and unsurprisingly, I have opinions.</p>



<figure class="wp-block-embed-twitter wp-block-embed is-type-rich is-provider-twitter"><div class="wp-block-embed__wrapper">
<blockquote class="twitter-tweet" data-width="550" data-dnt="true"><p lang="en" dir="ltr">So, we had a ton of fun taking the piss out of GRRM during the <a href="https://twitter.com/hashtag/HugoAwards?src=hash&amp;ref_src=twsrc%5Etfw">#HugoAwards</a> livestream but now that it&#39;s over, there needs to be a serious conversation about what happened last night. Because there is no way GRRM didn&#39;t know what he was doing.</p>&mdash; Dag-Erling Smørgrav (@desdotdev) <a href="https://twitter.com/desdotdev/status/1289430519910825988?ref_src=twsrc%5Etfw">August 1, 2020</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div></figure>



<p class="wp-block-paragraph">This post is not a blow-by-blow account of events or any sort of clever analysis or deep thoughts on how to move forward. Better minds than mine have already taken care of that; see for instance <a class="ek-link ek-link" href="http://www.pretty-terrible.com/george-r-r-martin-2020-hugo-awards/">Natalie Luhrs&#8217;s take on the affair</a>. Instead, I would like to offer a little bit of context for those who heard what happened (or watched it happen) and have a vague idea that it was bad but do not understand why everybody is so upset and do not want to jump down the rabbit hole of SFF fandom drama.</p>



<span id="more-1282"></span>



<p class="wp-block-paragraph">So, here is my best attempt at putting the controversy in context.</p>



<ol class="is-style-default wp-block-list"><li>This year&#8217;s Hugo award administrators and / or WorldCon organizing committee selected George R. R. Martin to host the award ceremony. He, in turn, selected Robert Silverberg to present two of the awards (Best Editor Short Form / Long Form).</li><li>There is a Hugo-adjacent award for new authors, which used to be called the <em>John W. Campbell Award for Best New Writer</em>. It is not technically a Hugo award, but in practice, the only difference is that instead of a pin and a silver rocket, you get a different pin and a plaque.</li><li>In her acceptance speech for the 2019 Campbell award, Jeannette Ng referenced the fact that Campbell was, shall we say, Not Very Nice.<a href="#fn2" class="ek-link">²</a> As she points out herself, she was neither the first nor the most prominent person to bring that up, or even the first or most prominent to do so in front of a large audience. But we live in interesting times, and her speech resonated as never before. This had two major consequences: the award was renamed to the <em>Astounding Award for Best New Writer</em>, and Ng&#8217;s acceptance speech was nominated for the 2020 Hugo Award for Best Related Work.</li><li>As editor of the <em>Astounding Science Fiction</em> magazine (later renamed to <em>Analog Science Fiction and Fact</em>) for thirty-odd years, Campbell was credited with discovering, mentoring, and promoting many new authors, some of whom went on to become the most recognizable names in the genre. In that light, it seems natural that an award given to new writers should be named after him. However, we cannot mention the voices which Campbell elevated without also mentioning the ones he suppressed. Because Campbell had a very clear idea of who was worth listening to (white men) and who wasn&#8217;t (everybody else). If Campbell was still alive and in a position of power, it is doubtful that Jeannette Ng would be a published author. Or Rebecca F. Kuang, who won this year&#8217;s Astounding Award. Or Rebecca Roanhorse (2018). Or Wesley Chu (2015). Or Sofia Samatar (2014). Or any but five or six of the last twenty Best New Writer laureates. And certainly not N. K. Jemisin, whose <em>Broken Earth</em> trilogy netted her three consecutive Best Novel Hugos (2016-2018), a Nebula (2018), and a Locus (2018), but whose skin is of a shade which Campbell particularly detested.</li></ol>



<p class="wp-block-paragraph">When Martin (and Silverberg, who was granted — or granted himself — a disproportionate amount of airtime compared to other presenters) brought up Campbell again, and again, and again, during the ceremony; and when Martin repeatedly pronounced “Astounding” in the most theatrical way imaginable when referring to the award; and when Martin gave a list of examples of what constitutes a “related work”<a href="https://blog.des.no/wp-admin/post.php?post=1282&amp;action=edit#fn3" class="ek-link">³</a> which covered every nominee <em>except</em> Ng; this has to be viewed in the context of Ng&#8217;s speech last year, of her nomination this year, and of the renaming of the award. And it does not look pretty.</p>



<p class="wp-block-paragraph">Finally,</p>



<figure class="wp-block-embed-twitter wp-block-embed is-type-rich is-provider-twitter"><div class="wp-block-embed__wrapper">
<blockquote class="twitter-tweet" data-width="550" data-dnt="true"><p lang="en" dir="ltr">If you&#39;re here because of my shit-tweeting about the <a href="https://twitter.com/hashtag/HugoAwards?src=hash&amp;ref_src=twsrc%5Etfw">#HugoAwards</a>: I&#39;m happy that you liked it but there are better voices than mine to listen to. A good place to start is <a href="https://twitter.com/MaryRobinette?ref_src=twsrc%5Etfw">@MaryRobinette</a> who is a SMoF in the best sense of the term.</p>&mdash; Dag-Erling Smørgrav (@desdotdev) <a href="https://twitter.com/desdotdev/status/1289684452344393728?ref_src=twsrc%5Etfw">August 1, 2020</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div></figure>



<hr class="wp-block-separator is-style-wide"/>



<p class="has-small-font-size wp-block-paragraph" id="fn1">¹ It was to have been held in Wellington, New Zealand as part of the 2020 World Science Fiction Convention, but was entirely virtual due to the ongoing pandemic. It started at 11 am on Saturday in New Zealand time, which was the middle of the night in Europe and Friday evening in the US.</p>



<p class="has-small-font-size wp-block-paragraph" id="fn2">² Her exact words were “a fucking fascist”, which may have been impolitic but was certainly not inaccurate. Also, if there is one thing we have learned from the history of civil rights, it is that politeness gets you nowhere; when the ruling class asks protesters to “be civil”, what they actually mean is “be invisible”.</p>



<p class="has-small-font-size wp-block-paragraph" id="fn3">³ Starting at 2:46:15 in the <a class="ek-link ek-link" href="https://watch.thefantasy.network/the-2020-hugo-awards-livestream/">archived livestream</a>: “biographies are related works, autobiographies, works of criticism, art books, collections of reviews, memoirs, histories, and… other things”</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.des.no/2020/08/on-dinosaurs-and-context/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Bump</title>
		<link>https://blog.des.no/2018/11/bump/</link>
					<comments>https://blog.des.no/2018/11/bump/#respond</comments>
		
		<dc:creator><![CDATA[Dag-Erling Smørgrav]]></dc:creator>
		<pubDate>Wed, 14 Nov 2018 19:11:20 +0000</pubDate>
				<category><![CDATA[English]]></category>
		<category><![CDATA[tech]]></category>
		<guid isPermaLink="false">https://blog.des.no/?p=1264</guid>

					<description><![CDATA[Time for my annual “oh shit, I forgot to bump the copyright year again” round-up! In the F/OSS community, there are two different philosophies when it comes to applying copyright statements to a project. If the code base consists exclusively (or almost exclusively) of code developed for that specific project by the project&#8217;s author or &#8230; <a href="https://blog.des.no/2018/11/bump/" class="more-link">Continue reading<span class="screen-reader-text"> "Bump"</span></a>]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Time for my annual “oh shit, I forgot to bump the copyright year again” round-up!</p>



<p class="wp-block-paragraph">In the F/OSS community, there are two different philosophies when it comes to applying copyright statements to a project. If the code base consists exclusively (or almost exclusively) of code developed for that specific project by the project&#8217;s author or co-authors, many projects will have a single file (usually named <code>LICENSE</code>) containing the license, a list of copyright holders, and the copyright dates or ranges. However, if the code base incorporates a significant body of code taken from other projects or contributed by parties outside the project, it is customary to include the copyright statements and either the complete license or a reference to it in each individual file. In my experience, projects that use the BSD, ISC, MIT, adjacent licenses tend to use the latter model regardless.</p>



<span id="more-1264"></span>



<p class="wp-block-paragraph">The advantage of the second model is that it&#8217;s hard to get wrong. You might forget to add a name to a central list, but you&#8217;re far less likely to forget to state the name of the author when you add a new file. The disadvantage is that it&#8217;s really, really easy to forget to update the copyright year when you commit a change to an existing file that hasn&#8217;t been touched in a while.</p>



<p class="wp-block-paragraph">So, how can we automate this?</p>



<p class="wp-block-paragraph">One possibility is to have a pre-commit hook that updates it for you (generally a bad idea), or one that rejects the commit if it thinks you forgot (better, but not perfect; what if you&#8217;re adding a file from an outside source?), or one that prints a big fat warning if it thinks you forgot (much better, especially with Git since you can <code>commit --amend</code> once you&#8217;ve fixed it, before pushing).</p>



<p class="wp-block-paragraph">But how do you fix the mistake retroactively, without poring over commit logs to figure out what was modified when?</p>



<p class="wp-block-paragraph">Let&#8217;s start by assuming that you have a list of files that were modified in 2017, and that each file only has one copyright statement that needs to be updated to reflect that fact. The following Perl one-liner should do the trick:</p>



<pre class="wp-block-preformatted">perl -p -i -e 'if (/Copyright/) { s/ ([0-9]{4})-20(?:0[0-9]|1[0-6]) / $1-2017 /; s/ (20(?:0[0-9]|1[0-6])) / $1-2017 /; }'</pre>



<p class="wp-block-paragraph">It should be fairly self-explanatory if you know regular expressions. The first substitution handles the case where the existing statement contains a range, in which case we extend it to include 2017, and the second substitution handles the case where the existing statement contains a single year, which we replace with a range starting with the original year and ending with 2017. The complexity stems mostly from having to take care not to replace 2018 (or later) with 2017; our regexes only match years in the range 2000-2016.</p>



<p class="wp-block-paragraph">OK, so now we know how to fix the files, but how do we figure out which ones need fixing?</p>



<p class="wp-block-paragraph">With Git, we could try something like this:</p>



<pre class="wp-block-preformatted">git diff --name-only 'HEAD@{2017-01-01}..HEAD@{2018-01-01}'</pre>



<p class="wp-block-paragraph">This is&#8230; imperfect, though. The first problem is that it will list <em>every</em> file that was touched, including files that were added, moved, renamed, or deleted. Files that were added should be assumed to have had a correct copyright statement at the time they were added; files that were only moved or renamed should not be updated, since their contents did not change; and files that were deleted are no longer there to be updated.¹ We should restrict our search to files that were actually modified:</p>



<pre class="wp-block-preformatted">git diff --name-only --diff-filter M 'HEAD@{2017-01-01}..HEAD@{2018-01-01}'<br></pre>



<p class="wp-block-paragraph">Some of those changes might be too trivial to copyright, though. This is a fairly complex legal matter, but to simplify, if the change was inevitable and there was no room for creative expression&nbsp;— for instance, a function in a third-party library you are using was renamed, so both the reason for the change and the nature of the change are external to the work itself&nbsp;— then it is not protected. So perhaps you should remove <code>--name-only</code> and review the diff, which is when you realize that half those files were only modified to update their copyright statements because you forgot to do so in 2016. Let&#8217;s try to exclude them mechanically, rather than manually. Unfortunately, <code>git diff</code> does not have anything that resembles <code>diff -I</code>, so we have to write our own diff command which does that, and ask git to use it:</p>



<pre class="wp-block-preformatted">$ echo 'exec diff -u -ICopyright "$@"' &gt;diff-no-copyright<br>$ chmod a+rx diff-no-copyright<br>$ git difftool --diff-filter M --extcmd $PWD/diff-no-copyright&nbsp;'HEAD@{2017-01-01}..HEAD@{2018-01-01}'</pre>



<p class="wp-block-paragraph">This gives us a diff, though, not a list of files. We can try to extract the names as follows:</p>



<pre class="wp-block-preformatted">$ git difftool --diff-filter M --no-prompt --extcmd $PWD/diff-no-copyright&nbsp;'HEAD@{2017-01-01}..HEAD@{2018-01-01}' | awk '/^---/ { print $2 }'</pre>



<p class="wp-block-paragraph">Wait&#8230; no, that&#8217;s just garbage. The thing is, <code>git difftool</code>&nbsp;works by checking out both versions of a file and diffing them, so what we get is a list of the names of the temporary files it created. We have to be a little more creative:</p>



<pre class="wp-block-preformatted">$ echo '/usr/bin/diff -q -ICopyright "$@" &gt;/dev/null || echo "$BASE"' &gt;list-no-copyright<br>$ chmod a+rx list-no-copyright<br>$ git difftool --diff-filter M --no-prompt --extcmd $PWD/list-no-copyright 'HEAD@{2017-01-01}..HEAD@{2018-01-01}'</pre>



<p class="wp-block-paragraph">Much better. We can glue this together with our Perl one-liner using <code>xargs</code>, then repeat the process for 2018.</p>



<p class="wp-block-paragraph">Finally, how about Subversion? On the one hand, Subversion is far simpler than Git, so we can get 90% of the way much more easily. On the other hand, Subversion is far less flexible than Git, so we can&#8217;t go the last 10% of the way. Here&#8217;s the best I could do:</p>



<pre class="wp-block-preformatted">$ echo 'exec diff -u -ICopyright "$@"' &gt;diff-no-copyright<br>$ chmod a+rx diff-no-copyright<br>$ svn diff --ignore-properties --diff-cmd $PWD/diff-no-copyright -r'{2017-01-01}:{2018-01-01}' | awk '/^---/ { print $2 }'</pre>



<p class="wp-block-paragraph">This will not work properly if you have files with names that contain whitespace; you&#8217;ll have to use <code>sed</code>&nbsp;with a much more complicated regex, which I leave as an exercise.</p>



<hr class="wp-block-separator is-style-wide"/>



<p class="has-small-font-size wp-block-paragraph">¹ I will leave the issue of move-and-modify being incorrectly recorded as delete-and-add to the reader. One possibility is to include added files in the list by using <code>--diff-filter AM</code>, and review them manually before committing.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.des.no/2018/11/bump/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>DNS over TLS in FreeBSD 12</title>
		<link>https://blog.des.no/2018/10/dns-over-tls-in-freebsd-12/</link>
					<comments>https://blog.des.no/2018/10/dns-over-tls-in-freebsd-12/#comments</comments>
		
		<dc:creator><![CDATA[Dag-Erling Smørgrav]]></dc:creator>
		<pubDate>Mon, 22 Oct 2018 09:36:51 +0000</pubDate>
				<category><![CDATA[English]]></category>
		<category><![CDATA[DNS]]></category>
		<category><![CDATA[FreeBSD]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[tech]]></category>
		<category><![CDATA[Unbound]]></category>
		<guid isPermaLink="false">https://blog.des.no/?p=1249</guid>

					<description><![CDATA[With the arrival of OpenSSL 1.1.1, an upgraded Unbound, and some changes to the setup and init scripts, FreeBSD 12, currently in beta, now supports DNS over TLS out of the box. We show how to set it up and discuss its advantages and disadvantages.]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">With the arrival of OpenSSL 1.1.1, an upgraded Unbound, and <a href="https://svnweb.freebsd.org/base?view=revision&amp;revision=339424">some changes to the setup and init scripts</a>, FreeBSD 12.0, currently in beta, now supports <a href="https://en.wikipedia.org/wiki/DNS_over_TLS">DNS over TLS</a> out of the box.</p>



<p class="wp-block-paragraph">DNS over TLS is just what it sounds like: DNS over TCP, but wrapped in a TLS session. It encrypts your requests and the server&#8217;s replies, and optionally allows you to verify the identity of the server. The advantages are protection against eavesdropping and manipulation of your DNS traffic; the drawbacks are a slight performance degradation and potential firewall traversal issues, as it runs over a non-standard port (TCP port 853) which may be blocked on some networks. Let&#8217;s take a look at how to set it up.</p>



<span id="more-1249"></span>



<h2 class="wp-block-heading">Basic setup</h2>



<p class="wp-block-paragraph">As a simple test case, let&#8217;s set up our 12.0-ALPHA10 VM to use <a href="https://developers.cloudflare.com/1.1.1.1/dns-over-tls/">Cloudflare&#8217;s DNS service</a>:</p>



<pre class="wp-block-preformatted"># uname -r<br>12.0-ALPHA10<br># cat &gt;/etc/rc.conf.d/local_unbound &lt;&lt;EOF<br>local_unbound_enable="YES"<br><strong>local_unbound_tls="YES"<br></strong>local_unbound_forwarders="<strong>1.1.1.1@853 1.0.0.1@853</strong>"<br>EOF<br># service local_unbound start<br>Performing initial setup.<br>destination: <br>/var/unbound/forward.conf created<br>/var/unbound/lan-zones.conf created<br>/var/unbound/control.conf created<br>/var/unbound/unbound.conf created<br>/etc/resolvconf.conf not modified<br>Original /etc/resolv.conf saved as /var/backups/resolv.conf.20181021.192629<br>Starting local_unbound.<br>Waiting for nameserver to start... good<br># host www.freebsd.org<br>www.freebsd.org is an alias for wfe0.nyi.freebsd.org.<br>wfe0.nyi.freebsd.org has address 96.47.72.84<br>wfe0.nyi.freebsd.org has IPv6 address 2610:1c1:1:606c::50:15<br>wfe0.nyi.freebsd.org mail is handled by 0 .</pre>



<p class="wp-block-paragraph">Note that this is <em>not</em> a configuration you want to run in production—we will come back to this later.<br></p>



<h2 class="wp-block-heading">Performance</h2>



<p class="wp-block-paragraph">The downside of DNS over TLS is the performance hit of the TCP and TLS session setup and teardown. We demonstrate this by flushing our cache and (rather crudely) measuring a cache miss and a cache hit:<br></p>



<pre class="wp-block-preformatted"># local-unbound-control reload<br>ok<br># time host www.freebsd.org &gt;x<br>host www.freebsd.org &gt; x  0.00s user 0.00s system 0% cpu 0.553 total<br># time host www.freebsd.org &gt;x<br>host www.freebsd.org &gt; x  0.00s user 0.00s system 0% cpu 0.005 total</pre>



<p class="wp-block-paragraph">Compare this to querying our router, a puny Soekris net5501 running Unbound 1.8.1 on FreeBSD 11.1-RELEASE:<br></p>



<pre class="wp-block-preformatted"># time host www.freebsd.org gw &gt;x<br>host www.freebsd.org gw &gt; x  0.00s user 0.00s system 0% cpu 0.232 total<br># time host www.freebsd.org 192.168.144.1 &gt;x<br>host www.freebsd.org gw &gt; x  0.00s user 0.00s system 0% cpu 0.008 total</pre>



<p class="wp-block-paragraph">or to querying Cloudflare directly over UDP:</p>



<pre class="wp-block-preformatted"># time host www.freebsd.org 1.1.1.1 &gt;x      <br>host www.freebsd.org 1.1.1.1 &gt; x  0.00s user 0.00s system 0% cpu 0.272 total<br># time host www.freebsd.org 1.1.1.1 &gt;x<br>host www.freebsd.org 1.1.1.1 &gt; x  0.00s user 0.00s system 0% cpu 0.013 total</pre>



<p class="wp-block-paragraph">(Cloudflare uses anycast routing, so it is not so unreasonable to see a cache miss during off-peak hours.)</p>



<p class="wp-block-paragraph">This clearly shows the advantage of running a local caching resolver—it absorbs the cost of DNSSEC and TLS. And speaking of DNSSEC, we can separate that cost from that of TLS by reconfiguring our server without the latter:<br></p>



<pre class="wp-block-preformatted"># cat &gt;/etc/rc.conf.d/local_unbound &lt;&lt;EOF<br>local_unbound_enable="YES"<br>local_unbound_tls="NO"<br>local_unbound_forwarders="1.1.1.1 1.0.0.1"<br>EOF<br># service local_unbound setup<br>Performing initial setup.<br>destination: <br>Original /var/unbound/forward.conf saved as /var/backups/forward.conf.20181021.205328<br>/var/unbound/lan-zones.conf not modified<br>/var/unbound/control.conf not modified<br>Original /var/unbound/unbound.conf saved as /var/backups/unbound.conf.20181021.205328<br>/etc/resolvconf.conf not modified<br>/etc/resolv.conf not modified<br># service local_unbound start<br>Starting local_unbound.<br>Waiting for nameserver to start... good<br># time host www.freebsd.org &gt;x<br>host www.freebsd.org &gt; x  0.00s user 0.00s system 0% cpu 0.080 total<br># time host www.freebsd.org &gt;x<br>host www.freebsd.org &gt; x  0.00s user 0.00s system 0% cpu 0.004 total</pre>



<p class="wp-block-paragraph">So does TLS add nearly half a second to every cache miss? Not quite, fortunately—in our previous tests, our first query was not only a cache miss but also the first query after a restart or a cache flush, resulting in a complete load and validation of the entire path from the name we queried to the root. The difference between a first and second cache miss is quite noticeable:<br></p>



<pre class="wp-block-preformatted"># time host www.freebsd.org &gt;x <br>host www.freebsd.org &gt; x  0.00s user 0.00s system 0% cpu 0.546 total<br># time host www.freebsd.org &gt;x<br>host www.freebsd.org &gt; x  0.00s user 0.00s system 0% cpu 0.004 total<br># time host repo.freebsd.org &gt;x<br>host repo.freebsd.org &gt; x  0.00s user 0.00s system 0% cpu 0.168 total<br># time host repo.freebsd.org &gt;x<br>host repo.freebsd.org &gt; x  0.00s user 0.00s system 0% cpu 0.004 total</pre>



<h2 class="wp-block-heading">Revisiting our configuration</h2>



<p class="wp-block-paragraph">Remember when I said that you shouldn&#8217;t run the sample configuration in production, and that I&#8217;d get back to it later? This is later.</p>



<p class="wp-block-paragraph">The problem with our first configuration is that while it encrypts our DNS traffic, it does not verify the identity of the server. Our ISP could be routing all traffic to 1.1.1.1 to its own servers, logging it, and selling the information to the highest bidder. We need to tell Unbound to validate the server certificate, but there&#8217;s a catch: Unbound only knows the IP addresses of its forwarders, not their names. We have to provide it with names that will match the x509 certificates used by the servers we want to use. Let&#8217;s double-check the certificate:</p>



<pre class="wp-block-preformatted"># :| openssl s_client -connect 1.1.1.1:853 |&amp; openssl x509 -noout -text |&amp; grep DNS<br><code>            DNS:*.cloudflare-dns.com, IP Address:1.1.1.1, IP Address:1.0.0.1, DNS:cloudflare-dns.com, IP Address:2606:4700:4700:0:0:0:0:1111, IP Address:2606:4700:4700:0:0:0:0:1001</code><br></pre>



<p class="wp-block-paragraph">This matches <a href="https://developers.cloudflare.com/1.1.1.1/dns-over-tls/">Cloudflare&#8217;s documentation</a>, so let&#8217;s update our configuration:<br></p>



<pre class="wp-block-preformatted"># cat &gt;/etc/rc.conf.d/local_unbound &lt;&lt;EOF<br>local_unbound_enable="YES"<br>local_unbound_tls="YES"<br>local_unbound_forwarders="1.1.1.1@853<strong>#cloudflare-dns.com</strong> 1.0.0.1@853<strong>#cloudflare-dns.com</strong>"<br>EOF<br># service local_unbound setup            <br>Performing initial setup.<br>destination: <br>Original /var/unbound/forward.conf saved as /var/backups/forward.conf.20181021.212519<br>/var/unbound/lan-zones.conf not modified<br>/var/unbound/control.conf not modified<br>/var/unbound/unbound.conf not modified<br>/etc/resolvconf.conf not modified<br>/etc/resolv.conf not modified<br># service local_unbound restart<br>Stopping local_unbound.<br>Starting local_unbound.<br>Waiting for nameserver to start... good<br># host www.freebsd.org<br>www.freebsd.org is an alias for wfe0.nyi.freebsd.org.<br>wfe0.nyi.freebsd.org has address 96.47.72.84<br>wfe0.nyi.freebsd.org has IPv6 address 2610:1c1:1:606c::50:15<br>wfe0.nyi.freebsd.org mail is handled by 0 .</pre>



<p class="wp-block-paragraph">How can we confirm that Unbound actually validates the certificate? Well, we can run Unbound in debug mode (<code>/usr/sbin/local-unbound -dd -vvv</code>) and read the debugging output&#8230; or we can confirm that it fails when given a name that does not match the certificate:</p>



<pre class="wp-block-preformatted"># perl -p -i -e 's/cloudflare/cloudfire/g' /etc/rc.conf.d/local_unbound<br># service local_unbound setup<br>Performing initial setup.<br>destination: <br>Original /var/unbound/forward.conf saved as /var/backups/forward.conf.20181021.215808<br>/var/unbound/lan-zones.conf not modified<br>/var/unbound/control.conf not modified<br>/var/unbound/unbound.conf not modified<br>/etc/resolvconf.conf not modified<br>/etc/resolv.conf not modified<br># service local_unbound restart<br>Stopping local_unbound.<br>Waiting for PIDS: 33977.<br>Starting local_unbound.<br>Waiting for nameserver to start... good<br># host www.freebsd.org<br>Host www.freebsd.org not found: 2(SERVFAIL)<br></pre>



<p class="wp-block-paragraph">But is this really a failure to validate the certificate? Actually, no. When provided with a server name, Unbound will pass it to the server during the TLS handshake, and the server will reject the handshake if that name does not match any of its certificates. To <em>truly</em> verify that Unbound validates the server certificate, we have to confirm that it fails when it <em>cannot</em>&nbsp;do so. For instance, we can remove the root certificate used to sign the DNS server&#8217;s certificate from the test system&#8217;s trust store. Note that we cannot simply remove the trust store entirely, as Unbound will refuse to start if the trust store is missing or empty.</p>



<p class="wp-block-paragraph">While we&#8217;re talking about trust stores, I should point out that you currently must have <code>ca_root_nss</code> installed for DNS over TLS to work. However, 12.0-RELEASE will ship with a pre-installed copy.</p>



<h2 class="wp-block-heading">Conclusion<br></h2>



<p class="wp-block-paragraph">We&#8217;ve seen how to set up Unbound—specifically, the <code>local_unbound</code> service in FreeBSD 12.0—to use DNS over TLS instead of plain UDP or TCP, using Cloudflare&#8217;s public DNS service as an example. We&#8217;ve looked at the performance impact, and at how to ensure (and verify) that Unbound validates the server certificate to prevent man-in-the-middle attacks.</p>



<p class="wp-block-paragraph">The question that remains is whether it is all worth it. There is undeniably a performance hit, though this may improve with TLS 1.3. More importantly, there are currently very few DNS-over-TLS providers—only one, really, since Quad9 filter their responses—and you have to weigh the advantage of encrypting your DNS traffic against the disadvantage of sending it all to a single organization. I can&#8217;t answer that question for you, but I can tell you that the parameters are evolving quickly, and if your answer is negative today, it may not remain so for long. More providers will appear. Performance will improve with TLS 1.3 and <a href="https://en.wikipedia.org/wiki/QUIC">QUIC</a>. Within a year or two, running DNS over TLS may very well become the rule rather than the experimental exception.<br></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.des.no/2018/10/dns-over-tls-in-freebsd-12/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Twenty years</title>
		<link>https://blog.des.no/2018/04/twenty-years/</link>
					<comments>https://blog.des.no/2018/04/twenty-years/#respond</comments>
		
		<dc:creator><![CDATA[Dag-Erling Smørgrav]]></dc:creator>
		<pubDate>Mon, 09 Apr 2018 20:35:59 +0000</pubDate>
				<category><![CDATA[English]]></category>
		<category><![CDATA[FreeBSD]]></category>
		<category><![CDATA[tech]]></category>
		<guid isPermaLink="false">https://blog.des.no/?p=1233</guid>

					<description><![CDATA[Yesterday was the twentieth anniversary of my FreeBSD commit bit, and tomorrow will be the twentieth anniversary of my first commit. I figured I&#8217;d split the difference and write a few words about it today. My level of engagement with the FreeBSD project has varied greatly over the twenty years I&#8217;ve been a committer. There &#8230; <a href="https://blog.des.no/2018/04/twenty-years/" class="more-link">Continue reading<span class="screen-reader-text"> "Twenty years"</span></a>]]></description>
										<content:encoded><![CDATA[<p>Yesterday was the twentieth anniversary of my <a href="https://www.freebsd.org/">FreeBSD</a> commit bit, and tomorrow will be the twentieth anniversary of <a href="https://svnweb.freebsd.org/base?view=revision&amp;revision=35121">my first commit</a>. I figured I&#8217;d split the difference and write a few words about it today.</p>
<p>My level of engagement with the FreeBSD project has varied greatly over the twenty years I&#8217;ve been a committer. There have been times when I worked on it full-time, and times when I did not touch it for months. The last few years, health issues and life events have consumed my time and sapped my energy, and <a href="https://www.openhub.net/p/freebsd/contributors/16565688874653">my contributions</a> have come in bursts. Commit statistics do not tell the whole story, though: even when not working on FreeBSD directly, I have worked on side projects which, like <a href="https://www.openpam.org/">OpenPAM</a>, may one day find their way into FreeBSD.</p>
<p>My contributions have not been limited to code. I was the project&#8217;s first <a href="https://www.freebsd.no/administration.html#t-bugmeister">Bugmeister</a>; I&#8217;ve served on the <a href="https://www.freebsd.no/administration.html#t-secteam">Security Team</a> for a long time, and have been both Security Officer and Deputy Security Officer; I managed the last four <a href="https://www.freebsd.org/doc/en/books/dev-model/process-core-election.html">Core Team elections</a> and am doing so again this year.</p>
<p>In return, the project has taught me much about programming and software engineering. It taught me code hygiene and the importance of clarity over cleverness; it taught me the ins and outs of revision control; it taught me the importance of good documentation, and how to write it; and it taught me good release engineering practices.</p>
<p>Last but not least, it has provided me with the opportunity to work with some of the best people in the field. I have the privilege today to count several of them among my friends.</p>
<p>For better or worse, the FreeBSD project has shaped my career and my life. It set me on the path to information security in general and IAA in particular, and opened many a door for me. I would not be where I am now without it.</p>
<p>I won&#8217;t pretend to be able to tell the future. I don&#8217;t know how long I will remain active in the FreeBSD project and community. It could be another twenty years; or it could be ten, or five, or less. All I know is that FreeBSD and I still have things to teach each other, and I don&#8217;t intend to call it quits any time soon.</p>
<p><em><a href="/2008/04/ten-years/">Previously</a></em></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.des.no/2018/04/twenty-years/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Yes, all men</title>
		<link>https://blog.des.no/2017/07/yes-all-men/</link>
					<comments>https://blog.des.no/2017/07/yes-all-men/#respond</comments>
		
		<dc:creator><![CDATA[Dag-Erling Smørgrav]]></dc:creator>
		<pubDate>Mon, 31 Jul 2017 21:56:46 +0000</pubDate>
				<category><![CDATA[English]]></category>
		<category><![CDATA[current affairs]]></category>
		<category><![CDATA[feminism]]></category>
		<category><![CDATA[mixed bolts]]></category>
		<category><![CDATA[tech]]></category>
		<guid isPermaLink="false">https://blog.des.no/?p=1220</guid>

					<description><![CDATA[As a man, you are, and always have been, part of the problem. Accept it, and start being part of the solution.]]></description>
										<content:encoded><![CDATA[<p>Since Susan Fowler blogged about her <a href="https://www.susanjfowler.com/blog/2017/2/19/reflecting-on-one-very-strange-year-at-uber">experience at Uber</a> in February, the debate about sexism in tech has dominated IT and business news. Note that this debate is not new, and Fowler&#8217;s story isn&#8217;t all that different from many other stories we&#8217;ve heard before. It&#8217;s just that for once, <em>finally</em>, people were paying attention, and There Were Consequences. Then matters escalated in June with a string of revelations about sexism—not just discrimination, but full on sexual harassment.</p>
<p>Then came the apologies. Let me tell you about the apologies. The average response from a manager or venture capitalist accused of sexism went something like this:</p>
<blockquote>
<p>I apologized unreservedly for my treatment of X. I realize now that my innocent jokes may have been misinterpreted. I&#8217;m actually a pretty nice guy, and X&#8217;s refusal to sleep with me had no impact whatsoever on my decision not to invest in her startup.</p>
</blockquote>
<p>Then came the White Knights:</p>
<blockquote>
<p>As a VC, I&#8217;m appalled to hear about my colleagues&#8217; behavior towards women. I would like to reassure you all that Not All Men are like that. I myself am actually a pretty nice guy and completely innocent in all this.</p>
</blockquote>
<p>Guys, it&#8217;s time to face the music. We have all been That Guy. We have all made sexist jokes, or laughed when others made them, or stood by silently while our male bosses, coworkers and colleagues ignored or patronized or belittled or humiliated women. We have all benefited from a system that eliminates close to 50% of our competition before the race has even started.</p>
<p>We are all complicit. We are all guilty.</p>
<p>So what do we do? Where do we go next?</p>
<p>First, take a deep breath, do a little soul-searching, and re-read that paragraph until any impulse, however minor, to say to yourself “OK, but not <em>me</em>” is gone. <em>Yes, you too.</em></p>
<p>Next, if you&#8217;ve ever acted inappropriately towards a female coworker or friend or acquaintance, or stood by silently while others did, consider apologizing.</p>
<p>Third, vow to never do so again, and work hard to keep that vow. Respect the women around you as much as you respect the men. If someone around you acts or speaks inappropriately, speak up, even if there are no women present. Be proactive: make sure that women are given equal opportunity to join those career-building projects, and are included in those backstage chats where decisions are made. If you are hiring, seek out female candidates, keeping in mind that women have a tendency to underestimate their abilities and experience just as men have a tendency to overestimate them. If you are teaching, encourage and mentor female students. Reach out to them if they seem discouraged. Don&#8217;t wait until they drop out.</p>
<p>Open your eyes. Open your ears. Listen to the women around you. Believe them. Respect them. Be someone they can vent to and someone they can count on for support when push comes to shove.</p>
<p>You will slip up. When you do, apologize and vow to do better.</p>
<p>As a man, you are, and always have been, part of the problem. Accept it, and start being part of the solution.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.des.no/2017/07/yes-all-men/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Fidelio, Act Two</title>
		<link>https://blog.des.no/2017/04/fidelio-act-two/</link>
					<comments>https://blog.des.no/2017/04/fidelio-act-two/#respond</comments>
		
		<dc:creator><![CDATA[Dag-Erling Smørgrav]]></dc:creator>
		<pubDate>Sun, 02 Apr 2017 16:11:03 +0000</pubDate>
				<category><![CDATA[English]]></category>
		<category><![CDATA[mixed bolts]]></category>
		<category><![CDATA[music]]></category>
		<guid isPermaLink="false">https://blog.des.no/?p=1197</guid>

					<description><![CDATA[As promised, here is my adaption of the second act of Beethoven&#8216;s one and only opera Fidelio. Read the first act if you haven&#8217;t already. Scene 1 Florestan: Shit, it&#8217;s really dark in here. It&#8217;s a good thing I&#8217;m really, really righteous and brave! I just hope Leonore is OK. Scene 2 Fidelionore: Brr, it&#8217;s &#8230; <a href="https://blog.des.no/2017/04/fidelio-act-two/" class="more-link">Continue reading<span class="screen-reader-text"> "Fidelio, Act Two"</span></a>]]></description>
										<content:encoded><![CDATA[<p>As promised, here is my adaption of the second act of <a href="https://en.wikipedia.org/wiki/Ludwig_van_Beethoven">Beethoven</a>&#8216;s one and only opera <a href="https://en.wikipedia.org/wiki/Fidelio">Fidelio</a>. Read <a href="http://blog.des.no/2017/04/fidelio-act-one">the first act</a> if you haven&#8217;t already.<span id="more-1197"></span></p>
<hr />
<p><strong>Scene 1</strong></p>
<p><em>Florestan:</em> Shit, it&#8217;s really dark in here. It&#8217;s a good thing I&#8217;m really, really righteous and brave! I just hope Leonore is OK.</p>
<hr />
<p><strong>Scene 2</strong></p>
<p><em>Fidelionore:</em> Brr, it&#8217;s cold as balls down here.</p>
<p><em>Rocco:</em> Sorry, Pizarro must have forgotten to pay the electricity bill. Anyway, here we are.</p>
<p><em>Fidelionore:</em> He&#8217;s not moving!</p>
<p><em>Rocco:</em> You think he&#8217;s dead? Nah, just asleep. Help me dig. You scared?</p>
<p><em>Fidelionore:</em> Just cold. Sorry.</p>
<p><em>Rocco:</em> Start digging, it&#8217;ll keep you warm.</p>
<p><em>They dig.</em></p>
<p><em>Fidelionore:</em> I think he&#8217;s waking up!</p>
<p><em>Rocco:</em> Get out of here, I need to talk to him.</p>
<p><em>Florestan:</em> I have been imprisoned here for over two years, and surely I must know where I am and what has happened, but the audience wasn&#8217;t here, so please pretend I don&#8217;t know, and tell me who is keeping me here.</p>
<p><em>Rocco:</em> Pizarro, and believe me, I like him about as much as you do.</p>
<p><em>Florestan:</em> Pizarro? Shit. Send word to Sevilla, let my wife know where I am!</p>
<p><em>Rocco:</em> Sorry, bud, no can do. I brought some wine to dull the pain of digging another man&#8217;s grave, want a drop?</p>
<p><em>Florestan:</em> Why the hell not.</p>
<p><em>Rocco:</em> Fidelio, bring the wine! Hey, you don&#8217;t look too good.</p>
<p><em>Florestan:</em> Poor kid!</p>
<p><em>Fidelionore:</em> I don&#8217;t feel too good.</p>
<p><em>Rocco:</em> Look, it sucks that he&#8217;s going to die, but I&#8217;m only following orders.</p>
<p><em>Fidelionore:</em> Want some stale bread? I&#8217;ve been carrying this around for days instead of grabbing a fresh piece at the breakfast table every morning.</p>
<p><em>Rocco:</em> I am about to become complicit in an innocent man&#8217;s death, but it&#8217;s all good because I&#8217;m only following orders, plus I gave him some wine.</p>
<p><em>Florestan:</em> I am sorry that I cannot repay you for bringing me a stale piece of bread and the dregs of your wine after you were done digging my grave.</p>
<p><em>Rocco:</em> Okiedokie, off to tell Pizarro everything is ready.</p>
<p><em>Fidelionore:</em> Don&#8217;t worry, it&#8217;ll all work out. Somehow. Maybe. I hope.</p>
<hr />
<p><strong>Scene 3</strong></p>
<p><em>Pizarro:</em> All done?</p>
<p><em>Rocco:</em> All done.</p>
<p><em>Pizarro:</em> Send the kid away and untie the prisoner while I gloat over his impending doom and make sure to let him know at whose hand it will come.</p>
<p><em>Florestan:</em> Murderer!</p>
<p><em>Fidelionore:</em> Murderer!</p>
<p><em>Rocco:</em> Just following orders.</p>
<p><em>Fidelionore throws herself between Pizarro and Florestan</em></p>
<p><em>Fidelionore:</em> You&#8217;ll have to kill me first!</p>
<p><em>Pizarro:</em> Wut?</p>
<p><em>Fidelionore:</em> I&#8217;m his wife, dumbass. Did nobody notice the hips and the tits and the fact that I&#8217;m a ducking soprano?</p>
<p><em>Pizarro:</em> You&#8217;re his wife?</p>
<p><em>Rocco:</em> You&#8217;re his wife?</p>
<p><em>Florestan:</em> You&#8217;re my wife?</p>
<p><em>Pizarro:</em> Wow, you&#8217;re really brave.</p>
<p><em>Rocco:</em> Wow, you&#8217;re really brave.</p>
<p><em>Florestan:</em> Wow, you&#8217;re really brave.</p>
<p><em>Pizarro:</em> Shit, now I have to kill them both.</p>
<p><em>Fidelionore:</em> Well, sucks to be you.</p>
<p><em>The alarm sounds.</em></p>
<p><em>Fidelionore:</em> You&#8217;re saved!</p>
<p><em>Florestan:</em> I&#8217;m saved?</p>
<p><em>Pizarro:</em> Shit, Fernando!</p>
<p><em>Rocco:</em> We&#8217;re saved!</p>
<hr />
<p><strong>Scene 4</strong></p>
<p><em>Jaquino:</em> Hey boss, Secretary Fernando has arrived.</p>
<p><em>Rocco:</em> Send the guards down to, eh, ensure Pizarro gets safely up the stairs.</p>
<p><em>Fidelionore &amp; Florestan:</em> We&#8217;re saved!</p>
<p><em>Pizarro:</em> I&#8217;m doomed!</p>
<p><em>Rocco:</em> Remember, I was only following orders!</p>
<hr />
<p><strong>Scene 5</strong></p>
<p><em>Fidelionore:</em> You&#8217;re saved!</p>
<p><em>Florestan:</em> We gonna frick!</p>
<hr />
<p><strong>Scene 6</strong></p>
<p><em>Prisoners:</em> We&#8217;re free!</p>
<p><em>Fernando:</em> The King has sent me to free you!</p>
<p><em>Prisoners:</em> Bonus heart-wrenching chorus!</p>
<hr />
<p><strong>Scene 7</strong></p>
<p><em>Rocco:</em> Help! Help!</p>
<p><em>Pizarro:</em> Shut up!</p>
<p><em>Fernando:</em> What&#8217;s all this then?</p>
<p><em>Rocco:</em> Have mercy on Florestan—</p>
<p><em>Fernando:</em> Florestan? Isn&#8217;t he dead?</p>
<p><em>Rocco:</em> Only <em>mostly</em> dead. There&#8217;s a big difference between mostly dead and all dead. Mostly dead is slightly alive.</p>
<p><em>Fernando:</em> Florestan is slightly alive?</p>
<p><em>Fidelionore:</em> HE&#8217;S RIGHT IN FRONT OF YOU, YOU DUMBASS!</p>
<p><em>Rocco:</em> &#8230;with his wife Leonore! Dressed as a man!</p>
<p><em>Marzelline:</em> Oh shit.</p>
<p><em>Rocco:</em> Pizarro was going to murder him!</p>
<p><em>Pizarro:</em> And I would have gotten away with it too, if it weren&#8217;t for that meddling kid! Besides, you were helping.</p>
<p><em>Rocco:</em> For the last time, I was only following orders!</p>
<p><em>Pizarro is arrested and taken away</em></p>
<p><em>Fernando:</em> Here, Leonore, unshackle your husband.</p>
<p><em>Everybody:</em> WE&#8217;RE SO HAPPY!</p>
<p><em>Florestan:</em> Let this be a lesson to you all, the righteous always prevail in the end!</p>
<p><em>Fidelionore:</em> Not to mention Tru Wuv.</p>
<p><em>Everybody:</em> Yeah, yeah, we&#8217;re all very impressed.</p>
<p><em>Fidelionore:</em> We gonna frick!</p>
<hr />
<p><strong>TEH END</strong></p>
<p>Thank you, you&#8217;ve been a lovely audience.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.des.no/2017/04/fidelio-act-two/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Fidelio, Act One</title>
		<link>https://blog.des.no/2017/04/fidelio-act-one/</link>
					<comments>https://blog.des.no/2017/04/fidelio-act-one/#respond</comments>
		
		<dc:creator><![CDATA[Dag-Erling Smørgrav]]></dc:creator>
		<pubDate>Sun, 02 Apr 2017 14:16:09 +0000</pubDate>
				<category><![CDATA[English]]></category>
		<category><![CDATA[mixed bolts]]></category>
		<category><![CDATA[music]]></category>
		<guid isPermaLink="false">https://blog.des.no/?p=1183</guid>

					<description><![CDATA[I went to see a concert version of Fidelio at the Norwegian National Opera last night. For those of you who aren&#8217;t well versed in opera or in the classical or romantic eras of Western music, Fidelio is Beethoven&#8216;s only opera; initially written in 1804 under the title Leonore, oder Der Triumph der ehelichen Liebe, &#8230; <a href="https://blog.des.no/2017/04/fidelio-act-one/" class="more-link">Continue reading<span class="screen-reader-text"> "Fidelio, Act One"</span></a>]]></description>
										<content:encoded><![CDATA[<p>I went to see a <a href="http://operaen.no/en/Performances/fidelio/">concert version of <em>Fidelio</em></a> at the <a href="http://operaen.no/en/">Norwegian National Opera</a> last night. For those of you who aren&#8217;t well versed in opera or in the classical or romantic eras of Western music, <em>Fidelio</em> is <a href="https://en.wikipedia.org/wiki/Ludwig_van_Beethoven">Beethoven</a>&#8216;s only opera; initially written in 1804 under the title <em>Leonore, oder Der Triumph der ehelichen Liebe</em>, it took ten years and numerous rewrites before it became what we know today as <em>Fidelio</em>. I know <em>Fidelio</em> quite well, having owned a copy of <a href="https://www.discogs.com/release/4681819">Karajan&#8217;s 1970 recording</a> since my teens, but never really paid attention to the lyrics as a whole until I saw it on stage. I was mildly surprised at how progressive and (in places) possibly even scandalous they are, for their time. They deserve wider recognition. So without further ado, I present my abridged and somewhat&#8230; <em>improved</em> version of the libretto.<span id="more-1183"></span></p>
<hr />
<p><strong>Background</strong></p>
<p><em>Two years ago, Florestan uncovered evidence of his rival Pizarro&#8217;s crimes. Since then, he has been illegally detained by the latter in the prison he governs. Florestan&#8217;s wife Leonore has tracked Florestan down and obtained employment at the prison, disguised as a young man named Fidelio (because opera, that&#8217;s why). She has gradually gained warden Rocco&#8217;s trust. Prison guard Jaquino is infatuated with Rocco&#8217;s daughter Marzelline, who is infatuated with Fidelio (because opera, that&#8217;s why).</em></p>
<hr />
<p><strong>Scene 1</strong></p>
<p><em>Jaquino:</em> Finally got you cornered! I need to talk to you.</p>
<p><em>Marzelline:</em> Dude, I got work to do.</p>
<p><em>Jaquino:</em> Come on, give a guy a break!</p>
<p><em>Marzelline:</em> OK, spit it out. Just don&#8217;t expect me to like it.</p>
<p><em>Jaquino:</em> I&#8217;ve decided that you are to be my wife. We can have the wedding in a few weeks.</p>
<p><em>Marzelline:</em> LOL WUT</p>
<p><em>someone knocks</em></p>
<p><em>Jaquino:</em> PISS OFF I&#8217;M TRYING TO PROPOSE HERE</p>
<p><em>Marzelline:</em> Dude, I don&#8217;t even like you. I&#8217;m in love with Fidelio.</p>
<p><em>Jaquino:</em> What can I do to convince you?</p>
<p><em>knocking intensifies</em></p>
<p><em>Marzelline:</em> Good, maybe he&#8217;ll let me go now.</p>
<p><em>Rocco (off-stage):</em> Jaquino, you lazy good-for-nothing, get back to work!</p>
<p><em>Marzelline:</em> You heard the man, now scram!</p>
<p><em>Jaquino leaves</em></p>
<p><em>Marzelline:</em> Poor guy. I used to like him until I met Fidelio. Now <em>there&#8217;s</em> a man in touch with his feminine side!</p>
<hr />
<p><strong>Scene 2</strong></p>
<p><em>Marzelline pines for Fidelio</em></p>
<hr />
<p><strong>Scene 3</strong></p>
<p><em>Rocco:</em> Where the f&#8212; is Fidelio?</p>
<p><em>Marzelline:</em> Hell if I know. Oh, wait, there he is!</p>
<hr />
<p><strong>Scene 4</strong></p>
<p><em>Fidelionore:</em> Sorry, boss. Dude took for<em>ever</em>. Here&#8217;s the receipt.</p>
<p><em>Rocco:</em> Wow, how&#8217;d you talk the price down so much?</p>
<p><em>Fidelionore:</em> I try my best, boss.</p>
<p><em>Rocco:</em> Good man. Don&#8217;t worry, you&#8217;ll get what you&#8217;re after.</p>
<p><em>Fidelionore:</em> Say what now?</p>
<p><em>Rocco:</em> Oh come on, I know you like Marzelline.</p>
<p><em>Marzelline:</em> OMG OMG OMG FIDELIO LIKES ME OMG!</p>
<p><em>Fidelionore:</em> Oh shit.</p>
<p><em>Rocco:</em> I&#8217;m so happy for them!</p>
<p><em>Jaquino:</em> Oh shit.</p>
<p><em>Rocco:</em> Good, then it&#8217;s settled! We can have the wedding as soon as that ass Pizarro leaves for Sevilla.</p>
<p><em>Marzelline:</em> Squee!</p>
<p><em>Rocco:</em> One thing though, Fidelio. Promise me you&#8217;ll provide for my daughter. Love means nothing if you can&#8217;t put food on the table. Gold, gold, gold, gold, gold, gold, gold!</p>
<p><em>Fidelionore:</em> Well, I still maintain that true love&#8230; but there&#8217;s one thing that bothers me. Why don&#8217;t you trust me to accompany you down to the lower cells?</p>
<p><em>Rocco:</em> It&#8217;s not that I don&#8217;t trust you, it&#8217;s that I&#8217;m not allowed to let anyone near them.</p>
<p><em>Fidelionore:</em> But you work your fingers to the bone! Let me help.</p>
<p><em>Rocco:</em> Well, maybe. But I won&#8217;t let you near the oubliette. It&#8217;s too gruesome.</p>
<p><em>Marzelline:</em> Is that where the secret prisoner is kept?</p>
<p><em>Fidelionore:</em> Has he been there long?</p>
<p><em>Rocco:</em> Two years. And now Pizarro has ordered me to let him starve in the dark.</p>
<p><em>Marzelline:</em> Please don&#8217;t take Fidelio there, it&#8217;ll break his heart!</p>
<p><em>Fidelionore:</em> Are you calling me a wuss?</p>
<p><em>Rocco:</em> You need guts to get ahead in life, boy.</p>
<p><em>Fidelionore:</em> I got plenty. Try me.</p>
<p><em>Marzelline:</em> Your determination to see a man being starved to death makes me inexplicably proud.</p>
<p><em>Rocco:</em> Fine! I&#8217;ll ask the governor to allow you to assist me. I&#8217;m working myself to death as it is.</p>
<p><em>Marzelline:</em> I am <em>so</em> turned on right now.</p>
<hr />
<p><strong>Scene 5</strong></p>
<p><em>Pizarro storms in from who knows where</em></p>
<p><em>Pizarro:</em> Man the walls! Let no-one in without my express permission. Rocco, bring me my mail!</p>
<p><em>Rocco:</em> Here, sir.</p>
<p><em>Pizarro:</em> Bill—bill—advertising—overdue bill—Sears catalogue—final notice—pre-approved credit card—oh shit, I know that letterhead. “It has come to my attention that you are illegally keeping political prisoners, and I am therefore conducting a surprise inspection. You have a few hours to hide the evidence. XOXO Fernando.” Holy shit, he and Florestan were like <em>besties</em>. Captain! Post guards and sound the alarm the moment you see Secretary Fernando&#8217;s limo arrive!</p>
<p><em>Captain:</em> Sir, yes, sir!</p>
<p><em>Pizarro:</em> The only thing that can save me now is an act of unsurpassed bravery. And I will finally have my revenge, which I could have had at any time in the two years this man has been my prisoner, but inexplicably postponed! Oh, I can&#8217;t wait to see the knife twist in his heart! Rocco!</p>
<p><em>Rocco:</em> Sir?</p>
<p><em>Pizarro:</em> Rocco, I want you to prove my bravery, courage and high moral conviction by murdering this man in my place.</p>
<p><em>Rocco:</em> Let&#8217;s not, and say we did.</p>
<p><em>Pizarro:</em> Wuss. Never mind, I&#8217;ll do it myself. Go dig his grave while I put on an unconvincing disguise so I can tell myself it wasn&#8217;t really me who did it. And God help you if I get blood on my shoes!</p>
<p><em>Rocco:</em> Oh well. At least he won&#8217;t starve any more.</p>
<hr />
<p><strong>Scene 6</strong></p>
<p><em>Fidelionore:</em> WHAT THE F&#8212; JUST HAPPENED? I have to stop this.</p>
<hr />
<p><strong>Scene 7</strong></p>
<p><em>Jaquino:</em> Marzelline! You used to love me, but ever since this Fidelio&#8230;</p>
<p><em>Marzelline:</em> Leave me alone!</p>
<hr />
<p><strong>Scene 8</strong></p>
<p><em>Rocco:</em> Let it go, son. She doesn&#8217;t want you.</p>
<p><em>Fidelionore:</em> Rocco, won&#8217;t you please let the prisoners out into the sun? Pizarro doesn&#8217;t need to know.</p>
<p><em>Rocco:</em> Oh, why the hell not. Jaquino, Fidelio, open the upper cells!</p>
<hr />
<p><strong>Scene 9</strong></p>
<p><em>Prisoners:</em> Watch as we march dramatically out of our cells and sing a heart-wrenching chorus about how bad it is to imprison people for their political opinions! But not too loud, someone might hear us.</p>
<hr />
<p><strong>Scene 10</strong></p>
<p><em>Fidelionore:</em> How did it go?</p>
<p><em>Rocco:</em> He agreed to the wedding and to let you accompany me to the lower cells.</p>
<p><em>Fidelionore:</em> O frabjous day! Callooh! Callay!</p>
<p><em>Rocco:</em> What are you going on about? Anyway, we have to go down to the secret prisoner.</p>
<p><em>Fidelionore:</em> Is he being released?</p>
<p><em>Rocco:</em> Released? Oh, no, we are to bury him.</p>
<p><em>Fidelionore:</em> What?! He&#8217;s dead?</p>
<p><em>Rocco:</em> Well, not quite yet&#8230;</p>
<p><em>Fidelionore:</em> YOU&#8217;RE GOING TO KILL HIM?</p>
<p><em>Rocco:</em> No, just dig his grave and wash my hands of his murder.</p>
<p><em>Fidelionore starts crying</em></p>
<p><em>Rocco:</em> Oh, grow up. Let&#8217;s go.</p>
<hr />
<p><strong>Scene 11</strong></p>
<p><em>Marzelline:</em> Dad! Dad! Pizarro is looking for you, and let me tell you, he is PISSED. The guard captain told him we let the prisoners out. You know how mad he gets&#8230;</p>
<p><em>Rocco:</em> Oh shit. Quick, get everybody back inside.</p>
<hr />
<p><strong>Scene 12</strong></p>
<p><em>Pizarro:</em> Rocco! ROCCO! Who the FRACK gave you permission to let the prisoners out?</p>
<p><em>Rocco:</em> Well, uh, it&#8217;s, uh, spring, and also the King&#8217;s birthday or something? Also, I only let the regular prisoners out, not the secret one.</p>
<p><em>Pizarro:</em> Oh, shut up, and go dig that grave.</p>
<p><em>Prisoners:</em> We&#8217;re really sad to have to go back inside.</p>
<p><em>Marzelline:</em> I&#8217;m really sad to see the prisoners go back inside.</p>
<p><em>Fidelionore:</em> I&#8217;m really sad to see the prisoners go back inside.</p>
<p><em>Jaquino:</em> Oh, screw them.</p>
<p><em>Pizarro:</em> Off you go, Rocco, and stay there until the deed is done.</p>
<hr />
<p><strong>End of Act One</strong></p>
<hr />
<p>I&#8217;ll post Act Two as soon as that ass Pizarro leaves for Sevilla.</p>
<p><em>Update: <a href="https://blog.des.no/2017/04/fidelio-act-two/">Act Two</a></em></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.des.no/2017/04/fidelio-act-one/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Not up to our usual standards</title>
		<link>https://blog.des.no/2016/09/not-up-to-our-usual-standards/</link>
					<comments>https://blog.des.no/2016/09/not-up-to-our-usual-standards/#respond</comments>
		
		<dc:creator><![CDATA[Dag-Erling Smørgrav]]></dc:creator>
		<pubDate>Sun, 18 Sep 2016 13:54:17 +0000</pubDate>
				<category><![CDATA[English]]></category>
		<category><![CDATA[crypto]]></category>
		<category><![CDATA[FreeBSD]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[tech]]></category>
		<guid isPermaLink="false">https://blog.des.no/?p=1160</guid>

					<description><![CDATA[For a few years now, I&#8217;ve been working on and off on a set of libraries which collect cryptography- and security-related code I&#8217;ve written for other projects as well as functionality which is not already available under a permissive license, or where existing implementations do not meet my expectations of cleanliness, readability, portability and embeddability. &#8230; <a href="https://blog.des.no/2016/09/not-up-to-our-usual-standards/" class="more-link">Continue reading<span class="screen-reader-text"> "Not up to our usual standards"</span></a>]]></description>
										<content:encoded><![CDATA[<p>For a few years now, I&#8217;ve been working on and off on a <a href="https://github.com/cryb-to/cryb-to">set of libraries</a> which collect cryptography- and security-related code I&#8217;ve written for other projects as well as functionality which is not already available under a permissive license, or where existing implementations do not meet my expectations of cleanliness, readability, portability and embeddability.</p>
<p>(Aside: the reasons why this has taken years, when I initially expected to publish the first release in the spring or summer of 2014, are too complex to explain here; I may write about them at a later date. Keywords are health, family and world events.)</p>
<p>Two of the major features of that collection are the <a href="https://openauthentication.org/specifications-technical-resources/">OATH Authentication Methods</a> (which includes the algorithm used by Google Authenticator and a number of commercial one-time code fobs) and the <a href="https://scap.nist.gov/specifications/cpe/">Common Platform Enumeration</a>, part of the <a href="https://en.wikipedia.org/wiki/Security_Content_Automation_Protocol">Security Content Automation Protocol</a>. I implemented the former years ago for <a href="http://www.uio.no/">my employer</a>, and it has languished in the OpenPAM repository since 2012. The latter, however, has proven particularly elusive and frustrating, to the point where it has existed for two years as merely a header file and a set of mostly empty functions, just to sketch out the API. I decided to have another go at it yesterday, and actually made quite a bit of progress, only to hit the wall again. And this morning, I realized why.<span id="more-1160"></span></p>
<p>The CPE standard exists as a set of NIST Interagency reports: <a href="http://csrc.nist.gov/publications/nistir/ir7695/NISTIR-7695-CPE-Naming.pdf">NISTIR 7695</a> (naming), <a href="http://csrc.nist.gov/publications/nistir/ir7696/NISTIR-7696-CPE-Matching.pdf">NISTIR 7696</a> (name matching), <a href="http://csrc.nist.gov/publications/nistir/ir7696/NISTIR-7696-CPE-Matching.pdf">NISTIR 7697</a> (dictionary) and <a href="http://csrc.nist.gov/publications/nistir/ir7698/NISTIR-7698-CPE-Language.pdf">NISTIR 7698</a> (applicability language). The one I&#8217;ve been struggling with is 7695—it is the foundation for the other three, so I can&#8217;t get started on them until I&#8217;m done with 7695.</p>
<p>It should have been a breeze. On the surface, the specification seems quite thorough: basic concepts, representations, conversion between representations (including pseudocode). You know the kind of specification that you can read through once, then sit down at the computer, start from the top, and code your way down to the bottom? <a href="https://tools.ietf.org/html/rfc4226">RFC 4226</a> and <a href="https://tools.ietf.org/html/rfc6238">RFC 6238</a>, which describe OATH event-based and time-based one-time passwords respectively, are like that. NISTIR 7695 looks like it should be. But it isn&#8217;t. And I&#8217;ve been treating it like it was, with my nose so close to the code that I couldn&#8217;t see the big picture and realize that it is actually not very well written at all, and that the best way to implement it is to read it, understand it, and then set it aside before coding.</p>
<p>One sign that NISTIR 7695 is a bad specification is the pseudocode. It is common for specifications to describe algorithms, protocols and / or interfaces in the normative text and provide examples, pseudocode and / or a reference implementation (sometimes of dubious quality, as is the case for RFC 4226 and RFC 6238) as non-normative appendices. NISTIR 7695, however, eschews natural-language descriptions and includes pseudocode and examples in the normative text. By way of example, here is the description of the algorithm used to convert (“bind”, in their terminology) a well-formed name to a formatted string, <em>in its entirety</em>:</p>
<blockquote><p><strong>6.2.2.1 Summary of algorithm</strong></p>
<p>The procedure iterates over the eleven allowed attributes in a fixed order. Corresponding attribute values are obtained from the input WFN and conversions of logical values are applied. A result string is formed by concatenating the attribute values separated by colons.</p></blockquote>
<p>This is followed by one page of pseudocode and two pages of examples. But the examples are far from exhaustive; as unit tests, they wouldn&#8217;t even cover all of the common path, let alone any of the error handling paths. And the pseudocode looks like it was written by someone who learned Pascal in college thirty years ago and hasn&#8217;t programmed since.</p>
<p>The description of the reverse operation, converting a formatted string to a well-formed name, is slightly better in some respects and much worse in others. There is more pseudocode, and the examples include one—<em>one!</em>—instance of invalid input&#8230; but the pseudocode includes two functions—about one third of the total—which consist almost entirely of comments describing what the functions should do, rather than actual code.</p>
<p>You think I&#8217;m joking? Here is one of them:</p>
<pre><code>function get_comp_fs(fs,i)
  ;; Return the i’th field of the formatted string. If i=0,
  ;; return the string to the left of the first forward slash.
  ;; The colon is the field delimiter unless prefixed by a
  ;; backslash.
  ;; For example, given the formatted string:
  ;; cpe:2.3:a:foo:bar\:mumble:1.0:*:...
  ;; get_comp_fs(fs,0) = "cpe"
  ;; get_comp_fs(fs,1) = "2.3"
  ;; get_comp_fs(fs,2) = "a"
  ;; get_comp_fs(fs,3) = "foo"
  ;; get_comp_fs(fs,4) = "bar\:mumble"
  ;; get_comp_fs(fs,5) = "1.0"
  ;; etc.
end.
</code></pre>
<p>This function shouldn&#8217;t even exist. It should just be a lookup in an associative array, or a call to an accessor if the pseudocode was object-oriented. So why <em>does</em> it exist? Because the main problem with NISTIR 7695, which I should have identified on my first read-through but stupidly didn&#8217;t, is that it assumes that implementations would use well-formed names—a <em>textual representation</em> of a CPE name—as their <em>internal representation</em>. The bind and unbind functions, which should be described in terms of how to format and parse URIs and formatted strings, are instead described in terms of how to convert to and from WFNs. I cannot overstate how wrong this is. A specification should never describe a particular internal representation, except in a non-normative reference implementation, because it prevents conforming implementations from choosing more efficient representations, or representations which are better suited to a particular language and environment, and because it leads to this sort of nonsense.</p>
<p>So, is the CPE naming specification salvageable? Well, it includes complete ABNF grammars for URIs and formatted strings, which is good, and a <em>partial</em> ABNF grammar for well-formed names, which is&#8230; less good, but fixable. It also explains the meanings of the different fields; it would be useless otherwise. But apart from that, and the boilerplate at the top and bottom, it should be completely rewritten, including the pseudocode and examples, which should reference fictional, rather than real, vendors and products. Here is how I would structure it (text in <em>italic</em> is carried over from the original):</p>
<ol>
<li><em>Introduction</em><br />
1.1. <em>Purpose and scope</em><br />
1.2. <em>Document structure</em><br />
1.3. <em>Document conventions</em><br />
1.4. <em>Relationship to existing specifications and standards</em></li>
<li><em>Definitions and abbreviations</em></li>
<li><em>Conformance</em></li>
<li>CPE data model<br />
4.1 Required attributes<br />
4.2 Optional attributes<br />
4.3 Special attribute values</li>
<li>Textual representations<br />
5.1. Well-formed name<br />
5.2. URI<br />
5.3. Formatted string</li>
<li>API<br />
6.1. Creating and destroying names<br />
6.2. Setting and getting attributes<br />
6.3. Binding and unbinding</li>
<li>Non-normative examples<br />
7.1. Valid and invalid attribute values<br />
7.2. Valid and invalid well-formed names<br />
7.3. Valid and invalid URIs<br />
7.4. Valid and invalid formatted strings</li>
<li>Non-normative pseudo-code</li>
<li><em>References</em></li>
<li><em>Change log</em></li>
</ol>
<p>I&#8217;m still going to implement CPE naming, but I&#8217;m going to implement it the way I think the standard should have been written, not the way it actually <em>was</em> written. Amusingly, the conformance chapter is so vague that I can do this and still claim conformance with the Terrible, Horrible, No Good, Very Bad specification. And it should only take a few hours.</p>
<p>By the way, if anybody from MITRE or NIST reads this and genuinely wants to improve the specification, I&#8217;ll be happy to help.</p>
<p><em>PS: possibly my favorite feature of NISTIR 7695, and additional proof that the authors are not programmers: the specification mandates that WFNs are UTF-8 strings, which are fine for storage and transmission but horrible to work with in memory. But in the next sentence, it notes that only characters with hexadecimal values between x00 and x7F may be used, and subsequent sections further restrict the set of allowable characters. In case you didn&#8217;t know, the normalized UTF-8 representation of a sequence of characters with hexadecimal values between x00 and x7F is identical, bit by bit, to the ASCII representation of the same sequence.</em></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.des.no/2016/09/not-up-to-our-usual-standards/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>How to solve every problem in the world</title>
		<link>https://blog.des.no/2016/04/how-to-solve-every-problem-in-the-world/</link>
					<comments>https://blog.des.no/2016/04/how-to-solve-every-problem-in-the-world/#respond</comments>
		
		<dc:creator><![CDATA[Dag-Erling Smørgrav]]></dc:creator>
		<pubDate>Wed, 20 Apr 2016 07:28:30 +0000</pubDate>
				<category><![CDATA[English]]></category>
		<category><![CDATA[mixed bolts]]></category>
		<category><![CDATA[oh really?]]></category>
		<guid isPermaLink="false">https://blog.des.no/?p=1140</guid>

					<description><![CDATA[Identify a complex problem in country A which is deeply rooted in that country&#8217;s demography / economy / culture / political system. Point out that country B, which has a completely different demography / economy / culture / political system, does not have that problem or has found a simple solution to it. Declare that &#8230; <a href="https://blog.des.no/2016/04/how-to-solve-every-problem-in-the-world/" class="more-link">Continue reading<span class="screen-reader-text"> "How to solve every problem in the world"</span></a>]]></description>
										<content:encoded><![CDATA[<ol>
<li>Identify a complex problem in country A which is deeply rooted in that country&#8217;s demography / economy / culture / political system.</li>
<li>Point out that country B, which has a completely different demography / economy / culture / political system, does not have that problem or has found a simple solution to it.</li>
<li>Declare that the problem is trivial and that country A are idiots for having it in the first place.</li>
<li>Job done, have a beer.</li>
</ol>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.des.no/2016/04/how-to-solve-every-problem-in-the-world/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>FreeBSD and CVE-2015-7547</title>
		<link>https://blog.des.no/2016/02/freebsd-and-cve-2015-7547/</link>
					<comments>https://blog.des.no/2016/02/freebsd-and-cve-2015-7547/#comments</comments>
		
		<dc:creator><![CDATA[Dag-Erling Smørgrav]]></dc:creator>
		<pubDate>Wed, 17 Feb 2016 17:53:34 +0000</pubDate>
				<category><![CDATA[English]]></category>
		<category><![CDATA[DNS]]></category>
		<category><![CDATA[FreeBSD]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[tech]]></category>
		<category><![CDATA[Unbound]]></category>
		<guid isPermaLink="false">https://blog.des.no/?p=1116</guid>

					<description><![CDATA[As you have probably heard by now, a buffer overflow was recently discovered in GNU libc’s resolver code which can allow a malicious DNS server to inject code into a vulnerable client. This was announced yesterday as CVE-2015-7547. The best sources of information on the bug are currently Google’s Online Security Blog and Carlos O’Donnell’s &#8230; <a href="https://blog.des.no/2016/02/freebsd-and-cve-2015-7547/" class="more-link">Continue reading<span class="screen-reader-text"> "FreeBSD and CVE-2015-7547"</span></a>]]></description>
										<content:encoded><![CDATA[<p>As you have probably heard by now, a buffer overflow was recently discovered in <a href="https://www.gnu.org/software/libc/">GNU libc</a>’s resolver code which can allow a malicious DNS server to inject code into a vulnerable client. This was announced yesterday as <a href="https://access.redhat.com/security/cve/cve-2015-7547">CVE-2015-7547</a>. The best sources of information on the bug are currently <a href="https://googleonlinesecurity.blogspot.no/2016/02/cve-2015-7547-glibc-getaddrinfo-stack.html">Google’s Online Security Blog</a> and <a href="https://sourceware.org/ml/libc-alpha/2016-02/msg00416.html">Carlos O’Donnell’s in-depth analysis</a>.</p>
<p>Naturally, people have started asking whether FreeBSD is affected. The FreeBSD Security Officer has not yet released an official statement, but in the meantime, here is a brief look at the issue as far as FreeBSD is concerned.</p>
<p><span id="more-1116"></span></p>
<p>First of all: <strong>neither FreeBSD itself nor native FreeBSD applications are affected</strong>. While the resolver in FreeBSD’s libc and GNU libc share a common ancestry, the bug was introduced when the latter was rewritten to send <code>A</code> and <code>AAAA</code> queries in parallel rather than sequentially when the application requests both.</p>
<p>However, Linux applications running under emulation on a FreeBSD system use the GNU libc and are therefore vulnerable unless patched. I believe, but have not verified, that <del>the <a href="https://www.freshports.org/emulators/linux_base-c6/">linux_base-c6</a> port contains a vulnerable version of GNU libc</del> while the older <a href="https://www.freshports.org/emulators/linux_base-f10/">linux_base-f10</a> port does not. For now, it is safest to assume that they are both vulnerable.</p>
<p><em><strong>UPDATE</strong> 2016-02-17 18:40 UTC: the linux_base-c6 port <a href="http://svnweb.freebsd.org/ports?view=revision&amp;revision=409060&amp;limit_changes=0">has been updated</a> in ports-head, <del>2016Q1 branch to follow,</del> no word on linux_base-f10</em></p>
<p><em><strong>UPDATE</strong> 2016-02-18 00:15 UTC: the quarterly branch <a href="http://svnweb.freebsd.org/ports?view=revision&amp;revision=409078&amp;limit_changes=0">has been updated</a></em></p>
<p>The issue can be mitigated by only using resolvers you trust, and configuring them to avoid sending responses which can trigger the bug.</p>
<p>If you already have your own resolvers, you can configure them to avoid sending UDP responses larger than 2048 bytes. If the response does not fit in 2048 bytes, the server will send a truncated response, and the client should retry using TCP. While a similar bug exists in the code path for TCP requests, I believe that it can only be exploited by a malicious resolver, and interposing your own resolver will protect affected Linux systems and applications.</p>
<ul>
<li>
<p>If your resolvers run <a href="https://www.isc.org/downloads/bind/">BIND</a>, add the following line to the <code>options</code> section in <code>named.conf</code> (note the semicolon!):</p>
<pre><code>max-udp-size 2048;
</code></pre>
</li>
<li>
<p>If your resolvers run <a href="https://www.unbound.net/">Unbound</a>, add the following line to the <code>server</code> section in <code>unbound.conf</code> (no semicolon!):</p>
<pre><code>max-udp-size: 2048
</code></pre>
</li>
<li>
<p>If your resolvers run something else, please consult the documentation and look for a way to restrict the size of UDP responses to 2048 bytes.</p>
</li>
</ul>
<p>If you do not already have your own resolvers, you can set one up in a couple of minutes as follows:</p>
<pre><code># pkg install -y unbound
# fetch -o /usr/local/etc/unbound https://blog.des.no/wp-content/uploads/2016/02/unbound.conf
# vi /usr/local/etc/unbound/unbound.conf
  ... fix access-control statements as mentioned in comments ...
# echo 'unbound_enable="yes"' &gt;&gt;/etc/rc.conf
# service unbound start
</code></pre>
<p><em>(<a href="https://blog.des.no/wp-content/uploads/2016/02/unbound.conf">link to the config file</a>)</em></p>
<p>You must then edit <code>/etc/resolv.conf</code> on all affected systems to point to your new resolver. If you are running Linux applications under emulation, make sure that there is no <code>/compat/linux/etc/resolv.conf</code>, as it would override the system-wide <code>/etc/resolv.conf</code>.</p>
<p>Note that unlike FreeBSD libc, GNU libc does not automatically pick up changes to <code>/etc/resolv.conf</code>, so you will have to restart all affected Linux services and applications.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.des.no/2016/02/freebsd-and-cve-2015-7547/feed/</wfw:commentRss>
			<slash:comments>12</slash:comments>
		
		
			</item>
		<item>
		<title>Samples from my Inbox, pt 3</title>
		<link>https://blog.des.no/2016/01/samples-from-my-inbox-pt-3/</link>
					<comments>https://blog.des.no/2016/01/samples-from-my-inbox-pt-3/#respond</comments>
		
		<dc:creator><![CDATA[Dag-Erling Smørgrav]]></dc:creator>
		<pubDate>Mon, 11 Jan 2016 08:29:03 +0000</pubDate>
				<category><![CDATA[English]]></category>
		<category><![CDATA[mixed bolts]]></category>
		<category><![CDATA[oh really?]]></category>
		<category><![CDATA[spam]]></category>
		<guid isPermaLink="false">https://blog.des.no/?p=1107</guid>

					<description><![CDATA[(part 1, part 2) Bottom of the barrel here. Take a look at good health products checks backpack Lamotrigine, Rizatriptan, Diclofenac and Zopiclone (prescription), Paracetamol and Ibuprofen (over-the-counter) and three sets of single-use contact lenses. Oh, does WD-40 count? Time for great nights with your female partner Not bloody likely, what with my chronic insomnia. &#8230; <a href="https://blog.des.no/2016/01/samples-from-my-inbox-pt-3/" class="more-link">Continue reading<span class="screen-reader-text"> "Samples from my Inbox, pt 3"</span></a>]]></description>
										<content:encoded><![CDATA[<p><span style="font-style: italic; font-size: small">(<a href="/2016/01/samples-from-my-inbox/">part 1</a>, <a href="/2016/01/samples-from-my-inbox-pt-2/">part 2</a>)</span></p>
<p>Bottom of the barrel here.</p>
<h3>Take a look at good health products</h3>
<p><em>checks backpack</em> Lamotrigine, Rizatriptan, Diclofenac and Zopiclone (prescription), Paracetamol and Ibuprofen (over-the-counter) and three sets of single-use contact lenses. Oh, does WD-40 count?</p>
<h3>Time for great nights with your female partner</h3>
<p>Not bloody likely, what with my chronic insomnia.</p>
<h3>Your girlfriend wants you to be the best</h3>
<p>That&#8217;s the great thing about a healthy relationship, we both want each other to succeed and support each other&#8217;s endeavors.</p>
<h3>Here you will find some photos</h3>
<p>Hey, I&#8217;ve been looking for those! Thanks for finding that memory card.</p>
<h3>The easiest way to gain more health</h3>
<p>Look, I know I could stand to lose a few pounds, but I&#8217;m already eating relatively healthy and there&#8217;s nothing easy about working out regularly, especially with a busted knee. Now get off my case!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.des.no/2016/01/samples-from-my-inbox-pt-3/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
