<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://m6w6.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://m6w6.github.io/" rel="alternate" type="text/html" /><updated>2025-01-06T17:15:02+00:00</updated><id>https://m6w6.github.io/feed.xml</id><title type="html">Michael Wallner (m6w6)</title><subtitle>C/C++ writer. PHP partisan. Postgres fan. GNU/Linux hacker. Webophilic op. &lt;br&gt; Father of two. Wide open throttle. Photographer in another life.</subtitle><entry><title type="html">Debian: disabling SSLv3 in courier server</title><link href="https://m6w6.github.io/2016/04/debian-disabling-sslv3-in-courier-server.html" rel="alternate" type="text/html" title="Debian: disabling SSLv3 in courier server" /><published>2016-04-16T00:00:00+00:00</published><updated>2016-04-16T00:00:00+00:00</updated><id>https://m6w6.github.io/2016/04/debian-disabling-sslv3-in-courier-server</id><content type="html" xml:base="https://m6w6.github.io/2016/04/debian-disabling-sslv3-in-courier-server.html"><![CDATA[<p>Debian wheezy (currently oldstable) ships courier-0.68 which was probably released on 2012. 
“Probably”, because, head over to the <a href="http://www.courier-mta.org/">Courier website</a> and 
try to find the NEWS/ChangeLog.</p>

<h2 id="the-problem">The Problem</h2>

<p>Anyway. Courier-0.68 has built-in openssl support on Debian and it initializes a SSL 
context the following way:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">ctx</span><span class="o">=</span><span class="n">SSL_CTX_new</span><span class="p">(</span><span class="n">protocol</span> <span class="o">&amp;&amp;</span> <span class="n">strcmp</span><span class="p">(</span><span class="n">protocol</span><span class="p">,</span> <span class="s">"SSL3"</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span>
                <span class="o">?</span> <span class="n">SSLv3_method</span><span class="p">()</span><span class="o">:</span>
                <span class="n">protocol</span> <span class="o">&amp;&amp;</span> <span class="n">strcmp</span><span class="p">(</span><span class="n">protocol</span><span class="p">,</span> <span class="s">"SSL23"</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span>
                <span class="o">?</span> <span class="n">SSLv23_method</span><span class="p">()</span><span class="o">:</span>
                <span class="n">TLSv1_method</span><span class="p">());</span>

<span class="c1">// ...</span>
<span class="n">SSL_CTX_set_options</span><span class="p">(</span><span class="n">ctx</span><span class="p">,</span> <span class="n">SSL_OP_ALL</span><span class="p">);</span>

<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">ssl_cipher_list</span><span class="p">)</span>
        <span class="n">ssl_cipher_list</span><span class="o">=</span><span class="s">"SSLv3:TLSv1:HIGH:!LOW:!MEDIUM:!EXP:!NULL:!aNULL@STRENGTH"</span><span class="p">;</span>

<span class="n">SSL_CTX_set_cipher_list</span><span class="p">(</span><span class="n">ctx</span><span class="p">,</span> <span class="n">ssl_cipher_list</span><span class="p">);</span>
</code></pre></div></div>

<h4 id="some-clarifications">Some clarifications:</h4>

<ul>
  <li><code class="language-shell highlighter-rouge">SSLv3_method</code> would <strong>only</strong> allow SSLv3</li>
  <li><code class="language-shell highlighter-rouge">TLSv1_method</code> would <strong>only</strong> allow TLSv1.0</li>
  <li><code class="language-shell highlighter-rouge">SSLv23_method</code> is “the general-purpose version-flexible SSL/TLS method”</li>
</ul>

<p>So, if we do not want to limit ourselves to TLSv1.0, i.e. allow TLSv1.0, TLSv1.1 and TLSv1.2, 
we have to limit our protocol version support through other means.</p>

<p>Openssl-1.0.1 (remember, we’re on Debian wheezy) does neither come with <code class="language-shell highlighter-rouge">TLS_method<span class="o">()</span></code> the 
generic TLS-only method, nor does it come with <code class="language-shell highlighter-rouge">SSL_CTX_set_min_proto_version</code> and we cannot 
disable SSLv3 with the cipher list if we also want to allow TLSv1.0.</p>

<h2 id="solution-1-upgrading-to-jessie">Solution 1: Upgrading to Jessie</h2>

<p>What if we upgrade to Debian jessie (current stable)? Jessie ships courier-0.73, so let’s see 
how SSL context intitialization looks there:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">options</span><span class="o">=</span><span class="n">SSL_OP_ALL</span><span class="p">;</span>

