Author Archives: Rob

(on)bereikbare telefonische helpdesk

Ik heb een trucje ontdekt dat de wachttijd voor de telefonische helpdesk van mijn bank, die altijd overbelast en onbereikbaar is, terugbrengt tot minder dan een minuut.

Nieuwsgierig?
Let op.

Iedereen weet dat banken schoften zijn, die alleen maar op ons geld uit zijn, en die geen enkele boodschap hebben aan service. Dat geldt overigens niet alleen voor banken, maar ook voor telefoon- en internetproviders, energiebedrijven, verzekeraars, enzovoort; dat weet ook iedereen.
Deze bedrijven verstoppen zich achter onbereikbaarheid: de telefonische hulplijnen zijn altijd overbelast en onbereikbaar, en de email-hulplijnen reageren alleen met geautomatiseerde nutteloze berichten.

Mijn trucje, als je het zo kunt noemen, gaat uit van de inhaligheid van deze bedrijven. Ik ging er namelijk vanuit dat deze bedrijven richting nieuwe klanten veel minder onbeschoft zouden zijn; deze moeten immers eerst binnengeharkt worden voordat ze geld gaan opleveren.

In plaats van de helpdesk voor klanten belde ik dus de algemene hulplijn:

robot   : Goedemiddag. Welkom bij <bank>.
          Kies 1 als u al klant bent en toegang wilt tot uw rekeninggegevens.
          Kies 2 als u al klant bent en informatie wilt over aanvullende produkten.
          Kies 3 als u nog geen klant bent.
ik      : 3
robot   : Kies 1 als u informatie wilt over betalen en sparen.
          Kies 2 als u informatie wilt over verzekeringen.
          ... enzovoort ...
ik      : ... (doe niets, maar wacht alleen)
robot   : Ik heb uw keuze niet begrepen.
          Kies 1 als u informatie wilt over ... (zelfde menuutje als hiervoor) ...
ik      : ... (doe niets, maar wacht alleen)
robot   : Ik heb uw keuze niet begrepen.
          (een paar seconden muziek)
persoon : Goedemiddag. Waarmee kan ik u van dienst zijn?

Zoals gezegd: dit soort bedrijven zijn inhalige schoften; ze zullen dus potentiële nieuwe klanten nooit de kans geven om af te haken.
En daar kun je gebruik van maken. En dat moet je ook vooral zonder schaamte doen, want ze maken nog veel harder gebruik van jou.

Uiteraard kan ik niet garanderen dat dit altijd werkt, of dat het altijd op dezelfde manier werkt. Maar het is altijd de moeite van het proberen waard.
Zoek in het menu naar de meest commerciële optie, en gedraag je dan als een bejaarde die niets snapt van wat-ie voorgeschoteld krijgt; de kans is groot dat je dan wordt behandeld met de voorrang die je als betalende klant verdient.

The 1 thing that’s missing in 2FA

Wikipedia, Twitter, GitHub, Trello, …
Hundreds, if not thousands of websites require multi-factor authentication, or at least offer it as a complementary security measure.

WordPress, Roundcube, Kanboard, Nextcloud, …
Hundreds, if not thousands of web applications offer multi-factor authentication by default or as a module/plugin.

And yet, there is one thing that none of all these 2FA developers/implementors have thought of. And since I don’t have the time, nor the desire, to submit a bug report for each of these thousands of applications and websites, I’m just going to say it here. Kudos to all developers who read this, realize that I’m right, and implement this.

IF AND WHEN SOMEONE REACHES MY 2FA FORM AND CANNOT COMPLETE IT, I WANT TO BE NOTIFIED!

If someone reaches the 2FA form, this means that they have correctly entered my password.
If someone cannot complete the 2FA form, this means that they probably do not have my phone or 2FA device.
So it is very probable that someone who cannot complete the 2FA challenge IS NOT ME.
This means that someone who is not me has managed to correctly enter my password.

This means that very probably my password has been compromised, and I must change it. NOW!

So, if the above is too much text for you, let me summarize below:

IF SOMEONE CANNOT COMPLETE MY 2FA CHALLENGE,
THEY HAVE PROBABLY ALREADY COMPROMISED MY PASSWORD,
AND I NEED TO KNOW ASAP!

