💾 Archived View for perso.pw › blog › rss.xml captured on 2023-11-04 at 11:30:32.

View Raw

More Information

⬅️ Previous capture (2023-09-28)

➡️ Next capture (2023-11-14)

🚧 View Differences

-=-=-=-=-=-=-

<?xml version="1.0" encoding="UTF-8"?> 
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Solene'%</title>
    <description></description>
    <link>gemini://perso.pw/blog/</link>
    <atom:link href="gemini://perso.pw/blog/rss.xml" rel="self" type="application/rss+xml" />
    <item>
  <title>Read quoted-printable emails with qprint</title>
  <description>
    <![CDATA[
<pre># Introduction

You may already have encountered emails in raw text that contained weird characters sequences like `=E3` or `=09`, especially if you work with patch files embedded as text in emails.

There is nothing wrong with the text itself, or the sender email client.  In fact, this shows the email client is doing the right thing by applying the RFC 1521.  Non-ASCII character should be escaped in some way in emails.

=> https://www.rfc-editor.org/rfc/rfc1521 RFC 1521: MIME part one

This is where qprint enters in action, it can be used to encode using the quoted-printable, or decode such content.  The software can be installed on OpenBSD with the package named `qprint`.

=> https://www.fourmilab.ch/webtools/qprint/ qprint official website

I already introduced qprint in a blog post in a guide about OpenBSD pledge.

# What does quoted-printable look like?

If you search for an email from the OpenBSD mailing list, and display it in raw format, you may encounter this encoding.  There isn't much you can do with the file, it's hard to read and can't be used with the program patch.

=> https://marc.info/?l=openbsd-ports&m=169833007120486&q=raw Email example featuring quoted-printable characters

A sample of the email looks like that:

From italiano-=E6=97=A5=E6=9C=AC=E8=AA=9E (=E3=81=AB=E3=81=BB=E3=82=93=

=E3=81=94) FreeDict+WikDict dictionary ver.

2022.11.18 [itajpn]:

=09

ciao //'=CA=A7ao// <interjection>

=E3=81=93=E3=82=93=E3=81=AB=E3=81=A1=E3=81=AF

=09


If you pipe this content through the command `qprint -d`, you will obtain a much more interesting text:

From italiano-日本語 (にほんご) FreeDict+WikDict dictionary ver.

2022.11.18 [itajpn]:

ciao //'ʧao// <interjection>

こんにちは


There is little use in encoding content with qprint, but it could do it as well.

# Conclusion

If you ever encounter this kind of encoding, now you should be able to figure what it is, and how to read it.

Qprint may not be available on all systems, but compiling it is quite easy, as long as you have a C compiler and make installed.
</pre>
    ]]>
  </description>
  <guid>gemini://perso.pw/blog//articles/potw-qprint.gmi</guid>
  <link>gemini://perso.pw/blog//articles/potw-qprint.gmi</link>
  <pubDate>Mon, 30 Oct 2023 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Run your own Syncthing discovery server on OpenBSD</title>
  <description>
    <![CDATA[
<pre># Introduction

In a previous article, I covered the software Syncthing and mentioned a specific feature named "discovery server".

The discovery server is used to allow clients to connect each other through NATs to help connect each other, this is NOT a relay server (which is a different service) that serves as a proxy between clients.

A motivation to run your own discovery server(s) would be for security, privacy or performance reasons.



Let's see how to install your own Syncthing discovery daemon on OpenBSD.

=> https://docs.syncthing.net/users/stdiscosrv.html Syncthing discovery daemon documentation

# Setup

On OpenBSD, the binary we need is provided by syncthing package.

pkg_add syncthing


The relay service is done by the binary `stdiscosrv`, you need to create a service file to enable it at boot.  We can use the syncthing service file as a template for the new one.

sed '/^daemon=/ s/syncthing/stdiscosrv/ ; /flags/ s/".*"/""/' /etc/rc.d/syncthing > /etc/rc.d/syncthing_discovery


You created a service named `syncthing_discovery`, it's time to enable and start it.

rcctl enable syncthing_discovery


You need to retrieve the line "Server device IS is XXXX-XXXX......" from the output, keep the ID (which is the XXXX-XXXX-XXXX-XXXX part) because we will need to reuse it later.  We will start the service in debug mode to display the binary output in the terminal.

rcctl -d start syncthing_discovery


Make sure your firewall is correctly configured to let pass incoming connections on port TCP/8443 used by the discovery daemon.

# Client configuration

On the client Web GUI, click on "Actions" and "Settings" to open the settings panel.

In the "Connections tab", you need to change the value of "Global Discovery servers" from "Default" to `https://IP:8443/?id=ID` where IP is the IP address where the discovery daemon is running, and ID is the value retrieved at the previous step when running the daemon.

Depending on your use case, you may want to have the global discovery server plus yours, it's possible to use multiple servers, in which case you would use the value `default,https://IP:8443/?id=ID`.

# Conclusion

If you change the default discovery server by your own, make sure all the peers can reach it, otherwise your syncthing clients may not be able to connect to each other.

# Going further

By default, the discovery daemon will generate self-signed certificate, you could use a Let's Encrypt certificate if you prefer.

There are some other options like prometheus export for getting metrics or changing the connection port, you will find all the extra options in the documentation / man page.
</pre>
    ]]>
  </description>
  <guid>gemini://perso.pw/blog//articles/syncthing-discovery-server.gmi</guid>
  <link>gemini://perso.pw/blog//articles/syncthing-discovery-server.gmi</link>
  <pubDate>Sat, 21 Oct 2023 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Port of the Week: Presenting Syncthing</title>
  <description>
    <![CDATA[
<pre># Introduction

Today's "port of the week" article is featuring Syncthing, a file synchronization software.

=> https://syncthing.net/ Syncthing official project website

# Quick intro

As stated earlier, Syncthing is a network daemon that synchronize files between computers/phones.  Each Syncthing instance must know the other instance ID to trust them and find them over the network.  The transfer are encrypted and efficient, the storage itself can be encrypted.

Some Syncthing vocabulary:



# Interesting features

I gathered a list of interesting features that you may find interesting in Syncthing.

## Security: authentication and encryption

When you need to add a new remote, you need to add the remote's ID on a Syncthing and trust that one on the remote one.  The ID is a human representation of the Syncthing instance certificate fingerprint.  When you exchange ID, you are basically asked to review each certificate and allow each instance to trust the other.

All network transfers occurring between two Syncthing are encrypted using TLS, as the remote certificate can be checked, the incoming data integrity can be verified and authenticated.

=> https://docs.syncthing.net/users/security.html Syncthing official documentation about security principles in the software

## Relaying

I guess this is Syncthing killer feature.  Connecting two remotes is very easy and file transfer between them can bypass firewalls and NATs.

This works because the Syncthing offers a default discovery server which has two purposes:



The file transfer is still encrypted, but having a third party server involved may rise privacy issues, and security risks if a vulnerability can be exploited.

My next blog post will show how to self-host your own Syncthing relay, for better privacy and even more complicated setups!

Note that the discovery server or the relaying can be disabled!  You could also build a mesh VPN and run Syncthing on each node without using any relay or discovery server.

## Built-in file versioning

This may be my preferred feature in Syncthing!

On a given Syncthing instance, you can enable per shared folder a retention policy, aka file versioning in the interface.

Basically, if a file is modified / removed in the share by a remote, the local instance can keep a hidden copy for a while.

There are different versioning modes, from a simple "trash bin" style keeping the files for n days, or more elaborated policies like you could have in backup tools.

=> https://docs.syncthing.net/users/versioning.html Syncthing official documentation about file versioning

## Partial share synchronization

For each share, it's possible to write an exclusion filter, this allows you to either discard sync changes for some pattern (like excluding vim swap files) or entire directories if you don't want to retrieve all the shared folder.

The filter works in both way, if you accept a remote, you could write a filter before starting the synchronization and remove some huge directories you may not want locally.  But this could also allow preventing a directory to be sent to the remotes, like a temporary directory for instance.

This is a topic I covered with a very specific use case, only sync a single file in a directory.

=> https://dataswamp.org/~solene/2023-01-28-syncthing-single-file.html Earlier blog post: Configure Syncthing to sync a single file

## Encrypted remotes

A pretty cool feature I found recently was the support for encrypted shared folders per remote.  I'm using syncthing to keep my KeepassXC databases synchronized between my computers.

As I don't always have at least two of my computers turned ON at the same time, they can't always synchronize directly with each other, so I use a remote dedicated server as a buffer to hold the files, Syncthing encryption is activated for this remote, both my computers can exchange data with it, but on the server itself you can't get my KeepassXC databases.

This is also pretty cool as it doesn't leave any readable data on the storage drive if you use 3rd party systems.

Taking the opportunity here, KeepassXC has a cool feature that allows you to add a binary file as a key in addition to a password / FIDO key.  If this binary file isn't part of the synchronized directory, even someone who could access your KeepassXC database and steal your password shouldn't be able to use it.

## Data chunk based

When Syncthing scans a directory, it will hash all the file into chunks and synchronize all these chunks to other remotes, this is basically how BitTorrent work too.

This may sound boring, but basically, this allows Syncthing to move or rename files on a remote instead of transferring the data again when you rename / move files in a local shared directory.  Indeed, only the changed paths list is sent, and the chunks used in the files, as the files already exist on the remote, the data chunks don't have to be retrieved.

Note that this doesn't work for encrypted remotes as the chunks contain some path information, once encrypted, the same file with different paths will look as two different encrypted chunks.

## Bandwidth control

Syncthing GUI allows you to define inbound or outbound bandwidth limitation, either globally or per remote.  If like me, you have a slow ADSL line with slow upload, you may want to limit the bandwidth used to send data to set the non-local remotes.

## Support for all attributes synchronization

This may sound more niche, but it's important for some users: Syncthing can synchronize file permissions, ownership or even extended attributes.  This is not enabled by default as Syncthing requires elevated privileges (typically running as root) to make it work.

## Runs everywhere

Syncthing is a Go program, it's a small binary with no dependencies, it's quite portable and runs on Linux, all the BSD, Android, Windows, macOS etc...  There is nothing worse than a synchronization utility that can't be installed on a specific computer...

# Conclusion

I really love this software, especially since I figured the file versioning and the encrypted remotes, now I don't fear conflicts or lost files anymore when syncing my files between computers.

My computers also use a local discovery server that allows my Qubes OS to be kept in sync together over the LAN.

# Note for SystemD users

When you install Syncthing on your system, you can enable the service as your user, this will make Syncthing start properly when you log in with your user:

systemctl enable --user syncthing.service


# Note for OpenBSD users

Syncthing has to listen for each file change, you will need to increase the maximum opened files limit for your user, and maybe the limit in the kernel using the according sysctl.

You can find more detailed information about using Syncthing on OpenBSD in the file `/usr/local/share/doc/pkg-readmes/syncthing`.
</pre>
    ]]>
  </description>
  <guid>gemini://perso.pw/blog//articles/potw-syncthing.gmi</guid>
  <link>gemini://perso.pw/blog//articles/potw-syncthing.gmi</link>
  <pubDate>Sat, 07 Oct 2023 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Introduction to the OpenBSD operating system</title>
  <description>
    <![CDATA[
<pre># Introduction

I often see a lot of confusion with regard to OpenBSD, either assimilate as a Linux distribution or mixed up with FreeBSD.

Let's be clear, OpenBSD is a stand alone operating system.  It came as a fork of NetBSD in 1994, there isn't much things in common between the two nowadays.

While OpenBSD and the other BSDs are independant projects, they share some very old roots in their core, and regularly see source code changes in one being imported to another, but this is really a very small amount of the daily code changes though.

# OpenBSD features in 60 seconds

Let's do it quick, what can you find in OpenBSD?



It's used with success on workstations, either for personal or professional use.  It's also widely used as a server, being for network services or just routing/filtering network!

=> https://www.openbsd.org/innovations.html All the innovations that happened in OpenBSD

# Give it a try?

## On a Live-CD

If you never used OpenBSD, you can easily give it a try using the community made LiveCD/LiveUSB FuguIta!

=> https://fuguita.org/ FuguIta project page
=> https://dataswamp.org/~solene/2020-11-18-fuguita.html Older blog page about FuguIta

## In a virtual machine

Another way to easily try OpenBSD is to run it in a virtual machine.

=> https://cdn.openbsd.org/pub/OpenBSD/7.3/amd64/INSTALL.amd64 Complete installation guide of OpenBSD

Please note that the VirtualBox additions are not available as their drivers never got written for OpenBSD.

## On a real system

You can install OpenBSD on your system, or a spare computers you don't use anymore.  You need at least 48 MB of memory for it to work, and many architectures are supported like arm64, amd64, i386, sparc64, powerpc, riscv...

=> https://cdn.openbsd.org/pub/OpenBSD/7.3/amd64/INSTALL.amd64 Complete installation guide of OpenBSD

## On a VPS

You can rent an OpenBSD VM on OpenBSD Amsterdam, a company doing OpenBSD hosting on OpenBSD servers using the OpenBSD hypervisor!  And they give money to the OpenBSD project for each VM they host!

=> https://openbsd.amsterdam/ OpenBSD Amsterdam hosting

# Installing GNOME

I made a tutorial showing how to install GNOME, it's fairly easy!

=> https://dataswamp.org/~solene/2022-04-23-openbsd-video-tutorial-installation.html How to install GNOME on OpenBSD (video tutorial)

# We play video games on OpenBSD!

This is actually possible, and always running native code to run video games.

=> https://videos.pair2jeux.tube/c/openbsd_gaming/videos OpenBSD Gaming video channel (peertube)
=> https://playonbsd.com/games/ PlayOnBSD Games compatibility list
=> https://www.reddit.com/r/openbsd_gaming/ OpenBSD_gaming subreddit community

# Going further

=> https://www.openbsd.org The OpenBSD project website
=> https://en.wikipedia.org/wiki/OpenBSD OpenBSD on Wikipedia
</pre>
    ]]>
  </description>
  <guid>gemini://perso.pw/blog//articles/octopenbsd-2023-openbsd-intro.gmi</guid>
  <link>gemini://perso.pw/blog//articles/octopenbsd-2023-openbsd-intro.gmi</link>
  <pubDate>Sun, 01 Oct 2023 00:00:00 GMT</pubDate>