<span class="n">method</span><span class="o">=</span><span class="p">((</span><span class="o">!</span><span class="n">protocol</span> <span class="o">||</span> <span class="o">!*</span><span class="n">protocol</span><span class="p">)</span>
        <span class="o">?</span> <span class="nb">NULL</span><span class="o">:</span>
        <span class="n">strcmp</span><span class="p">(</span><span class="n">protocol</span><span class="p">,</span> <span class="s">"SSL3"</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span>
                <span class="o">?</span> <span class="n">SSLv3_method</span><span class="p">()</span><span class="o">:</span>
        <span class="n">strcmp</span><span class="p">(</span><span class="n">protocol</span><span class="p">,</span> <span class="s">"SSL23"</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span>
                <span class="o">?</span> <span class="n">SSLv23_method</span><span class="p">()</span><span class="o">:</span>
        <span class="n">strcmp</span><span class="p">(</span><span class="n">protocol</span><span class="p">,</span> <span class="s">"TLSv1"</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span>
        <span class="o">?</span> <span class="n">TLSv1_method</span><span class="p">()</span><span class="o">:</span>
<span class="cp">#ifdef HAVE_TLSV1_1_METHOD
</span>        <span class="n">strcmp</span><span class="p">(</span><span class="n">protocol</span><span class="p">,</span> <span class="s">"TLSv1.1"</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span>
        <span class="o">?</span> <span class="n">TLSv1_1_method</span><span class="p">()</span><span class="o">:</span>
<span class="cp">#endif
#ifdef HAVE_TLSV1_2_METHOD
</span>        <span class="n">strcmp</span><span class="p">(</span><span class="n">protocol</span><span class="p">,</span> <span class="s">"TLSv1.2"</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span>
        <span class="o">?</span> <span class="n">TLSv1_2_method</span><span class="p">()</span><span class="o">:</span>
<span class="cp">#endif
</span>        <span class="nb">NULL</span><span class="p">);</span>

<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">method</span><span class="p">)</span>
<span class="p">{</span>
        <span class="n">method</span><span class="o">=</span><span class="n">SSLv23_method</span><span class="p">();</span>
        <span class="n">options</span><span class="o">|=</span><span class="n">SSL_OP_NO_SSLv2</span><span class="p">;</span>
<span class="p">}</span>

<span class="n">ctx</span><span class="o">=</span><span class="n">SSL_CTX_new</span><span class="p">(</span><span class="n">method</span><span class="p">);</span>

<span class="c1">// ...</span>
<span class="n">SSL_CTX_set_options</span><span class="p">(</span><span class="n">ctx</span><span class="p">,</span> <span class="n">options</span><span class="p">);</span>

<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">ssl_cipher_list</span><span class="p">)</span>
        <span class="n">ssl_cipher_list</span><span class="o">=</span><span class="s">"SSLv3:TLSv1:HIGH:!LOW:!MEDIUM:!EXP:!NULL:!aNULL@STRENGTH"</span><span class="p">;</span>

<span class="n">SSL_CTX_set_cipher_list</span><span class="p">(</span><span class="n">ctx</span><span class="p">,</span> <span class="n">ssl_cipher_list</span><span class="p">);</span>
</code></pre></div></div>

<p>Jessie also comes with openssl-1.0.1, so the situation would not improve for our undertaking 
by upgrading to jessie.</p>

<h2 id="solution-2-augmenting-ssl_ctx_new">Solution 2: Augmenting SSL_CTX_new</h2>

<p>What I came up with, is augmenting <code class="language-shell highlighter-rouge">SSL_CTX_new</code> and setting the desired <code class="language-shell highlighter-rouge">SSL_OP_NO_SSLv3</code> on 
each newly created SSL context.</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;dlfcn.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;openssl/ssl.h&gt;</span><span class="cp">
</span>
<span class="k">static</span> <span class="kt">void</span> <span class="o">*</span><span class="n">lib</span><span class="p">;</span>
<span class="k">static</span> <span class="kt">void</span> <span class="o">*</span><span class="n">new_sym</span><span class="p">;</span>
<span class="k">static</span> <span class="kt">void</span> <span class="o">*</span><span class="n">opt_sym</span><span class="p">;</span>

<span class="k">static</span> <span class="kt">void</span> <span class="nf">dl</span><span class="p">()</span> <span class="p">{</span>
        <span class="kt">char</span> <span class="o">*</span><span class="n">error</span><span class="p">;</span>

        <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">lib</span><span class="p">)</span> <span class="p">{</span>
                <span class="n">lib</span> <span class="o">=</span> <span class="n">dlopen</span><span class="p">(</span><span class="s">"libssl.so"</span><span class="p">,</span> <span class="n">RTLD_LAZY</span><span class="o">|</span><span class="n">RTLD_LOCAL</span><span class="p">);</span>
                <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">lib</span><span class="p">)</span> <span class="p">{</span>
                        <span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">"dlopen: %s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">dlerror</span><span class="p">());</span>
                        <span class="n">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
                <span class="p">}</span>   
                <span class="n">dlerror</span><span class="p">();</span>
        <span class="p">}</span>   
    
        <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">new_sym</span><span class="p">)</span> <span class="p">{</span>
                <span class="o">*</span><span class="p">(</span><span class="kt">void</span> <span class="o">**</span><span class="p">)</span> <span class="o">&amp;</span><span class="n">new_sym</span> <span class="o">=</span> <span class="n">dlsym</span><span class="p">(</span><span class="n">lib</span><span class="p">,</span> <span class="s">"SSL_CTX_new"</span><span class="p">);</span>
                <span class="k">if</span> <span class="p">((</span><span class="n">error</span> <span class="o">=</span> <span class="n">dlerror</span><span class="p">()))</span> <span class="p">{</span>
                        <span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">"dlsym: %s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">error</span><span class="p">);</span>
                        <span class="n">dlclose</span><span class="p">(</span><span class="n">lib</span><span class="p">);</span>
                        <span class="n">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
                <span class="p">}</span>   
        <span class="p">}</span>   

        <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">opt_sym</span><span class="p">)</span> <span class="p">{</span>
                <span class="o">*</span><span class="p">(</span><span class="kt">void</span> <span class="o">**</span><span class="p">)</span> <span class="o">&amp;</span><span class="n">opt_sym</span> <span class="o">=</span> <span class="n">dlsym</span><span class="p">(</span><span class="n">lib</span><span class="p">,</span> <span class="s">"SSL_CTX_ctrl"</span><span class="p">);</span>
                <span class="k">if</span> <span class="p">((</span><span class="n">error</span> <span class="o">=</span> <span class="n">dlerror</span><span class="p">()))</span> <span class="p">{</span>
                        <span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">"dlsym: %s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">error</span><span class="p">);</span>
                        <span class="n">dlclose</span><span class="p">(</span><span class="n">lib</span><span class="p">);</span>
                        <span class="n">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
                <span class="p">}</span>   
        <span class="p">}</span>   
<span class="p">}</span>

<span class="n">SSL_CTX</span> <span class="o">*</span><span class="nf">SSL_CTX_new</span><span class="p">(</span><span class="k">const</span> <span class="n">SSL_METHOD</span> <span class="o">*</span><span class="n">m</span><span class="p">)</span> 
<span class="p">{</span>
        <span class="n">SSL_CTX</span> <span class="o">*</span><span class="n">ctx</span><span class="p">;</span>

        <span class="n">dl</span><span class="p">();</span>

        <span class="n">ctx</span> <span class="o">=</span> <span class="p">((</span><span class="n">SSL_CTX</span> <span class="o">*</span><span class="p">(</span><span class="o">*</span><span class="p">)(</span><span class="k">const</span> <span class="n">SSL_METHOD</span><span class="o">*</span><span class="p">))</span><span class="n">new_sym</span><span class="p">)(</span><span class="n">m</span><span class="p">);</span>

        <span class="k">if</span> <span class="p">(</span><span class="n">ctx</span><span class="p">)</span> <span class="p">{</span>
                <span class="p">((</span><span class="kt">long</span> <span class="p">(</span><span class="o">*</span><span class="p">)(</span><span class="n">SSL_CTX</span> <span class="o">*</span><span class="p">,</span> <span class="kt">int</span><span class="p">,</span> <span class="kt">long</span><span class="p">,</span> <span class="kt">void</span><span class="o">*</span><span class="p">))</span><span class="n">opt_sym</span><span class="p">)(</span><span class="n">ctx</span><span class="p">,</span> <span class="n">SSL_CTRL_OPTIONS</span><span class="p">,</span> <span class="n">SSL_OP_ALL</span><span class="o">|</span><span class="n">SSL_OP_NO_SSLv2</span><span class="o">|</span><span class="n">SSL_OP_NO_SSLv3</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">);</span>
        <span class="p">}</span>   
        <span class="k">return</span> <span class="n">ctx</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>This is the source of a tiny shared library pre-defining our <code class="language-shell highlighter-rouge">SSL_CTX_new</code>; to build like e.g.</p>

<p><code class="language-shell highlighter-rouge">gcc <span class="nt">-ldl</span> <span class="nt">-fPIC</span> <span class="nt">-shared</span> <span class="nt">-o</span> preload.so preload.c</code></p>

<p>It does the following:</p>

<ul>
  <li>augments <code class="language-shell highlighter-rouge">SSL_CTX_new</code> with our own version, 
i.e. whenever courier calls <code class="language-shell highlighter-rouge">SSL_CTX_new</code> our own version gets called</li>
  <li>when it’s called the first time, it</li>
  <li><code class="language-shell highlighter-rouge">dlopen</code>’s libssl</li>
  <li>fetches the addresses of the original <code class="language-shell highlighter-rouge">SSL_CTX_new</code> and <code class="language-shell highlighter-rouge">SSL_CTX_ctrl</code> 
(which is the actual function <code class="language-shell highlighter-rouge">SSL_CTX_set_options</code> calls)</li>
  <li>calls the original <code class="language-shell highlighter-rouge">SSL_CTX_new</code> to actually create the SSL context</li>
  <li>calls <code class="language-shell highlighter-rouge">SSL_CTX_ctrl</code> on the new context with the options we want to set (<code class="language-shell highlighter-rouge">SSL_OP_NO_SSLv3</code>)</li>
  <li>returns the context to the caller</li>
</ul>

<h3 id="usage">Usage</h3>

<p>Courier config files are basically shell scripts which set a environment variables, so we’ll 
enable it as follows:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cd</span> /etc/courier
<span class="nb">cat</span> <span class="o">&gt;&gt;</span>esmtpd <span class="o">&gt;&gt;</span>esmtpd-msa <span class="o">&gt;&gt;</span>esmtpd-ssl <span class="se">\</span>
    <span class="o">&gt;&gt;</span>pop3d <span class="o">&gt;&gt;</span>pop3d-ssl <span class="se">\</span>
    <span class="o">&gt;&gt;</span>imapd <span class="o">&gt;&gt;</span>imapd-ssl <span class="se">\</span>
    <span class="o">&gt;&gt;</span>courierd <span class="o">&lt;&lt;</span><span class="no">EOF</span><span class="sh">
LD_PRELOAD=/path/to/preload.so
</span><span class="no">EOF
</span></code></pre></div></div>

<p>Then restart each courier service.</p>

<h3 id="verifying">Verifying</h3>

<p>Last, we have to verify that our solution actually works:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>openssl s_client <span class="se">\</span>
	<span class="nt">-CApath</span> /etc/ssl/certs/ <span class="se">\</span>
	<span class="nt">-starttls</span> imap <span class="se">\</span>
	<span class="nt">-connect</span> localhost:143 <span class="se">\</span>
	<span class="nt">-crlf</span> <span class="nt">-quiet</span> <span class="nt">-ssl3</span> <span class="se">\</span>
	<span class="o">&lt;&lt;&lt;</span>LOGOUT
139690858608296:error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure:s3_pkt.c:1261:SSL alert number 40
139690858608296:error:1409E0E5:SSL routines:SSL3_WRITE_BYTES:ssl handshake failure:s3_pkt.c:599:
</code></pre></div></div>

<p>A bunch of errors. “Good”! :)</p>

<p>Let’s see if we can still connect with TLSv1+:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>openssl s_client <span class="se">\</span>
	<span class="nt">-CApath</span> /etc/ssl/certs/ <span class="se">\</span>
	<span class="nt">-starttls</span> imap <span class="se">\</span>
	<span class="nt">-connect</span> localhost:143 <span class="se">\</span>
	<span class="nt">-crlf</span> <span class="nt">-quiet</span> <span class="nt">-tls1</span> <span class="se">\</span>
	<span class="o">&lt;&lt;&lt;</span>LOGOUT
<span class="nv">depth</span><span class="o">=</span>2 ...
verify <span class="k">return</span>:1
<span class="nv">depth</span><span class="o">=</span>1 ...
verify <span class="k">return</span>:1
<span class="nv">depth</span><span class="o">=</span>0 ...
verify <span class="k">return</span>:1
<span class="nb">.</span> OK CAPABILITY completed
<span class="k">*</span> BYE Courier-IMAP server shutting down
LOGOUT OK LOGOUT completed
</code></pre></div></div>

<p>Awesome. Mission accomplished.</p>

<h2 id="addendum">Addendum</h2>

<p>Here’s my cipher list for the interested:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>openssl ciphers <span class="nt">-v</span> <span class="s1">'HIGH+aRSA:+kEDH:+kRSA:+SHA:+3DES:!kSRP'</span> <span class="se">\</span>
  | <span class="nb">awk</span> <span class="s1">'{ printf "%-28s %-8s %-8s %-18s %-16s\n",$1,$2,$3,$5,$6 }'</span>
</code></pre></div></div>

<p>Which results in the following ciphers:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ECDHE-RSA-AES256-GCM-SHA384  TLSv1.2  <span class="nv">Kx</span><span class="o">=</span>ECDH  <span class="nv">Enc</span><span class="o">=</span>AESGCM<span class="o">(</span>256<span class="o">)</span>    <span class="nv">Mac</span><span class="o">=</span>AEAD
ECDHE-RSA-AES256-SHA384      TLSv1.2  <span class="nv">Kx</span><span class="o">=</span>ECDH  <span class="nv">Enc</span><span class="o">=</span>AES<span class="o">(</span>256<span class="o">)</span>       <span class="nv">Mac</span><span class="o">=</span>SHA384
ECDHE-RSA-AES128-GCM-SHA256  TLSv1.2  <span class="nv">Kx</span><span class="o">=</span>ECDH  <span class="nv">Enc</span><span class="o">=</span>AESGCM<span class="o">(</span>128<span class="o">)</span>    <span class="nv">Mac</span><span class="o">=</span>AEAD
ECDHE-RSA-AES128-SHA256      TLSv1.2  <span class="nv">Kx</span><span class="o">=</span>ECDH  <span class="nv">Enc</span><span class="o">=</span>AES<span class="o">(</span>128<span class="o">)</span>       <span class="nv">Mac</span><span class="o">=</span>SHA256
DHE-RSA-AES256-GCM-SHA384    TLSv1.2  <span class="nv">Kx</span><span class="o">=</span>DH    <span class="nv">Enc</span><span class="o">=</span>AESGCM<span class="o">(</span>256<span class="o">)</span>    <span class="nv">Mac</span><span class="o">=</span>AEAD
DHE-RSA-AES256-SHA256        TLSv1.2  <span class="nv">Kx</span><span class="o">=</span>DH    <span class="nv">Enc</span><span class="o">=</span>AES<span class="o">(</span>256<span class="o">)</span>       <span class="nv">Mac</span><span class="o">=</span>SHA256
DHE-RSA-AES128-GCM-SHA256    TLSv1.2  <span class="nv">Kx</span><span class="o">=</span>DH    <span class="nv">Enc</span><span class="o">=</span>AESGCM<span class="o">(</span>128<span class="o">)</span>    <span class="nv">Mac</span><span class="o">=</span>AEAD
DHE-RSA-AES128-SHA256        TLSv1.2  <span class="nv">Kx</span><span class="o">=</span>DH    <span class="nv">Enc</span><span class="o">=</span>AES<span class="o">(</span>128<span class="o">)</span>       <span class="nv">Mac</span><span class="o">=</span>SHA256
AES256-GCM-SHA384            TLSv1.2  <span class="nv">Kx</span><span class="o">=</span>RSA   <span class="nv">Enc</span><span class="o">=</span>AESGCM<span class="o">(</span>256<span class="o">)</span>    <span class="nv">Mac</span><span class="o">=</span>AEAD
AES256-SHA256                TLSv1.2  <span class="nv">Kx</span><span class="o">=</span>RSA   <span class="nv">Enc</span><span class="o">=</span>AES<span class="o">(</span>256<span class="o">)</span>       <span class="nv">Mac</span><span class="o">=</span>SHA256
AES128-GCM-SHA256            TLSv1.2  <span class="nv">Kx</span><span class="o">=</span>RSA   <span class="nv">Enc</span><span class="o">=</span>AESGCM<span class="o">(</span>128<span class="o">)</span>    <span class="nv">Mac</span><span class="o">=</span>AEAD
AES128-SHA256                TLSv1.2  <span class="nv">Kx</span><span class="o">=</span>RSA   <span class="nv">Enc</span><span class="o">=</span>AES<span class="o">(</span>128<span class="o">)</span>       <span class="nv">Mac</span><span class="o">=</span>SHA256
ECDHE-RSA-AES256-SHA         SSLv3    <span class="nv">Kx</span><span class="o">=</span>ECDH  <span class="nv">Enc</span><span class="o">=</span>AES<span class="o">(</span>256<span class="o">)</span>       <span class="nv">Mac</span><span class="o">=</span>SHA1
ECDHE-RSA-AES128-SHA         SSLv3    <span class="nv">Kx</span><span class="o">=</span>ECDH  <span class="nv">Enc</span><span class="o">=</span>AES<span class="o">(</span>128<span class="o">)</span>       <span class="nv">Mac</span><span class="o">=</span>SHA1
DHE-RSA-AES256-SHA           SSLv3    <span class="nv">Kx</span><span class="o">=</span>DH    <span class="nv">Enc</span><span class="o">=</span>AES<span class="o">(</span>256<span class="o">)</span>       <span class="nv">Mac</span><span class="o">=</span>SHA1
DHE-RSA-CAMELLIA256-SHA      SSLv3    <span class="nv">Kx</span><span class="o">=</span>DH    <span class="nv">Enc</span><span class="o">=</span>Camellia<span class="o">(</span>256<span class="o">)</span>  <span class="nv">Mac</span><span class="o">=</span>SHA1
DHE-RSA-AES128-SHA           SSLv3    <span class="nv">Kx</span><span class="o">=</span>DH    <span class="nv">Enc</span><span class="o">=</span>AES<span class="o">(</span>128<span class="o">)</span>       <span class="nv">Mac</span><span class="o">=</span>SHA1
DHE-RSA-CAMELLIA128-SHA      SSLv3    <span class="nv">Kx</span><span class="o">=</span>DH    <span class="nv">Enc</span><span class="o">=</span>Camellia<span class="o">(</span>128<span class="o">)</span>  <span class="nv">Mac</span><span class="o">=</span>SHA1
AES256-SHA                   SSLv3    <span class="nv">Kx</span><span class="o">=</span>RSA   <span class="nv">Enc</span><span class="o">=</span>AES<span class="o">(</span>256<span class="o">)</span>       <span class="nv">Mac</span><span class="o">=</span>SHA1
CAMELLIA256-SHA              SSLv3    <span class="nv">Kx</span><span class="o">=</span>RSA   <span class="nv">Enc</span><span class="o">=</span>Camellia<span class="o">(</span>256<span class="o">)</span>  <span class="nv">Mac</span><span class="o">=</span>SHA1
AES128-SHA                   SSLv3    <span class="nv">Kx</span><span class="o">=</span>RSA   <span class="nv">Enc</span><span class="o">=</span>AES<span class="o">(</span>128<span class="o">)</span>       <span class="nv">Mac</span><span class="o">=</span>SHA1
CAMELLIA128-SHA              SSLv3    <span class="nv">Kx</span><span class="o">=</span>RSA   <span class="nv">Enc</span><span class="o">=</span>Camellia<span class="o">(</span>128<span class="o">)</span>  <span class="nv">Mac</span><span class="o">=</span>SHA1
ECDHE-RSA-DES-CBC3-SHA       SSLv3    <span class="nv">Kx</span><span class="o">=</span>ECDH  <span class="nv">Enc</span><span class="o">=</span>3DES<span class="o">(</span>168<span class="o">)</span>      <span class="nv">Mac</span><span class="o">=</span>SHA1
EDH-RSA-DES-CBC3-SHA         SSLv3    <span class="nv">Kx</span><span class="o">=</span>DH    <span class="nv">Enc</span><span class="o">=</span>3DES<span class="o">(</span>168<span class="o">)</span>      <span class="nv">Mac</span><span class="o">=</span>SHA1
DES-CBC3-SHA                 SSLv3    <span class="nv">Kx</span><span class="o">=</span>RSA   <span class="nv">Enc</span><span class="o">=</span>3DES<span class="o">(</span>168<span class="o">)</span>      <span class="nv">Mac</span><span class="o">=</span>SHA1
</code></pre></div></div>

<p>Note, that courier actually does <strong>not</strong> support <code class="language-shell highlighter-rouge">ECDH</code> key exchange, but I didn’t exclude it for 
the sake of simplicity for using the same cipher list for every server (e.g. web etc.)</p>]]></content><author><name>m6w6</name></author><category term="WTF" /><category term="SYS" /><summary type="html"><![CDATA[Debian wheezy (currently oldstable) ships courier-0.68 which was probably released on 2012. “Probably”, because, head over to the Courier website and try to find the NEWS/ChangeLog.]]></summary></entry><entry><title type="html">Blank DELL on DisplayPort</title><link href="https://m6w6.github.io/2015/08/blank-dell-on-displayport.html" rel="alternate" type="text/html" title="Blank DELL on DisplayPort" /><published>2015-08-19T00:00:00+00:00</published><updated>2015-08-19T00:00:00+00:00</updated><id>https://m6w6.github.io/2015/08/blank-dell-on-displayport</id><content type="html" xml:base="https://m6w6.github.io/2015/08/blank-dell-on-displayport.html"><![CDATA[<p>I’ve been struggling since ever with my DELL U3014 on the DisplayPort
saying there’s no signal after a power cycle of the monitor.</p>