And actually, I’d even prefer to know if they reach the 2FA form and don’t try to complete the challenge. Because if I want to log in, I go all the way, and I don’t abandon between password and 2FA.

Check the ACL!

I just shot myself in the foot using Access Control Lists.

# ls -l ./somefile.txt
-rw-r-----+  1 root  www  893  Apr 4 00:44 ./somefile.txt
# getfacl ./somefile.txt
user::rw-
user:www:--x  # effective: ---
group::r-x    # effective: r--
mask::r--
other::---

In the above example, the file inherited the default ACL from the parent directory.

I’m not even going to tell you how long it took me to figure out why the web server couldn’t access the file…

If you can’t find it: check those ACL!

And if you want to drive your colleague crazy:

# setfacl -m u:george:--- /some/random/commonly/used/file

Reprocess mbox file

Say you’ve found an mbox file somewhere, and you’d like Postfix to reprocess the messages it contains, to have them imported into your regular mailbox.

Then you may want to copy this script:

#!/usr/bin/env python3

# Script to reprocess an mbox file.

################################################################################
#
# Copyright (c) 2021 Rob LA LAU <https://www.ohreally.nl/>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
################################################################################

import mailbox, os, subprocess, sys

if len(sys.argv) < 3:
	print('Usage:')
	print('  %s recipient@example.com /path/to/mbox/file' % sys.argv[0])
	sys.exit(1)

recipient = sys.argv[1]
mbox = sys.argv[2]
if not os.access(mbox, os.R_OK):
	print('mbox file is not accessible')
	sys.exit(1)

for message in mailbox.mbox(mbox):
	proc = subprocess.Popen(
		['sendmail', '-i', recipient],
		stdin = subprocess.PIPE,
		text = True
	)
	proc.communicate(message.as_string())

Save that script as ~/bin/resend_mbox.py, make it executable, and execute it as follows:

# ~/bin/resend_mbox.py george@example.com /var/mail/root

Obviously, you replace george@example.com with your own email address (don’t spam poor George, please), and /var/mail/root with the path to your mbox file.

JWPlayer errors

Error Code 224002: This video file cannot be played
Error Code 224003: This video file cannot be played
Error Code 232011: This video file cannot be played

A few of the more common web video player errors, but they tell you nothing.

If you search the internet for these errors, all you find are generic bullshit ‘solutions’: clear cache, disable all extensions, disable hardware acceleration, etc. So, here’s the actual list of JWPlayer error codes: Player errors reference. Get you some real answers.

By the way, the meaning of the above errors:

  • Failed to decode the associated resource (224002),
  • Failed to play the associated resource because it is not supported by this browser (224003), and
  • A manifest request was made without proper crossdomain credentials (232011)
    (The manifest is a file that contains the URLs for the various segments that make up the entire video.)

What it comes down to, is that JWPlayer just sucks a lot, especially if you use a proxy. Let’s hope that with the growing acceptance of HTML5, with built-in video support, projects like this will go the same way Flash players did.

Counting annotations in a PDF

Suppose that you wrote a book, and your publisher sent you a PDF of the final proof to review and correct, before the book is printed. Then you may want to know how many notes you’ve added to the document when you’re done.

$ env LC_CTYPE=C tr -d '\000-\011\013\014\016-\037' < FILENAME.pdf | grep -E '^<</Type /Annot /Rect \[[0-9\. ]+\] /Subtype /Text' | wc -l

It’s that simple…

And if you’d like to know how many terms you highlighted, all you have to do is replace /Text with /Highlight.

$ env LC_CTYPE=C tr -d '\000-\011\013\014\016-\037' < FILENAME.pdf | grep -E '^<</Type /Annot /Rect \[[0-9\. ]+\] /Subtype /Highlight' | wc -l

Inline notes are of subtype /FreeText.

And to count all your annotations, regardless of type, just delete the subtype altogether.

$ env LC_CTYPE=C tr -d '\000-\011\013\014\016-\037' < FILENAME.pdf | grep -E '^<</Type /Annot' | wc -l