</item>
<item>
  <title>This is OctOpenBSD month</title>
  <description>
    <![CDATA[
<pre># Introduction

We are in October 2023, let's celebrate the first OctOpenBSD event, the month where OpenBSD users show to the world our favorite operating system is still relevant.

The event will occur from 1st October up to 31st October.  A surprise will be revealed on the OpenBSD Webzine for the last day!

=> https://webzine.puffy.cafe The OpenBSD Webzine website

=> static/octopenbsd-2023.png A Puffy telling the hacker girl that sometimes we need to take a break
=> https://merveilles.town/@prahou Artwork by Prahou, the unix_surrealism artist

# What to do in OctOpenBSD?

There is a lot you can do!  It's just small things, that accumulated as a community will turn this into a great community event!

To contribute to OctOpenBSD, you can:



Let's celebrate!

# FAQ

If you have any question about the event, I'll answer them and gather the QA in this section.
</pre>
    ]]>
  </description>
  <guid>gemini://perso.pw/blog//articles/octopenbsd-2023.gmi</guid>
  <link>gemini://perso.pw/blog//articles/octopenbsd-2023.gmi</link>
  <pubDate>Sun, 01 Oct 2023 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Firefox hardening with Arkenfox</title>
  <description>
    <![CDATA[
<pre># Introduction

Dear Firefox users, what if I told you it's possible to harden Firefox by changing a lot of settings?  Something really boring to explain and hard to reproduce on every computer.  Fortunately, someone did the job of automating all of that under the name Arkenfox.

Arkenfox design is simple, it's a Firefox configuration file (more precisely a `user.js` file), that you have to drop in your profile directory to override many Firefox defaults with a lot of curated settings to harden privacy and security.  Cherry on cake, it features an updater and a way to override some of its values with a user defined file.

This makes Arkenfox easy to use on any system (including Windows), but also easy to tweak or distribute across multiple computers.

=> https://github.com/arkenfox/user.js Arkenfox user.js GitHub project page
=> https://github.com/arkenfox/user.js/wiki Arkenfox user.js Documentation

# Setup

The official documentation contains more information, but basically the steps are the following:

1. find your Firefox profile directory: open `about:support` and search for an entry name profile directory
2. download latest Arkenfox user.js release archive
2. if the profile is not new, there is an extra step to clean it using `scratchpad-scripts/arkenfox-cleanup.js` which contains instructions at the top of the file
3. save the file `user.js` in the profile directory
4. add `update.sh` to the profile directory, so you can update `user.js` easily later
5. create `user-overrides.js` in the profile directory if you want to override some settings and keep them, the updater is required for the override

# Configuration

Basically, Arkenfox disables a lot of persistency such as cache storage, cookies, history.  But it also enforces a canvas of fixed size to render the content, reset the preferred languages to English only (that defines which language is used to display a multilingual website) and many more changes.

You may want to override some settings because you don't like them.  In the project's Wiki, you can find all Arkenfox overrides, with the explanation of its new value, and which value you may want to use in your own override.

=> https://github.com/arkenfox/user.js/wiki/3.2-Overrides-%5BCommon%5D Arkenfox user.js Wiki about common overrides

For instance, if you want to re-enable the cache storage, add the following code to the file `user-overrides.js`.

user_pref("browser.cache.disk.enable", true);

user_pref("privacy.clearOnShutdown.cache", false);


Now, run the updater script, that will verify that Arkenfox user.js file is the latest version, and will append your override to it.

# Tips

By default, cookies aren't saved, so if you don't want to log in every time you restart Firefox, you have to specifically allow cookies for each website.

The easiest method I found is to press `Ctrl+I`, visit the Permissions tab, and uncheck the "Default permissions" relative to cookies.  You could also do it by visiting Firefox settings, and search for an exception button in which you can enter a list of domains where cookies shouldn't be cleared on shutdown.

By default, entering text in the address bar won't trigger a search anymore, so instead of using Ctrl+L to type in the bar, you can use Ctrl+K to type for a search.

# Extensions

Arkenfox wiki recommends to use uBlock Origin and Skip redirect extensions only, with some details.  I agree they both work well and do the job.

It's possible to harden uBlock Origin by disabling 3rd party scripts / frames by default, and giving you the opportunity to allow per domain / globally some sources, this is called the blocking mode.  I found it to be way more usable than NoScript.js.

=> https://github.com/gorhill/uBlock/wiki/Blocking-mode:-medium-mode uBlock Origin blocking mode documentation

# Conclusion

I found that Arkenfox was a bit hard to use at first because I didn't fully understand the scope of its changes, but it didn't break any website even if it disables a lot of Firefox features that aren't really needed.

This reduces Firefox attack surface, and it's always a welcome improvement.

# Going further

Arkenfox user.js isn't the only set of Firefox settings around, there is also Betterfox (thanks prx!) which provides different profiles, even one for performance.  I didn't try any of these profiles yet, Arkenfox and Betterfox are parallel projects and not forks, it's actually complicated to compare which one would be better.

=> https://github.com/yokoffing/Betterfox Betterfox Github project page
</pre>
    ]]>
  </description>
  <guid>gemini://perso.pw/blog//articles/harden-firefox-with-arkenfox.gmi</guid>
  <link>gemini://perso.pw/blog//articles/harden-firefox-with-arkenfox.gmi</link>
  <pubDate>Wed, 27 Sep 2023 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Flatpak integration in Qubes OS templates</title>
  <description>
    <![CDATA[
<pre># Introduction

I recently wanted to improve Qubes OS accessibility to new users a bit, yesterday I found why GNOME Software wasn't working in the offline templates.

Today, I'll explain how to install programs from Flatpak in a template to provide to other qubes.  I really like flatpak as it provides extra security features and a lot of software choice, and all the data created by Flatpak packaged software are compartmentalized into their own tree in `~/.var/app/program.some.fqdn/`.

=> https://qubes-os.org Qubes OS official project website
=> https://www.flatpak.org/ Flatpak official project website
=> https://flathub.org/ Flathub: main flatpak repository

# Setup

All the commands in this guide are meant to be run in a Fedora or Debian template as root.

In order to add Flathub repository, you need to define the variable `https_proxy` so flatpak can figure how to reach the repository through the proxy:

export https_proxy=http://127.0.0.1:8082/

flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo


Make the environment variable persistent for the user `user`, this will allow GNOME Software to work with flatpak and all flatpak commands line to automatically pick the proxy.

mkdir -p /home/user/.config/environment.d/

cat <<EOF >/home/user/.config/environment.d/proxy.conf

https_proxy=http://127.0.0.1:8082/

EOF


In order to circumvent a GNOME Software bug, if you want to use it to install packages (Flatpak or not), you need to add the following line to `/rw/config/rc.local`:

ip route add default via 127.0.0.2


=> https://gitlab.gnome.org/GNOME/gnome-software/-/issues/2336 GNOME Software gitlab issue #2336 saying a default route is required to make it work

Restart the template, GNOME software is now able to install flatpak programs!

# Qubes OS integration

If you install or remove flatpak programs, either from the command line or with the Software application, you certainly want them to be easily available to add in the qubes menus.

Here is a script to automatically keep the applications list in sync every time a change is made to the flatpak applications.

## Inotify-tool

For the setup to work, you will have to install the package `inotify-tools` in the template, this will be used to monitor changes in a flatpak directory.

## Syncing app menu script

Create `/usr/local/sbin/sync-app.sh`:

!/bin/sh

when a desktop file is created/removed

- links flatpak .desktop in /usr/share/applications

- remove outdated entries of programs that were removed

- sync the menu with dom0

inotifywait -m -r \

-e create,delete,close_write \

/var/lib/flatpak/exports/share/applications/ |

while IFS=':' read event

do

find /var/lib/flatpak/exports/share/applications/ -type l -name "*.desktop" | while read line

do

ln -s "$line" /usr/share/applications/

done

find /usr/share/applications/ -xtype l -delete

/etc/qubes/post-install.d/10-qubes-core-agent-appmenus.sh

done


You have to mark this file as executable with `chmod +x /usr/local/sbin/sync-app.sh`.

## Start the file monitoring script at boot

Finally, you need to activate the script created above when the templates boots, this can be done by adding this snippet to `/rw/config/rc.local`:

start monitoring flatpak changes to reload icons

/usr/local/sbin/sync-app.sh &


## Updating

This solution will look for flatpak programs updates each time the template starts, which should occur regularly to update the template packages, and update them unconditionnaly.

Add this snippet to `/rw/config/rc.local`:

check for update

export https_proxy=http://127.0.0.1:8082/

flatpak upgrade -y --noninteractive


This could be enhanced by asking the user if they want to update or skip for later, but I still have to figure how to make `notify-send` from the root user, I opened a Qubes OS issue about this.

# Conclusion

With this setup, you can finally install programs from flatpak in a template to provide it to other qubes, with bells and whistles to not have to worry about creating desktop files or keeping them up to date.

Please note that while well-made Flatpak programs like Firefox will add extra security, the repository flathub allows anyone to publish programs.  You can browse flathub to see who is publishing which software, they may be the official project team (like Mozilla for Firefox) or some random people.
</pre>
    ]]>
  </description>
  <guid>gemini://perso.pw/blog//articles/flatpak-on-qubesos.gmi</guid>
  <link>gemini://perso.pw/blog//articles/flatpak-on-qubesos.gmi</link>
  <pubDate>Mon, 18 Sep 2023 00:00:00 GMT</pubDate>