<p>I just found a solution to bring the monitor back to life without rebooting
the box; just ssh into and issue:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ DISPLAY</span><span class="o">=</span>:0 xset dpms force off  
<span class="nv">$ DISPLAY</span><span class="o">=</span>:0 xset dpms force on  
</code></pre></div></div>

<p>I’m running Gnome3 on Arch Linux, so YMMV.</p>]]></content><author><name>m6w6</name></author><category term="WTF" /><category term="SYS" /><summary type="html"><![CDATA[I’ve been struggling since ever with my DELL U3014 on the DisplayPort saying there’s no signal after a power cycle of the monitor. I just found a solution to bring the monitor back to life without rebooting the box; just ssh into and issue:]]></summary></entry><entry><title type="html">Testing PHP extensions on Travis-CI</title><link href="https://m6w6.github.io/2015/08/testing-php-extensions-on-travis-ci.html" rel="alternate" type="text/html" title="Testing PHP extensions on Travis-CI" /><published>2015-08-11T00:00:00+00:00</published><updated>2015-08-11T00:00:00+00:00</updated><id>https://m6w6.github.io/2015/08/testing-php-extensions-on-travis-ci</id><content type="html" xml:base="https://m6w6.github.io/2015/08/testing-php-extensions-on-travis-ci.html"><![CDATA[<p>Testing PECL extensions on Travis-CI has always been
cumbersome for me; build PHP in different versions and debug/threadsafe
flavors, install PECL dependencies and so on, which usually results in a mess
of command line scripts, repeated for every extension.</p>