Open your PDF in less to see what other interesting things you could do with grep; pipe the file through tr to get rid of the control characters.

$ env LC_CTYPE=C tr -d '\000-\011\013\014\016-\037' < FILENAME.pdf | less

Warme chocolademelk

Een beker melk met een paar scheppen Nesquik een minuutje in de magnetron, dacht je?
Ik denk het niet. Dit is een recept voor lekkere warme chocolademelk.

Voor wie even genoeg heeft van vin chaud en Jägertee.

Nodig:

  • melk
  • instant chocolademelk (Nesquik, Benco, …)
  • een reep donkere chocola; minstens 65% cacao
  • cayennepeper
  • cognac

Probeer een instant chocolademelk te vinden die meer naar chocola smaakt dan naar suiker (dat valt niet mee, want dat spul wordt gemaakt voor kinderen, en kinderen willen suiker).

Meet een niet helemaal volle beker melk af, doe dat in een steelpannetje, en zet het op half vuur.
Schep dan de instant chocolademelk in de beker; voor de beker die ik gebruik, heb ik 3-4 volle theelepels nodig.
Brokkel wat van de reep chocola in het pannetje met melk. Voor mijn beker gebruik ik 3 blokjes. Je kunt er natuurlijk gewoon de hele reep in mikken, maar dan lost niet alles op, maar slaat het neer op de bodem van je pannetje; experimenteer om de lekkerste chocolademelk te krijgen, en zo min mogelijk chocola weg te gooien.
Giet de melk, als die warm is en de chocola gesmolten, in de beker, en roer tot het poeder is opgelost.
Roer er dan een kwart tot een halve theelepel cayennepeper en een scheut cognac doorheen. Gebruik niet teveel cognac: balans is belangrijk, en als het je alleen om de cognac gaat, had je beter al dat werk achterwege kunnen laten, en gewoon een glas cognac nemen.

Tip:
Deze chocolademelk is erg lekker als je vanuit de kou thuis komt; het is een warmte-bommetje. Als je een beker maakt voor het slapen gaan, is het misschien lekkerder om de peper achterwege te laten.

En alsjeblieft: geen slagroom!
Het is echt heel raar om eerst werk te steken in de bereiding van een hele lekkere drank, om die vervolgens te vermoorden met een berg vet en suiker.

Smakelijk!

FreeBSD jails: a complete example

FreeBSD jails are a great way to separate and compartmentalize processes, which enhances the security of your system. A jail is an enhanced chroot: it prevents an attacker who manages to compromise a service from gaining access to the rest of the system.

This post documents the setup of 2 jails that serve data to the outside world, and communicate between each other (through a Unix Domain Socket, not a TCP socket).

Read More

FreeBSD: which ports/packages did I update today?

A FreeBSD oneliner this time.
This won’t work on Linux!

Tools like portmaster and portupgrade allow you to update all installed ports/packages in a single run, which is great.
But these tools do not list the ports and packages that have been upgraded, leaving you to guess which daemons and services must be restarted…

Luckily, all installed packages are registered in an SQLite database, together with a timestamp for their last upgrade (or installation). Add the following alias to your ~/.bashrc:

alias puptd='sqlite3 /var/db/pkg/local.sqlite "select origin from packages where time > $(date -v-2d +%s) order by origin" | less'

Clearly, if you don’t use the Bash shell, you should figure out how to add aliases in your shell. The alias will be active after you re-login; invoke it like any other command.

$ puptd

This alias will list all ports/packages that were updated (or installed) in the last 2 days (an update of all ports can run for quite some time). Obviously you should feel free to change the -v-2d to any other period (-v-3H for the last 3 hours, -v-1w for the last week, …). You can then check the list to see if any services must be restarted, configurations must be verified, etc.

Remember that some services may depend on other packages. E.g. if you updated Python, you may have to restart Radicale and Fail2ban, and if you updated PHP and you use mod_php, you may want to restart Apache.

If you’re going to play around with that database to see what other info you can extract from it, you should probably make a copy of it, to make sure you don’t accidentally write to the original; you don’t want to mess up your package database.

P.s.: the name for the alias comes from ‘Ports UPdated ToDay’; change it to anything you like.