</item>
<item>
  <title>How to add pledge to a program in OpenBSD</title>
  <description>
    <![CDATA[
<pre># Introduction

This article is meant to be a simple guide explaining how to make use of the OpenBSD specific feature pledge in order to restrict a software capabilities for more security.

While pledge falls in the sandboxing features, it's different than the traditional sandboxing we are used to see because it happens within the source code itself, and can be really tightened.  Actually, many programs requires lot of privileges like reading files, doing DNS etc... when initializing, then those privileges could be removed, this is possible with pledge but not for traditional sandboxing wrappers.

In OpenBSD, most of the base userland have support for pledge, and more and more packaged software (including Chromium and Firefox) received some code to add pledge.  If a program tries to use a system call that isn't in pledge promises list, it dies and the violation is reported in the system logs.

What makes pledge pretty cool is how it's easy to implement it in your software, it has a simple mechanism of system call families so you don't have to worry about listing every system calls, but only their categories (named promises), like reading a file, writing a file, executing binaries etc...

=> https://man.openbsd.org/pledge.2 OpenBSD manual page for pledge(2)

# Let's pledge a program

I found a small utility that I will use to illustrate how to add pledge to a program.  The program is qprint, a C quoted printable encoder/decoder.  This kind of converter is quite easy to pledge because most of the time, they only take an input, do some computation and make an output, they don't run forever and don't do network.

=> https://www.fourmilab.ch/webtools/qprint/ qprint official project page

## Digging in the sources

When extracting the sources, we can find a bunch of files, we will focus at reading the `*.c` files, the first thing we want to find is the function `main()`.

It happens the main function is in the file `qprint.c`.  It's important to call pledge as soon as possible in the program, most of the time after variable initialization.

## Modifying the code

Adding pledge to a program requires to understand how it works, because some feature that aren't often used may be broken by pledge, and some programs having live reloading or being able to change behavior during runtime are complicated to pledge.

Within the function `main` below variables declaration, We will add a call to pledge for `stdio` because the program can display the result on the output, `rpath` because it can read files and `wpath` as it can also write files.

include <unistd.h>

[...]

pledge("stdio rpath wpath", NULL);


It's ok, we imported the library providing pledge, and called it from within.  But what if the pledge call fails for some reasons?  We need to ensure it worked or abort the program.  Let's add some checks.

include <unistd.h>

include <err.h>

[...]

if (pledge("stdio rpath wpath", NULL) == -1) {

err(1, "pledge call didn't work");

}


This is a lot better now, if pledge call failed, the program will stop and we will be warned about it.  I don't know exactly under which circumstance it could fail, but maybe if promise name changes or doesn't exist anymore in a program, that would be bad if pledge silently failed.

## Testing

Now we made some changes to the program, we need to verify it's still working as expected.

Fortunately, qprint comes with a test suite which can be used with `make wringer`, if the test suite pass and the tests have a good coverage, this mean we may have not break anything.  If the test suite fails, we should have an error in the output of `dmesg` telling us why it failed.

And, it failed!

qprint[98802]: pledge "cpath", syscall 5


This error (which killed the PID instantly) indicates that the pledge list is missing `cpath`, this makes sense because it has to create new files if you specify an output file.

Adding `cpath` to the list, and running the test suite again, all tests pass!  Now, we exactly know that the software can't do anything except using the system calls we whitelisted.

We could tighten pledge more by dropping `rpath` if the file is read from stdin, and `cpath wpath` if the output is sent to stdout.  I left this exercise to the reader :-)

## The diff

Here is my diff to add pledge support to qprint.

Index: qprint.c

--- qprint.c.orig

+++ qprint.c

@@ -2,6 +2,8 @@

#line 70 "./qprint.w"

#include "config.h"

+#include <unistd.h>

+#include <err.h>

#define REVDATE "16th December 2014" \

@@ -747,6 +749,9 @@ char*cp;

+if (pledge("stdio cpath rpath wpath", NULL) == -1) {

+ err(1, "pledge error");

+}

fi= stdin;

fo= stdout;


# Using pledge in non-C programs

It's actually possible to call pledge() in other programming languages, Perl has a library provided in OpenBSD base system that will work out of the box.  For some other, such library may be packaged already (for python and Golang at least).  If you use something less common, you can define an interface to call the library.

=> https://man.openbsd.org/man3p/OpenBSD::Pledge.3p OpenBSD manual page for the Perl pledge library

Here is an example in Common LISP to create a new function `c-kiosk-pledge`.

+ecl

(progn

(ffi:clines "

#include <unistd.h>

void kioskPledge() {

pledge(\"dns inet stdio tty rpath\",NULL);

}

#endif")

#+openbsd

(ffi:def-function

("kioskPledge" c-kiosk-pledge)

() :returning :void))


# Extra

It's possible to find which running programs are currently using pledge() by using `ps auxww | awk '$8 ~ "p" { print }'`, any PID with a state containing `p` indicates it's pledged.

If you want to add pledge to a packaged program on OpenBSD, make sure it still fully work.

Adding pledge to a program that contain most promises won't be doing much...

# Exercise reader

Now, if you want to practice, you can tighten the pledge calls to only allow qprint to use the pledge `stdio` only in the case it's used in a pipe for input and output like this: `./qprint < input.txt > output.txt`.

Ideally, it should add the pledge `cpath wpath` only when it writes into a file, and `rpath` only when it has to read a file, so in the case of using stdin and stdout, only `stdio` would have been added at the beginning.

Good luck, Have fun!  Thanks to Brynet@ for the suggestion!

# Conclusion

The system call pledge() is a wonderful security feature that is reliable, and as it must be done in the source code, the program isn't run from within a sandboxed environment that may be possible to escape.  I can't say pledge can't be escaped, but I think it's a lot less likely to be escaped than any other sandbox mechanism (especially since the program immediately dies if it tries to escape).

Next time, I'll present its companion system called unveil which is used to restrict access to the filesystem, except some developer defined files.
</pre>
    ]]>
  </description>
  <guid>gemini://perso.pw/blog//articles/openbsd-how-to-pledge-a-program.gmi</guid>
  <link>gemini://perso.pw/blog//articles/openbsd-how-to-pledge-a-program.gmi</link>
  <pubDate>Mon, 11 Sep 2023 00:00:00 GMT</pubDate>
</item>
<item>
  <title>My top 20 video games</title>
  <description>
    <![CDATA[
<pre># Introduction

I wanted to share my favorite games list of all time.  Making the list wasn't easy though, but I've set some rules to help deciding myself.

Here are the criteria:



Trivia, I'm not a huge gamer, I still play many games nowaday, but I only play each of them for a couple of hours to see what they have to offer in term of gameplay, mechanics, and see if they are innovative in some way.  If a game is able to surprise me or give me something new, I may spend a bit more time on it.

# My top 20

Here is the list of my top 20 games I enjoyed, and with which I'd be fine to enjoy play them again anytime.

I tried to elect some games to be a bit better than the other, so there is my top 3, top 10, and the top 20.  I haven't been able to rank them from 1 to 20, so I just made tiers.

## Top 20 to 11

### Heroes of Might and Magic III

=> https://www.gog.com/fr/game/heroes_of_might_and_magic_3_complete_edition Product page on GOG

I spent so many hours playing with my brother or friends, sharing the mouse each turn so everyone could play with a single computer.

And not only the social factor was nice, the game was cool, there are many different factions to play, the game is cool and there is strategy at play to win.  A must have.

### Saturn Bomberman

=> https://retrospiritgames.blogspot.com/2013/11/retro-review-saturn-bomberman-saturn.html Game review

The Sega Saturn hasn't been very popular, but it had some good games, and one is Saturn Bomberman.  From all the games from the Bomberman franchise, this looks really the best, it featured some dinosaurs with unique abilities, and they could grow up, some weird items, many maps.

And it had an excellent campaign that was long to play, and could be played in coop!  The campaign was really really top notch for this kind of game, with unique items you couldn't find in multiplayer.

### Tony Hawk's Pro Skater 1 and 2

=> https://store.epicgames.com/fr/p/tony-hawks-pro-skater-1-and-2 Product page on Epic Game Store

I guess this is a classic, I played a lot the Nintendo 64 version, and now we have the 1+2 games into one, with high refresh rate, HD textures and still the same good music.

A chill game that is always fun to play.

### Risk of rain 2

=> https://store.steampowered.com/app/632360/Risk_of_Rain_2/ Product page on Steam

A pure rogue-like that shines in multiplayer, lot of classes, lot of weapons, lot of items, lot of enemies, lot of fun.

While it's not the kind of game I'd play all day, I'm always up for a run or two.

### Warhammer 40K: Dawn of War

=> https://store.steampowered.com/app/4580/Warhammer_40000_Dawn_of_War__Dark_Crusade/ Product page on Steam (Dark Crusade)

This may sound like heresy, but I never played the campaign of this game.  I just played skirmish or in multiplayer with friends, and with the huge factions choice with different gameplay, it's always cool even if the graphics aged a bit.

Being able to send dreadnought from space directly into the ork base, or send legions of necrons to that Tau player is always source of joy.

### Street Fighter 2 Special Champion Edition

=> https://www.youtube.com/watch?v=sPTb1nvRg4s Video review on YouTube

A classic on the megadrive/genesis, it's smooth, music is good.  So many characters and stages, incredible soundtracks.  The combos were easy to remember, just enough to give each character their own identity and allow players to quickly onboard.

Maybe the super NES version is superior, but I always played it on megadrive.

### Slay the Spire

=> https://www.gog.com/fr/game/slay_the_spire Product page on GOG

Maybe the game which demonstrated we can do great deck based video games.

Playing a character with a set of skills as cards, gathering items while climbing a tower, it can get a bit repetitive over time though, but the game itself is good and doing a run occasionally is always tempting.

The community made a lot of mods, even adding new characters with very specific mechanics, I highly recommend it for anyone looking for a card based game.

### Monster Hunter 4 Ultimate

=> https://www.ign.com/articles/2015/02/10/monster-hunter-4-ultimate-review Game review on IGN

My first Monster Hunter game, on 3DS.  I absolutely loved it, insane fights against beloved monsters (we need to study them carefully, so we need to hunt a lot of them :P).

While Monster Hunter World shown better graphics and smoother gameplay, I still prefer the more rigid MH like MH4U or MH Generations Ultimate.

The 3D effect on the console was working quite well too!

### Peggle Nights

=> https://store.steampowered.com/app/3540/Peggle_Nights/ Product page on Steam

A simple arcade game with some extra powers depending on the character you picked.  It's really addictive despite the gameplay being simplistic.

### Monster Train

=> https://www.gog.com/fr/game/monster_train Product page on GOG

A very good card game with multiple factions, but not like Slay the Spire.

There are lot of combos to create as cards are persistent within the train, and runs are not that much depending on RNG (random number generator), which make it a great game.

## Top 10 to 4

Not ranked, let's enter the top 10 up to just before the top 3.

### Call of Cthulhu: Prisoner of Ice

=> https://www.gog.com/fr/game/call_of_cthulhu_prisoner_of_ice Product page on GOG

One of the first PC game I played, when I was 6.  I'm not into point & click usually, but this one features Lovecraft horrors, so it's good :)

### The Elder Scrolls IV: Oblivion

=> https://www.gog.com/fr/game/elder_scrolls_iv_oblivion_game_of_the_year_edition_deluxe_the Product page on GOG

A classic among the RPG, I wanted to put an Elder Scrolls game into the list and I went with Oblivion.  In my opinion, this was the coolest one compared to Morrowind or Skyrim.  I have to say, I just hesitated with Morrowind, but because of all Morrowind flaws and issues, Oblivion built a better game.  Skyrim was just bad for me, really boring and not interesting.

Oblivion gave the opportunity to discover many cities with day/night cycle, NPC that had homes and were at work during day, the game was incredible when it was released, and I think it's still really good.

Trivia, I never did the story of Morrowind or Oblivion, but yet I spent a lot of time playing them!

### Shining the Holy Ark

=> https://www.youtube.com/watch?v=MF2q28fWRzA Video review on YouTube

Another Sega Saturn game, almost unknown to the public I guess.  While not a Shining Force game, it's part of the franchise.

It's an RPG / dungeon crawler in first person view, in which you move from tiles to tiles and sometimes fight monster with your team.

### Into the Breach

=> https://www.gog.com/fr/game/into_the_breach Product page on GOG

The greatest puzzle game I ever played.  It's like chess, but actually fun.  Moving some mechas on a small tiled board when it's your turn, you must think about everything that will happen and in which order.

The number of mechas and equipment you find in the game make it really replayable, and game sessions can be short so it's always tempting to start yet another run.

### Like a Dragon

=> https://www.gog.com/fr/game/yakuza_like_a_dragon Product page on GOG

My first Yakuza / Like a dragon game, I didn't really know what to expect, and I was happy to discover it!

A Japanese RPG / turn based game featuring the most stupid skills or quests I've ever seen.  The story was really engaging, unlocking new jobs / characters leads to more stupidity around.

### Secret of Mana

=> https://www.ign.com/articles/2008/10/14/secret-of-mana-review Game review on IGN

A super NES classic, and it was possible to play in coop with a friend!

The game had so much content, lot of weapons, of magic, of monsters, the soundtrack is just incredible all along.  And even more, at some point in the game you have the opportunity to move from your current location by riding a dragon in a 3D view over the planet!

I start and finish this game every few years!

### Baldur's Gate 3

=> https://www.gog.com/fr/game/baldurs_gate_iii Product page on GOG

At the moment, it's the best RPG I played, and it's turn based like how I like them.

I'd have added Neverwinter Night, but BG3 does better than it in every way, so I retained BG3 instead.

Every new game could be played a lot differently than the previous one, there are so many possibilities out there, it's quite the next level of RPG compared to what we had before.

## Top 3

And finally, not ranked but my top 3 of my favorite games!

### Factorio

=> https://www.gog.com/fr/game/factorio Product page on GOG

After hesitating between Factorio and Dyson Sphere Program in the list, I chose to retain Factorio, because DSP is really good, but I can't see myself starting it again and again like Factorio.  DSP has a very very slow beginning, while Factorio provides fun much faster.

Factorio invented a new genre of game: automation.  I get crazy with automation, optimization.  It's like doing computer stuff in a game, everything is clean, can be calculated, I could stare at conveyor belts transporting stuff like I could stare at Gentoo compilation logs for hours.  The game is so deep, you can do crazy things, even more when you get into the logic circuits.

While I finished the game, I'm always up for a new world with some goals, and modding community added a lot of high quality content.

The only issue with this game is that it's hard to stop playing.

### Street of rage 4

=> https://www.gog.com/fr/game/streets_of_rage_4 Product page on GOG

While I played Street of Rage 2 a lot more than the 4Th, I think this modern version is just better.

You can play with a friend almost immediately, fun is there, brawling bad guys is pretty cool.  The music are good, the character roster is complete, it's just 100% fun to play it again and again.

### Outer Wilds

=> https://store.steampowered.com/app/753640/Outer_Wilds/ Product page on Steam

That's one game I wish I could forget to play it again...

It gave me a truly unique experience as a gamer.

It's an adventure game featuring a time loop of 15 minutes, the only things you acquire in the game is knowledge in your own mind.  With that knowledge, you can complete the game in different ways, but first, you need to find clues leading to other clues, leading to some pieces of the whole puzzle.

# Games that I couldn't put in the list

There are some games I really enjoyed, but for some reasons I haven't been able to put them in the list, could be replayability issues or the nostalgia factor that was too high maybe?


</pre>
    ]]>
  </description>
  <guid>gemini://perso.pw/blog//articles/my-top20-favorite-video-games.gmi</guid>
  <link>gemini://perso.pw/blog//articles/my-top20-favorite-video-games.gmi</link>
  <pubDate>Thu, 31 Aug 2023 00:00:00 GMT</pubDate>
</item>

  </channel>
</rss>