<p>Enter <a href="https://github.com/m6w6/travis-pecl">travis-pecl</a>.</p>

<p>This tiny support bin comes with a Makefile and small PHP scripts to generate
the build matrix and check your package.xml file. It supports building PHP in
a wide variety of flavors, installing PECL dependencies from the PECL website
or from bundled <a href="https://github.com/m6w6/pharext">pharext</a> packages and
running the testsuite with a comprehensive set of commands.</p>

<p>Let’s look at a few commands with a properly set up environment from the test
matrix:</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">env</span><span class="pi">:</span>  
 <span class="pi">-</span> <span class="s">PHP=5.6 enable_debug=yes with_iconv=yes enable_json=yes</span>  
</code></pre></div></div>

<h3 id="build-php">Build PHP:</h3>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>make <span class="nt">-f</span> travis/pecl/Makefile php  
</code></pre></div></div>
<h3 id="install-a-pecl-dependency">Install a PECL dependency:</h3>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>make <span class="nt">-f</span> travis/pecl/Makefile pecl <span class="nv">PECL</span><span class="o">=</span>propro  
</code></pre></div></div>
<h3 id="install-a-pecl-dependency-from-a-pharext-package-located-in-travis">Install a PECL dependency from a <a href="https://github.com/m6w6/pharext">pharext</a> package, located in travis/:</h3>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>make <span class="nt">-f</span> travis/pecl/Makefile pharext/raphf-phpng  
</code></pre></div></div>
<h3 id="build-the-currently-checked-out-extension">Build the currently checked out extension:</h3>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>make <span class="nt">-f</span> travis/pecl/Makefile ext <span class="nv">PECL</span><span class="o">=</span>http  
</code></pre></div></div>
<h3 id="run-the-testsuite">Run the testsuite:</h3>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>make <span class="nt">-f</span> travis/pecl/Makefile <span class="nb">test</span>  
</code></pre></div></div>

<p>Finally, check out the <a href="https://github.com/m6w6/travis-pecl/blob/master/README.md">README</a> 
and have a look at a couple of complete examples here:</p>

<ul>
  <li><a href="https://github.com/m6w6/ext-apfd/blob/master/gen_travis_yml.php">ext-apfd/gen_travis_yml.php</a></li>
  <li><a href="https://github.com/m6w6/ext-http/blob/master/scripts/gen_travis_yml.php">ext-http/scripts/gen_travis_yml.php</a></li>
</ul>]]></content><author><name>m6w6</name></author><category term="PHP" /><summary type="html"><![CDATA[Testing PECL extensions on Travis-CI has always been cumbersome for me; build PHP in different versions and debug/threadsafe flavors, install PECL dependencies and so on, which usually results in a mess of command line scripts, repeated for every extension. Enter travis-pecl. This tiny support bin comes with a Makefile and small PHP scripts to generate the build matrix and check your package.xml file. It supports building PHP in a wide variety of flavors, installing PECL dependencies from the PECL website or from bundled pharext packages and running the testsuite with a comprehensive set of commands. Let’s look at a few commands with a properly set up environment from the test matrix:]]></summary></entry><entry><title type="html">Evolution of $</title><link href="https://m6w6.github.io/2013/12/evolution-of.html" rel="alternate" type="text/html" title="Evolution of $" /><published>2013-12-09T00:00:00+00:00</published><updated>2013-12-09T00:00:00+00:00</updated><id>https://m6w6.github.io/2013/12/evolution-of</id><content type="html" xml:base="https://m6w6.github.io/2013/12/evolution-of.html"><![CDATA[<p>Today I realized an important and probably very obvious fact: we all change. Of
course, you will say. Surely most of us will agree to that, but the important
thing about that is also realizing that we drift away from things we loved.
Okay, so what am I actually talking about? :)</p>

<p>I talk about software development, specifically development of and with PHP.
We’ve seen some radical proposals in the nearer past and in deed are still
seeing those for PHP, the language. Often, I was inclined to think “cool,
that’s a great idea, let’s improve in that direction.”</p>

<p>PHP was and is a huge success, it attracts a lot of awesome people, sometimes
becoming unhappy with the language’s principles and resulting limitiations,
like its simplicity, its forgiving nature and the enigne’s effort to come to
an end for this request, i.e. to die. Looking at the larger frameworks which
have evolved the last few years, they head into a clear direction: strictly
object oriented programming with
RidiculouslyLongClassNamesLikeFoundInOtherStrictlyObjectOrientedLanguages.
Anything non object oriented seems to be verboten. But this is not of what PHP
was meant to be and it is very hard to change something that late in the game
in such drastical ways. I don’t think PHP can change as fast as we do, it’s
actually much longer around than most of us call ourself programmers.</p>

<p>What I mean to say is, don’t be angry with PHP the language, don’t force it to
change in a way it’s not supposed to survive, stop proposing language level
changes in a weekly manner, don’t be afraid to change yourself. Don’t be
afraid to advance yourself. Don’t be afraid to change the language you program
in. BOOM, I said it. Yes, don’t be afraid to explore other possibilities that
better support your principles instead of fighting them.</p>

<p>I’m not saying go away, I’m saying go ahead, or at least I mean to.</p>

<p>Sorry for the fast write-up, all the typos and errors. Have a nice start into
your week!</p>]]></content><author><name>m6w6</name></author><category term="PHP" /><summary type="html"><![CDATA[Today I realized an important and probably very obvious fact: we all change. Of course, you will say. Surely most of us will agree to that, but the important thing about that is also realizing that we drift away from things we loved. Okay, so what am I actually talking about? :) I talk about software development, specifically development of and with PHP. We’ve seen some radical proposals in the nearer past and in deed are still seeing those for PHP, the language. Often, I was inclined to think “cool, that’s a great idea, let’s improve in that direction.” PHP was and is a huge success, it attracts a lot of awesome people, sometimes becoming unhappy with the language’s principles and resulting limitiations, like its simplicity, its forgiving nature and the enigne’s effort to come to an end for this request, i.e. to die. Looking at the larger frameworks which have evolved the last few years, they head into a clear direction: strictly object oriented programming with RidiculouslyLongClassNamesLikeFoundInOtherStrictlyObjectOrientedLanguages. Anything non object oriented seems to be verboten. But this is not of what PHP was meant to be and it is very hard to change something that late in the game in such drastical ways. I don’t think PHP can change as fast as we do, it’s actually much longer around than most of us call ourself programmers. What I mean to say is, don’t be angry with PHP the language, don’t force it to change in a way it’s not supposed to survive, stop proposing language level changes in a weekly manner, don’t be afraid to change yourself. Don’t be afraid to advance yourself. Don’t be afraid to change the language you program in. BOOM, I said it. Yes, don’t be afraid to explore other possibilities that better support your principles instead of fighting them. I’m not saying go away, I’m saying go ahead, or at least I mean to. Sorry for the fast write-up, all the typos and errors. Have a nice start into your week!]]></summary></entry><entry><title type="html">Hear, hear</title><link href="https://m6w6.github.io/2013/06/hear-hear.html" rel="alternate" type="text/html" title="Hear, hear" /><published>2013-06-18T00:00:00+00:00</published><updated>2013-06-18T00:00:00+00:00</updated><id>https://m6w6.github.io/2013/06/hear-hear</id><content type="html" xml:base="https://m6w6.github.io/2013/06/hear-hear.html"><![CDATA[<p>I was about to write “in early February” but actually it already was in late January
that I stumbled over this tweet:</p>

<blockquote class="twitter-tweet">
  <p>I’m still ready &amp; willing to hire a
<a href="https://twitter.com/search?q=%23PHP&amp;src=hash">#PHP</a> internals coder to work
on PHP fulltime. Amazing place to work: <a href="http://t.co/GX4wtPSc">http://t.co/GX4wtPSc</a></p>

  <p>— Don MacAskill (@DonMacAskill) <a href="https://twitter.com/DonMacAskill/statuses/292117608076021760">January 18, 2013</a></p>
</blockquote>

<p>Fast-forward five months – now I am very excited to be able to announce that
the Awesomes over at <a href="http://www.smugmug.com/">SmugMug, Inc</a>. have hired me to
work full-time on the core of PHP.</p>

<p>Hide <a href="http://bugs.php.net/">bugs.php.net</a>, expect massive amounts of commits,
sleep well. Thank you for reading the simple words of the proudest man alive.
Thank you SmugMug!</p>]]></content><author><name>m6w6</name></author><category term="PHP" /><summary type="html"><![CDATA[I was about to write “in early February” but actually it already was in late January that I stumbled over this tweet:]]></summary></entry><entry><title type="html">pecl_http-1.7.5</title><link href="https://m6w6.github.io/2013/03/peclhttp-175.html" rel="alternate" type="text/html" title="pecl_http-1.7.5" /><published>2013-03-03T00:00:00+00:00</published><updated>2013-03-03T00:00:00+00:00</updated><id>https://m6w6.github.io/2013/03/peclhttp-175</id><content type="html" xml:base="https://m6w6.github.io/2013/03/peclhttp-175.html"><![CDATA[<p><a href="http://pecl.php.net/package/pecl_http/1.7.5">pecl_http-1.7.5</a> has been
released today.</p>

<p>Nearly a year and 170k downloads after the last release (1.7.4 was released
April 2nd 2012).</p>

<p>It fixes a single bug:</p>

<ul>
  <li><a href="http://bugs.php.net/64310">Bug #64310</a> (weak etags W/”abc” are quoted as “W/”abc””)</li>
</ul>

<p>The same user (thanks Niko), discovered a peculiarity of libcurl:</p>

<ul>
  <li>If you utilize libcurl’s <em>TIMECOND</em> feature through pecl_http’s <em>lastmodified</em> request option, 
libcurl ignores response bodies from servers that do not closely follow the RFC and send a <em>200 OK</em><br />
response instead of a <em>304 Not Modified</em>  when the condition is unmet.</li>
</ul>

<p>Slightly more background information is available at the relevant <a href="http://bugs.php.net/64298">bug
report</a>.</p>

<p>Please leave a comment, if you have an opinion about which component’s
behavior is arguable here.</p>]]></content><author><name>m6w6</name></author><category term="PHP" /><summary type="html"><![CDATA[pecl_http-1.7.5 has been released today.]]></summary></entry><entry><title type="html">pecl_http-v2 - http2 or httpi or http-*</title><link href="https://m6w6.github.io/2013/02/peclhttp-v2-http2-or-httpi-or-http.html" rel="alternate" type="text/html" title="pecl_http-v2 - http2 or httpi or http-*" /><published>2013-02-19T00:00:00+00:00</published><updated>2013-02-19T00:00:00+00:00</updated><id>https://m6w6.github.io/2013/02/peclhttp-v2-http2-or-httpi-or-http</id><content type="html" xml:base="https://m6w6.github.io/2013/02/peclhttp-v2-http2-or-httpi-or-http.html"><![CDATA[<p>I’m pondering to release v2 of pecl_http with a different
extension name than “http”, but I cannot agree with myself what’s worse:</p>

<h3 id="http2">http2</h3>

<p>This might be confused with HTTP/2.0</p>

<h3 id="httpi">httpi</h3>

<p>There’s mysqli following this approach, but I think this is pretty odd.</p>

<h3 id="split-it-up">Split it up</h3>

<p>Split the package up in several smaller sub-packages, like:</p>

<ul>
  <li>http-common</li>
  <li>http-env</li>
  <li>http-client</li>
  <li>http-client-curl</li>
  <li>etc.</li>
</ul>

<p>If you have an opinion, or maybe even a better idea, please leave a comment.</p>]]></content><author><name>m6w6</name></author><category term="PHP" /><summary type="html"><![CDATA[I’m pondering to release v2 of pecl_http with a different extension name than “http”, but I cannot agree with myself what’s worse:]]></summary></entry><entry><title type="html">Javascript delaying</title><link href="https://m6w6.github.io/2011/03/javascript-delaying.html" rel="alternate" type="text/html" title="Javascript delaying" /><published>2011-03-18T00:00:00+00:00</published><updated>2011-03-18T00:00:00+00:00</updated><id>https://m6w6.github.io/2011/03/javascript-delaying</id><content type="html" xml:base="https://m6w6.github.io/2011/03/javascript-delaying.html"><![CDATA[<p>In need of executing Javascript after the page has loaded, or something else
has been initialized I came up with a simple but useful tiny “Delayer”:</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/**  
 * @param handler a callback accepting Delayer.dispatch as argument  
 */</span>  
<span class="kd">function</span> <span class="nx">Delayer</span><span class="p">(</span><span class="nx">handler</span><span class="p">)</span> <span class="p">{</span>  
    <span class="kd">var</span> <span class="nb">self</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span>  
  
    <span class="k">this</span><span class="p">.</span><span class="nx">dispatch</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>  
        <span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o">&lt;</span> <span class="nb">self</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="o">++</span><span class="nx">i</span><span class="p">)</span> <span class="p">{</span>  
            <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">running delayed init </span><span class="dl">"</span><span class="o">+</span><span class="nx">i</span><span class="o">+</span><span class="dl">"</span><span class="s2">: </span><span class="dl">"</span><span class="o">+</span><span class="nb">self</span><span class="p">[</span><span class="nx">i</span><span class="p">]);</span>  
            <span class="nb">self</span><span class="p">[</span><span class="nx">i</span><span class="p">]();</span>  
        <span class="p">}</span>  
    <span class="p">};</span>  
  
    <span class="k">if</span> <span class="p">(</span><span class="k">typeof</span> <span class="nx">handler</span> <span class="o">==</span> <span class="dl">"</span><span class="s2">function</span><span class="dl">"</span> <span class="o">||</span> <span class="nx">handler</span> <span class="k">instanceof</span> <span class="nb">Function</span><span class="p">)</span> <span class="p">{</span>  
        <span class="nx">handler</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">dispatch</span><span class="p">);</span>  
    <span class="p">}</span>  
<span class="p">}</span>  
  
<span class="nx">Delayer</span><span class="p">.</span><span class="nx">prototype</span> <span class="o">=</span> <span class="nb">Array</span><span class="p">.</span><span class="nx">prototype</span><span class="p">;</span>
</code></pre></div></div>

<p>It can be initialized the following way:</p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/* e.g. with jQuery */</span>  
<span class="nb">window</span><span class="p">.</span><span class="nx">delayedInits</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Delayer</span><span class="p">(</span><span class="nx">$</span><span class="p">(</span><span class="nb">document</span><span class="p">).</span><span class="nx">ready</span><span class="p">);</span>  
<span class="cm">/* e.g. with Facebook */</span>  
<span class="nb">window</span><span class="p">.</span><span class="nx">fbDelayedInits</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Delayer</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">dp</span><span class="p">){</span><span class="nb">window</span><span class="p">.</span><span class="nx">fbAsyncInit</span> <span class="o">=</span> <span class="nx">dp</span><span class="p">;});</span>
</code></pre></div></div>

<p>Then you push your work the usual way:</p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">delayedInits</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span><span class="nx">alert</span><span class="p">(</span><span class="dl">"</span><span class="s2">Hello, delayed!</span><span class="dl">"</span><span class="p">);});</span>
</code></pre></div></div>]]></content><author><name>m6w6</name></author><category term="WEB" /><summary type="html"><![CDATA[In need of executing Javascript after the page has loaded, or something else has been initialized I came up with a simple but useful tiny “Delayer”:]]></summary></entry><entry><title type="html">courier imap, authdaemond and vpopmails vchkpw</title><link href="https://m6w6.github.io/2011/03/courier-imap-authdaemond-and-vpopmails-vchkpw.html" rel="alternate" type="text/html" title="courier imap, authdaemond and vpopmails vchkpw" /><published>2011-03-14T00:00:00+00:00</published><updated>2011-03-14T00:00:00+00:00</updated><id>https://m6w6.github.io/2011/03/courier-imap-authdaemond-and-vpopmails-vchkpw</id><content type="html" xml:base="https://m6w6.github.io/2011/03/courier-imap-authdaemond-and-vpopmails-vchkpw.html"><![CDATA[<p>A few years ago, it was possible to have courier-imap update the open-smtp
relay file with it’s authvchkpw module. This feature and thus imap-before-smtp
disappeared with the introduction of courier-authdaemond because the vchkpw
code of authdaemond does not have a chance to see the TCPREMOTEIP environment
variable.</p>

<p>I more or less lived with that, until a friend of mine got a new iphone…
well yeah, one of those i-geeks, and that gadget apparently only supports
imap, no pop.</p>

<p>To re-enable imap-before-smtp I wrote a little setuid wrapper, calling
vpopmails open_smtp_relay(). This wrapper has to replace the imapd command in
your courier-imap startup script and will exec imapd, after opening the smtp
relay, wile imap-login is still in place to authenticate via authdaemond’s
vchkpw module.</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;unistd.h&gt;</span><span class="c1">  </span><span class="cp">
#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="c1">  </span><span class="cp">
#include</span> <span class="cpf">&lt;sys/types.h&gt;</span><span class="c1">  </span><span class="cp">
#include</span> <span class="cpf">&lt;vpopmail_config.h&gt;</span><span class="c1">  </span><span class="cp">
#include</span> <span class="cpf">&lt;vauth.h&gt;</span><span class="c1">  </span><span class="cp">
#include</span> <span class="cpf">&lt;vpopmail.h&gt;</span><span class="c1">  </span><span class="cp">
</span>  
<span class="cp">#ifndef IMAPD  
#   define IMAPD "/usr/bin/imapd"  
#endif  
</span>  
<span class="k">extern</span> <span class="kt">char</span> <span class="o">**</span><span class="n">environ</span><span class="p">;</span>  
  
<span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> <span class="p">{</span>  
    <span class="k">if</span> <span class="p">(</span><span class="n">argc</span> <span class="o">!=</span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span>  
        <span class="n">printf</span><span class="p">(</span><span class="s">"1 NO argc != 2n"</span><span class="p">);</span>  
        <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>  
    <span class="p">}</span>  
  
    <span class="n">open_smtp_relay</span><span class="p">();</span>  
    <span class="cm">/* no need to chown vpopmail.vchkpw the open-smtp file  
     * because vchkpw used by qmail-pop3d is setuid root */</span>  
  
    <span class="n">sleep</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>  
  
    <span class="k">if</span> <span class="p">(</span><span class="n">setgid</span><span class="p">(</span><span class="n">VPOPMAILGID</span><span class="p">)</span> <span class="o">||</span> <span class="n">setuid</span><span class="p">(</span><span class="n">VPOPMAILUID</span><span class="p">))</span> <span class="p">{</span>  
        <span class="n">printf</span><span class="p">(</span><span class="s">"1 NO setuid/gid, getuid=%dn"</span><span class="p">,</span> <span class="n">getuid</span><span class="p">());</span>  
        <span class="k">return</span> <span class="o">-</span><span class="mi">2</span><span class="p">;</span>  
    <span class="p">}</span>  
  
    <span class="n">execl</span><span class="p">(</span><span class="n">IMAPD</span><span class="p">,</span> <span class="n">IMAPD</span><span class="p">,</span> <span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="nb">NULL</span><span class="p">);</span>  
  
    <span class="n">printf</span><span class="p">(</span><span class="s">"1 NO exec %s failedn"</span><span class="p">,</span> <span class="n">IMAPD</span><span class="p">);</span>  
    <span class="k">return</span> <span class="o">-</span><span class="mi">3</span><span class="p">;</span>  
<span class="p">}</span>
</code></pre></div></div>

<p>So while this worked to my satisfaction, I noticed that the tcp.smtp.cdb not
always contained the IPs of the open-smtp file:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="k">for </span>ip <span class="k">in</span> <span class="si">$(</span><span class="nb">sed</span> <span class="nt">-re</span> <span class="s1">'s/:.*//'</span> &lt; open-smtp<span class="si">)</span><span class="p">;</span> <span class="k">do   
    </span>cdbget <span class="nv">$ip</span> &lt; tcp.smtp.cdb <span class="o">&gt;</span> /dev/null   
        <span class="o">||</span> <span class="nb">echo</span> <span class="s2">"</span><span class="nv">$ip</span><span class="s2"> is missing"</span><span class="p">;</span>   
    <span class="k">done</span>
</code></pre></div></div>

<p>I also found out that, while the <a href="http://www.inter7.com/vpopmail/FAQ.txt">vpopmail FAQ</a> is claiming 
that clearopensmtp is requesting locks on the open-smtp(.lock) file, the source does not read like
it would.</p>

<p>I opened a <a href="https://sourceforge.net/tracker/?func=detail&amp;aid=3205655&amp;group_id=85937&amp;atid=577798">bug report</a>
for that issue, but as you might have already guessed, I’m running all of this
on an archaic debian box, where no upgrades are planned. So I came up with
another home-brewed solution:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;unistd.h&gt;</span><span class="c1">  </span><span class="cp">
#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="c1">  </span><span class="cp">
#include</span> <span class="cpf">&lt;sys/types.h&gt;</span><span class="c1">  </span><span class="cp">
#include</span> <span class="cpf">&lt;vpopmail_config.h&gt;</span><span class="c1">  </span><span class="cp">
#include</span> <span class="cpf">&lt;vauth.h&gt;</span><span class="c1">  </span><span class="cp">
#include</span> <span class="cpf">&lt;vpopmail.h&gt;</span><span class="c1">  </span><span class="cp">
#include</span> <span class="cpf">&lt;fcntl.h&gt;</span><span class="c1">  </span><span class="cp">
</span>  
<span class="k">extern</span> <span class="kt">int</span> <span class="nf">get_write_lock</span><span class="p">(</span><span class="kt">FILE</span><span class="o">*</span><span class="p">);</span>  
<span class="k">extern</span> <span class="kt">int</span> <span class="nf">lock_reg</span><span class="p">(</span><span class="kt">int</span><span class="p">,</span><span class="kt">int</span><span class="p">,</span><span class="kt">int</span><span class="p">,</span><span class="kt">off_t</span><span class="p">,</span><span class="kt">int</span><span class="p">,</span><span class="kt">off_t</span><span class="p">);</span>  
<span class="cp">#define unlock(F) lock_reg(fileno(F), F_SETLK, F_UNLCK, 0, SEEK_SET, 0)  
</span>  
<span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> <span class="p">{</span>  
    <span class="kt">FILE</span> <span class="o">*</span><span class="n">fs_temp</span><span class="p">,</span> <span class="o">*</span><span class="n">fs_smtp</span><span class="p">,</span> <span class="o">*</span><span class="n">fs_lock</span> <span class="o">=</span> <span class="n">fopen</span><span class="p">(</span><span class="n">OPEN_SMTP_LOK_FILE</span><span class="p">,</span> <span class="s">"w+"</span><span class="p">);</span>  
    <span class="kt">time_t</span> <span class="n">clear</span> <span class="o">=</span> <span class="n">RELAY_CLEAR_MINUTES</span> <span class="o">*</span> <span class="mi">60</span><span class="p">,</span> <span class="n">now</span> <span class="o">=</span> <span class="n">time</span><span class="p">(</span><span class="nb">NULL</span><span class="p">);</span>  
    <span class="kt">int</span> <span class="n">cc</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">rc</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>  
  
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">fs_lock</span><span class="p">)</span> <span class="p">{</span>  
        <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>  
    <span class="p">}</span>  
    <span class="k">if</span> <span class="p">(</span><span class="n">get_write_lock</span><span class="p">(</span><span class="n">fs_lock</span><span class="p">))</span> <span class="p">{</span>  
        <span class="n">unlock</span><span class="p">(</span><span class="n">fs_lock</span><span class="p">);</span>  
        <span class="n">fclose</span><span class="p">(</span><span class="n">fs_lock</span><span class="p">);</span>  
        <span class="k">return</span> <span class="o">-</span><span class="mi">2</span><span class="p">;</span>  
    <span class="p">}</span>     
  
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="p">(</span><span class="n">fs_temp</span> <span class="o">=</span> <span class="n">fopen</span><span class="p">(</span><span class="n">OPEN_SMTP_TMP_FILE</span> <span class="s">".clear"</span><span class="p">,</span> <span class="s">"w"</span><span class="p">)))</span> <span class="p">{</span>  
        <span class="n">rc</span> <span class="o">=</span> <span class="o">-</span><span class="mi">3</span><span class="p">;</span>  
    <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="p">(</span><span class="n">fs_smtp</span> <span class="o">=</span> <span class="n">fopen</span><span class="p">(</span><span class="n">OPEN_SMTP_CUR_FILE</span><span class="p">,</span> <span class="s">"r+"</span><span class="p">)))</span> <span class="p">{</span>  
        <span class="n">fclose</span><span class="p">(</span><span class="n">fs_temp</span><span class="p">);</span>  
        <span class="n">rc</span> <span class="o">=</span> <span class="o">-</span><span class="mi">4</span><span class="p">;</span>  
    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>  
        <span class="k">while</span> <span class="p">(</span><span class="o">!</span><span class="n">rc</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="n">feof</span><span class="p">(</span><span class="n">fs_smtp</span><span class="p">))</span> <span class="p">{</span>  
            <span class="kt">unsigned</span> <span class="n">stime</span><span class="p">;</span>  
            <span class="kt">char</span> <span class="n">sdata</span><span class="p">[</span><span class="mi">256</span><span class="p">];</span>  
  
            <span class="k">switch</span> <span class="p">(</span><span class="n">fscanf</span><span class="p">(</span><span class="n">fs_smtp</span><span class="p">,</span> <span class="s">"%255st%un"</span><span class="p">,</span> <span class="n">sdata</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">stime</span><span class="p">))</span> <span class="p">{</span>  
                <span class="k">case</span> <span class="mi">2</span><span class="p">:</span>  
                    <span class="k">if</span> <span class="p">((</span><span class="n">clear</span> <span class="o">+</span> <span class="n">stime</span><span class="p">)</span> <span class="o">&gt;=</span> <span class="n">now</span><span class="p">)</span> <span class="p">{</span>  
                        <span class="n">fprintf</span><span class="p">(</span><span class="n">fs_temp</span><span class="p">,</span> <span class="s">"%st%un"</span><span class="p">,</span> <span class="n">sdata</span><span class="p">,</span> <span class="n">stime</span><span class="p">);</span>  
                    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>  
                        <span class="o">++</span><span class="n">cc</span><span class="p">;</span>  
                    <span class="p">}</span>  
                    <span class="k">break</span><span class="p">;</span>  
  
                <span class="nl">default:</span>  
                    <span class="n">rc</span> <span class="o">=</span> <span class="o">-</span><span class="mi">5</span><span class="p">;</span>  
                <span class="k">case</span> <span class="n">EOF</span><span class="p">:</span>  
                    <span class="k">break</span><span class="p">;</span>  
            <span class="p">}</span>  
        <span class="p">}</span>  
        <span class="n">fclose</span><span class="p">(</span><span class="n">fs_smtp</span><span class="p">);</span>  
        <span class="n">fclose</span><span class="p">(</span><span class="n">fs_temp</span><span class="p">);</span>  
    <span class="p">}</span>  
  
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">rc</span><span class="p">)</span> <span class="p">{</span>  
        <span class="k">if</span> <span class="p">(</span><span class="n">cc</span><span class="p">)</span> <span class="p">{</span>  
            <span class="k">if</span> <span class="p">(</span><span class="n">rename</span><span class="p">(</span><span class="n">OPEN_SMTP_TMP_FILE</span> <span class="s">".clear"</span><span class="p">,</span> <span class="n">OPEN_SMTP_CUR_FILE</span><span class="p">))</span> <span class="p">{</span>  
                <span class="n">rc</span> <span class="o">=</span> <span class="o">-</span><span class="mi">6</span><span class="p">;</span>  
            <span class="p">}</span> <span class="k">else</span> <span class="k">if</span><span class="p">(</span><span class="n">update_rules</span><span class="p">())</span> <span class="p">{</span>  
                <span class="n">rc</span> <span class="o">=</span> <span class="o">-</span><span class="mi">7</span><span class="p">;</span>  
            <span class="p">}</span>  
        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>  
            <span class="n">unlink</span><span class="p">(</span><span class="n">OPEN_SMTP_TMP_FILE</span> <span class="s">".clear"</span><span class="p">);</span>  
        <span class="p">}</span>  
    <span class="p">}</span>  
  
    <span class="n">unlock</span><span class="p">(</span><span class="n">fs_lock</span><span class="p">);</span>  
    <span class="n">fclose</span><span class="p">(</span><span class="n">fs_lock</span><span class="p">);</span>  
    <span class="k">return</span> <span class="n">rc</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>It’s not the prettiest piece of code, but it helps.<br />
Well, maybe someone else running last-millenium software finds this useful</p>]]></content><author><name>m6w6</name></author><category term="WTF" /><category term="SYS" /><summary type="html"><![CDATA[A few years ago, it was possible to have courier-imap update the open-smtp relay file with it’s authvchkpw module. This feature and thus imap-before-smtp disappeared with the introduction of courier-authdaemond because the vchkpw code of authdaemond does not have a chance to see the TCPREMOTEIP environment variable.]]></summary></entry><entry><title type="html">WebSockets Handshake non HTTP conforming?</title><link href="https://m6w6.github.io/2010/05/websockets-handshake-non-http-conforming.html" rel="alternate" type="text/html" title="WebSockets Handshake non HTTP conforming?" /><published>2010-05-10T00:00:00+00:00</published><updated>2010-05-10T00:00:00+00:00</updated><id>https://m6w6.github.io/2010/05/websockets-handshake-non-http-conforming</id><content type="html" xml:base="https://m6w6.github.io/2010/05/websockets-handshake-non-http-conforming.html"><![CDATA[<p>While skimming through the new <a href="http://dev.w3.org/html5/websockets/">HTML5 WebSocket draft</a>, 
I noticed the following exemplar HTTP message demonstrating the client message of a WebSocket handshake:</p>

<div class="language-http highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">GET</span> <span class="nn">/demo</span> <span class="k">HTTP</span><span class="o">/</span><span class="m">1.1</span>
<span class="na">Host</span><span class="p">:</span> <span class="s">example.com</span>
<span class="na">Connection</span><span class="p">:</span> <span class="s">Upgrade</span>
<span class="na">Sec-WebSocket-Key2</span><span class="p">:</span> <span class="s">12998 5 Y3 1  .P00</span>
<span class="na">Sec-WebSocket-Protocol</span><span class="p">:</span> <span class="s">sample</span>
<span class="na">Upgrade</span><span class="p">:</span> <span class="s">WebSocket</span>
<span class="na">Sec-WebSocket-Key1</span><span class="p">:</span> <span class="s">4 @1  46546xW%0l 1 5</span>
<span class="na">Origin</span><span class="p">:</span> <span class="s">http://example.com</span>

^n:ds[4U
</code></pre></div></div>

<p>To me this looks non conforming to the <a href="http://www.w3.org/Protocols/rfc2616/rfc2616.html">HTTP
spec</a> due to the lack of an
indicator that the request contains a message body.</p>

<p>Quoting <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.3">the 4th paragraph of section 4.3 of
RFC2616</a>:</p>

<blockquote>
  <p>The <strong>presence of a message-body</strong> in a request <strong>is signaled</strong> by the
inclusion of a <strong>Content-Length or Transfer-Encoding header</strong> field in the
request’s message-headers. A message-body MUST NOT be included in a request if
the specification of the request method (section 5.1.1) does not allow sending
an entity-body in requests. A server SHOULD read and forward a message-body on
any request; if the request method does not include defined semantics for an
entity-body, then the message-body SHOULD be ignored when handling the
request.</p>
</blockquote>

<p>Huh?</p>]]></content><author><name>m6w6</name></author><category term="WTF" /><category term="PHP" /><category term="WEB" /><summary type="html"><![CDATA[While skimming through the new HTML5 WebSocket draft, I noticed the following exemplar HTTP message demonstrating the client message of a WebSocket handshake:]]></summary></entry></feed>