https://scarpino.dev/Andrea Scarpino's blog2022-09-15T00:00:00ZAndrea Scarpinohttps://scarpino.devtag:scarpino.dev,2022-09-15:/posts/sniffing-android-apps-network-traffic.htmlSniffing Android apps network traffic2022-09-15T00:00:00Z2022-09-15T00:00:00Z<p>Back in the days, it was really easy to sniff the network traffic made by the
Apps in Android. You could do it in a few minutes by adding mitmproxy’s
certificate and setting the HTTP proxy on your wifi network settings. That was it.
But things have changed (for good) and that’s no longer the case. However, I
still want to sniff the network traffic made by the Apps in Android.</p>
<p>How? Well, I can no longer use my smartphone to do it, but I can set up the
Android emulator, install the application via the Google Play Store and sniff
the network traffic it generates on my PC \o/</p>
<p>Let’s get started. First, install the Android SDK and create an Android virtual
device using Android API 30 and x86 architecture (any API and any architecture
is fine). However, we need an image without Google Play Store preinstalled as
we need a writable <code>/system</code> folder to inject mitmproxy’s certificate later.
That’s okay, because we’ll install the Play Store manually.</p>
<pre><code>echo no | ./Android/Sdk/tools/bin/avdmanager create avd -n Pixel_5_API_30 --abi google_apis/x86 --package 'system-images;android-30;google_apis;x86'
</code></pre>
<p>Start the virtual device with the additional <code>-writable-system</code> flag which
permits us to make <code>/system</code> writable. I also have to unset <code>QT_QPA_PLATFORM=</code>
because I’m on wayland and the emulator doesn’t support it.</p>
<pre><code>QT_QPA_PLATFORM= ./Android/Sdk/emulator/emulator @Pixel_5_API_30 -writable-system
</code></pre>
<p>Now let’s download the <a href="https://opengapps.org/">OpenGAPPs</a> that match our API and architecture.
Select the <code>pico</code> variant because we don’t need anything else, just the Play Store.</p>
<pre><code>curl -OL 'https://master.dl.sourceforge.net/project/opengapps/x86/20220503/open_gapps-x86-11.0-pico-20220503.zip'
</code></pre>
<p>We’ve to decompress it in order to get and push <code>Phonesky.apk</code> to the virtual
device. We also need to whitelist its permissions (thank you to the <a href="https://github.com/FriendlyNeighborhoodShane/MinMicroG">MinMicroG</a>
guys).</p>
<pre><code>unzip open_gapps-x86-11.0-pico-20220503.zip
lzip -d Core/vending-x86.tar.lz
tar xf vending-x86.tar
adb root
adb shell avbctl disable-verification # adb disable-verity makes the emulator crash
adb reboot
adb wait-for-device
adb root
adb remount
adb push vending-x86/nodpi/priv-app/Phonesky/Phonesky.apk /system/priv-app/
curl -O https://raw.githubusercontent.com/FriendlyNeighborhoodShane/MinMicroG/master/res/system/etc/permissions/com.android.vending.xml
adb push com.android.vending.xml /system/etc/permissions/
</code></pre>
<p>Now, create a dedicated user to run mitmproxy as it’s written in the <a href="https://docs.mitmproxy.org/stable/howto-transparent/#work-around-to-redirect-traffic-originating-from-the-machine-itself">documentation</a>:</p>
<pre><code>sudo useradd --create-home mitmproxyuser
sudo iptables -t nat -A OUTPUT -p tcp -m owner ! --uid-owner mitmproxyuser --dport 80 -j REDIRECT --to-port 8080
sudo iptables -t nat -A OUTPUT -p tcp -m owner ! --uid-owner mitmproxyuser --dport 443 -j REDIRECT --to-port 8080
sudo -u mitmproxyuser -H bash -c 'mitmproxy --mode transparent --showhost --set block_global=false'
</code></pre>
<p>Mandatory copy’n’paste from the mitmproxy documentation page:
> Note, as soon as you add the iptables rules, you won’t be able to perform successful network calls until you start mitmproxy.</p>
<p>At this point we are almost there, we just need another step to add the
mitmproxy certificate as it’s written in the <a href="https://docs.mitmproxy.org/stable/howto-install-system-trusted-ca-android/#3-insert-certificate-into-system-certificate-store">documentation page</a>:</p>
<pre><code>hashed_name=`sudo openssl x509 -inform PEM -subject_hash_old -in ~mitmproxyuser/.mitmproxy/mitmproxy-ca-cert.cer | head -1`
sudo adb push ~mitmproxyuser/.mitmproxy/mitmproxy-ca-cert.cer /system/etc/security/cacerts/$hashed_name.0
adb shell chmod 664 /system/etc/security/cacerts/$hashed_name.0
adb reboot
</code></pre>
<p>You should now have the Play Store, login with your Google account and install
the App you need.</p>
<p>That’s it! Happy sniffing!</p>
tag:scarpino.dev,2022-02-25:/posts/i-went-out-for-dinner-and-i-took-some-endpoint.htmlI went out for dinner and I took some endpoint2022-02-25T00:00:00Z2022-02-25T00:00:00Z<p>Three weeks ago I went out to a pub for dinner. Due to covid restrictions there are no paper menus anymore and the waitress gave me a card to place my order.</p>
<p>The card she gave me had a QR code and a 5-digit number. I scanned the QR code and opened the website it pointed to. To login I used that 5-digit number. I placed my order. So far so good.</p>
<p>When suddenly a hamburger button caught my attention. I pressed it, but mostly I clicked on the first item in the menu because, judging by its text, it seemed “nice” to have a look at the order I had just placed:</p>
<p><a href="/images/order_hamburger_button.jpg"><img src="/images/order_hamburger_button_thumb.jpg" alt="Hamburger button" /></a></p>
<p><a href="/images/order_history.jpg"><img src="/images/order_history_thumb.jpg" alt="Order history" /></a></p>
<p>Uh?! 4751€?! Definitely not me! To my surprice that page listed many orders, not just mine, and they were also old. That’s interesting.</p>
<p>Once back home, I wanted to understand it more. I opened the website in my browser, but I failed to login because my 5-digit number “expired”, then I gave it a few tries by increasing it and it worked :-)</p>
<p>I took a look at the JavaScript files to find the one that makes the request to retrieve the orders:</p>
<pre><code>$.ajax({
type: "POST",
url: '/include/ajax.php?f=getlist&t=orders',
data: {
src:[
{
name:"self_cart_id",
value:app.table_id,
compare:"equal"
}
],
orderby: "id DESC"
}
</code></pre>
<p>Let’s do the same request, changing the <code>value</code> (<code>app.table_id</code>) parameter and see what happens:</p>
<pre><code>curl 'https://$HOST/include/ajax.php?f=getlist&t=orders' -X POST --data-raw "src%5B0%5D%5Bname%5D=self_cart_id&src%5B0%5D%5Bvalue%5D=1&src%5B0%5D%5Bcompare%5D=equal&orderby=id+DESC"
</code></pre>
<p>I got fewer orders. Then I increase the <code>table_id</code> and I got even less orders. Mmm, I take a second look at the parameters and then I realize that’s a query statement! At this point I played a bit with the parameters until I removed the <code>value</code> parameter completly. Well, now I got 347752 orders and they are even paginated:</p>
<pre><code>"success": 1,
"pag": "1",
"per_pag": 500,
"total_records": 347752,
"total_pages": 696,
</code></pre>
<p>Fortunately, there was no sensitive information. I got all the orders made in the last ~2 years from all the pubs scattered around italy (the pub is part of a franchising). There was some Deliveroo/UberEats/Glovo id, but nothing sensitive. Not yet.</p>
<p>Back to the JavaScript file, there were few interesting calls:</p>
<pre><code> url: '/include/ajax.php?f=get&t=customers&id='+app.customer_id,
url: '/include/ajax.php?f=edit_customer&t=self_cart&id='+app.table_id,
url: '/include/ajax.php?f=getlist&t=categories',
url: '/include/ajax.php?f=getlist&t=products',
url: '/include/ajax.php?f=get&t=products&id='+$(this).attr("data-id"),
url: '/include/ajax.php?f=edit_product&t=self_cart&id='+app.table_id,
</code></pre>
<p>I tried with the most tempting, <code>customers</code>, and here we go:</p>
<pre><code>curl 'https://$HOST/include/ajax.php?f=getlist&t=customers'
"success": 1,
"pag": 1,
"per_pag": 500,
"total_records": 11928,
"total_pages": 24,
"rows": [
{
"surname": "<REDACTED>",
"name": "<REDACTED>",
"email": "<REDACTED>",
"mobile": "<REDACTED>",
"addresses": [
{
"name": "<REDACTED>",
"surname": "",
"address": "<REDACTED>",
"zipcode": "<REDACTED>",
"city": "<REDACTED>",
"province": "<REDACTED>",
"coord": "44.6<REDACTED>, 10.6<REDACTED>",
"doorphone": "<REDACTED>",
}
]
"barcode": "https:\/\/api.$ANOTHER_HOST\/include\/barcode.php?f=png&s=code-128&d=1",
</code></pre>
<p>That single request returned 500 out of 11928 results that include full names, phone numbers and addresses of real persons who placed their orders through one of those food delivery apps.</p>
<p>Back to the JavaScript file, the <code>edit_product</code> call is also very tempting (what if I change the price of a product, place my order, and then restore the original price?), but I had already eaten dinner and didn’t try it.</p>
<p>Finally, the <code>$ANOTHER_HOST</code> domain got my attention because it points to a different domain. I googled it and I then realized that this pub was using an e-commerce made by a company that claims on their website that they serve 570 restaurants in Italy. Which makes that 11928 <strong>way larger</strong>.</p>
<p>To confirm this, I first googled the footer text in the e-commerce and actually found ~100 other websites using it that are affected by the same issue. Then, I found others using DNS enumeration targeting the $ANOTHER_HOST domain.</p>
<p>I warned the company about the unauthenticated endpoints and the possible data leak affecting them and their customers. They politely replied that they don’t provide bug bounties and the endpoints have been patched.</p>
tag:scarpino.dev,2021-06-11:/posts/im-back-in-the-boat.htmlI'm back in the boat2021-06-11T00:00:00Z2021-06-11T00:00:00Z<p>In mid-2014 I first heard about <a href="https://jolla.com">Jolla</a> and <a href="https://sailfishos.org">Sailfish OS</a> and immediately bought a Jolla 1; wrote apps; participated in the IGG campaign for Jolla Tablet; bought the TOHKBD2; applied for (and got) Jolla C.</p>
<p>Sounds like the beginning of a good story doesn’t it?</p>
<p>Well, by the beginning of 2017 I had sold everything (except the tablet, we all know <a href="https://blog.jolla.com/jolla-tablet-project-update/">what happened</a> to that one).</p>
<p>So what happened?? I was a happy Sailfish user, but Jolla’s false promises disappointed me.</p>
<p>Yet, despite all that, I still think about Sailfish OS to this day. I think it’s because, despite <a href="https://reviewjolla.blogspot.com/p/sailfish-os-open-source-licencing-stage.html">some proprietary components</a>, the ecosystem around Sailfish OS is ultimately open source. And that’s what interests me. It also got <a href="https://blog.jolla.com/koli/">a fresh update</a> which solves some of the problems that where there 5 years ago.</p>
<p>Nowadays, <strong>thanks to the community</strong>, Sailfish OS can be installed on <a href="https://wiki.merproject.org/wiki/Adaptations/libhybris">many devices</a>, even if with some less components, but I’m looking for that complete experience and so I asked on the <a href="https://forum.sailfishos.org">forum</a> if there was someone willing to sell his Xperia device with or without the license… and I got one for free. Better still, in exchange for some apps!</p>
<p>To decide which applications to create, I therefore took a look at that ecosystem. I started with the apps I use daily on Android and looked for the Sailfish OS alternative (spoiler: I’m impressed, good job guys!).</p>
<p>I am writing them all here because I am sure it will be useful to someone else:</p>
<ul>
<li>AntennaPod (podcast app) -> <a href="https://gitlab.com/cy8aer/podqast">PodQast</a></li>
<li>Ariane (gemini protocol browser)</li>
<li>AsteroidOS (AsteroidOS sync) -> <a href="https://github.com/AsteroidOS/starfish">Starfish</a></li>
<li>Connectbot (ssh client) -> built-in (Terminal)</li>
<li>Conversation (xmpp client) -> built-in (Messaging)</li>
<li>Davx5 (caldav/cardav) -> built-in (Account)</li>
<li>DroidShows (TV series) -> <a href="https://github.com/corecomic/seriesfinale">SeriesFinale</a></li>
<li>Element (Matrix client) -> <a href="https://github.com/R1tschY/harbour-determinant">Determinant</a></li>
<li>Endoscope (camera stream)</li>
<li>Fedilab (Mastodon client) -> <a href="https://github.com/dysk0/harbour-tooter">Tooter</a></li>
<li>ForkHub (GitHub client) -> <a href="https://github.com/black-sheep-dev/harbour-sailhub">SailHub</a></li>
<li>FOSS Browser -> built-in (<a href="https://github.com/sailfishos/sailfish-browser">Browser</a>)</li>
<li>FreeOTP -> <a href="https://github.com/seiichiro0185/sailotp">SailOTP</a></li>
<li>Glider (hacker news reader) -> <a href="https://gitlab.com/ilpianista/harbour-SailHN">SailHN</a></li>
<li>K-9 Mail -> built-in (Mail)</li>
<li>KDE Connect (KDE sync) -> <a href="https://github.com/R1tschY/harbour-sailfishconnect">SailfishConnect</a></li>
<li>Keepassx (password manager) -> <a href="https://github.com/jobe-m/ownkeepass">ownKeepass</a></li>
<li>Labcoat (GitLab client)</li>
<li>Lemmur (Lemmy client)</li>
<li>MasterPassword (password manager) -> <a href="https://gitlab.com/ilpianista/harbour-MPW">MPW</a></li>
<li>MuPDF (PDF reader) -> built-in (Documents)</li>
<li>Newpipe (YouTube client) -> <a href="https://github.com/direc85/harbour-ytplayer">YTPlayer</a></li>
<li>Nextcloud (Nextcloud files) -> <a href="https://github.com/fredldotme/harbour-owncloud">GhostCloud</a></li>
<li>Notes (Nextcloud notes) -> <a href="https://github.com/scharel/harbour-nextcloudnotes">Nextcloud Notes</a></li>
<li>OCReader (Nextcloud RSS) -> <a href="https://github.com/Huessenbergnetz/Fuoten">Fuoten</a></li>
<li>OsmAnd~ (Maps) -> <a href="https://github.com/rinigus/pure-maps">PureMaps</a></li>
<li>Printing (built-in) -> <a href="https://github.com/attah/harbour-seaprint">SeaPrint</a></li>
<li>QuickDic (dictionary) -> <a href="https://github.com/d0b3rm4n/harbour-sidudict">Sidudict</a></li>
<li>RedMoon (screen color temperature) -> <a href="https://github.com/CODeRUS/harbour-tint-overlay">Tint Overlay</a></li>
<li>RedReader (Reddit client) -> <a href="https://github.com/accumulator/Quickddit">Quickddit</a></li>
<li>Signal -> <a href="https://gitlab.com/whisperfish/whisperfish">Whisperfish</a></li>
<li>Syncthing (files sync) -> there’s <a href="https://github.com/fuchsmich/sailfish-syncthing-bin">the binary</a>, no UI</li>
<li>Transdroid (Trasmission client) -> <a href="https://github.com/equeim/tremotesf2">Tremotes</a></li>
<li>Vinyl (music player) -> built-in (Mediaplayer)</li>
<li>VLC (NFS streaming) -> <a href="https://github.com/llelectronics/videoPlayer">videoPlayer</a></li>
<li>WireGuard (VPN) -> there’s <a href="https://github.com/antranigv/wireguard-sailfish">the binary</a>, no UI</li>
<li>YetAnotherCallBlocker (call blocker) -> <a href="https://github.com/omnight/phonehook">Phonehook</a></li>
</ul>
<p>So, to me it looks like almost everything is there, except:</p>
<ul>
<li>a <a href="https://gemini.circumlunar.space/">gemini</a> protocol browser</li>
<li>a client for <a href="https://gitlab.com">GitLab</a></li>
<li>a client for <a href="https://dev.lemmy.ml">Lemmy</a></li>
<li>a UI for <a href="https://syncthing.net">Syncthing</a></li>
<li>a UI for <a href="https://www.wireguard.com/">Wireguard</a></li>
</ul>
<p>I’ve already started to write a UI for <a href="https://gitlab.com/ilpianista/harbour-syncthing">Syncthing</a>, then maybe I could write the browser for the gemini protocol or rather the GitLab client?</p>
<p>Please consider a donation if you would like to support me (mention your favourite project!).</p>
<p><a href="https://liberapay.com/ilpianista/donate"><img src="https://liberapay.com/assets/widgets/donate.svg" alt="Liberapay" /></a></p>
<p>Many many thanks to Jörg who sent me his Sony Xperia 10 Plus! I hope I don’t disappoint him!</p>
tag:scarpino.dev,2021-05-24:/posts/sharing-your-loan-details-to-anyone.htmlSharing your loan details to anyone2021-05-24T00:00:00Z2021-05-24T00:00:00Z<p>A week ago, I blogged about <a href="/posts/sharing-your-amortisation-schedule-to-anyone.html">a vulnerability</a> in a platform that would allow anyone to download users’ amortisation schedules. This was a critical issue, but it wasn’t really exploitable in the wild as it included a part where you had to guess the name of the document to download.</p>
<p>I no longer trust that platform so I went to their website to remove my loan data from it, but apparently this isn’t possibile via the UI.</p>
<p>I also opened a ticket on their support platform to request removal and they replied that it isn’t possible.</p>
<p>So I went to their website with the intention of replacing the data with a fake one… but there was no longer an edit button!</p>
<p><a href="/images/loans.png"><img src="/images/loans_thumb.png" alt="Loans" /></a></p>
<p>I’m sure it was there before and in fact the code also confirms that it was there:</p>
<p><a href="/images/loans_code.png"><img src="/images/loans_code_thumb.png" alt="Loans code" /></a></p>
<p>However, the platform is based on Magento and so, starting from the current URL, we can easily guess the edit URL, e.g. <code>https://<host>/anagraficamutui/mutuo/edit/id/<n></code>.</p>
<p>Let’s try 1… bingo!</p>
<p>But wait a minute… this isn’t my loan! Luckily it’s just a demo entry put in by some developer:</p>
<p><a href="/images/someone_else_loan.png"><img src="/images/someone_else_loan_thumb.png" alt="Someone else loan" /></a></p>
<p>Even though it’s a dummy page, we can already see the details of the loan such as the (hopefully) fake IBAN, or the loan total and loan number and even the bank contact person name and email address.</p>
<p>And now take a look at this: if I try to access that page in private mode, then I get the login page. All (almost) well, right?</p>
<p>Nope. Let’s try the same request via <code>curl</code>:</p>
<pre><code>$ curl -s https://<host>/anagraficamutui/edit/id/1 | grep banca
<input type="text" name="istituto_credito" id="istituto_credito" value="banca acme" title="Nome istituto" class="input-text istituto_credito required-entry" />
$ curl -s https://<host>/anagraficamutui/edit/id/1 | grep NL75
<input type="text" name="iban" id="iban" value="NL75xxxxxxxxx" title="Iban" class="input-text iban required-entry validate-iban validate-length maximum-length-27 validate-alphanum" />
</code></pre>
<p>Wait a minute, what’s going on?</p>
<p>Well, it turns out that the page sets the <code>location</code> header to redirect you to the login page when there’s no cookie, otherwise it prints the HTML page!</p>
<pre><code>$ curl -s https://<host>/anagraficamutui/edit/id/1 -I | grep location
location: https://<host>/customer/account/login/
</code></pre>
<p>Oh-no!</p>
<h2 id="conclusion">Conclusion</h2>
<p>Data from 5723 loans could have been exposed by accessing a specific URL. Details such as IBAN, loan number, loan total and the bank account contact person could have been used to perform spear phishing attacks.</p>
<p>I reported this privacy flaw to the <a href="https://csirt.gov.it/">CSIRT Italia</a> and the platform’s DPO. The issue has been solved after 2 days, but I still haven’t heard from them.</p>
tag:scarpino.dev,2021-05-19:/posts/sharing-your-amortisation-schedule-to-anyone.htmlSharing your amortisation schedule to anyone2021-05-19T00:00:00Z2021-05-19T00:00:00Z<p>Last month, my company allowed me to claim some benefits through a dedicated platform. This platform is specifically built for this purpose and allows you to recover these benefits not only in the form of coupons or discount codes, but also as reimbursements for medical visits or interest on mortgage payments.</p>
<p>I wanted to try the latter.</p>
<p>I logged on to the platform and then I filled in all the (many) details about the loan that the plaform asks you to fill in, until I had to upload my amortisation schedule which contains <strong>a lot</strong> of sensitive data. In fact, a strange thing happened at this step: my file was named <code>document.pdf</code>, but after uploading it was renamed to <code>document_2.pdf</code>.</p>
<p>How do I know? Well, let’s have a look to the UI:</p>
<p><a href="/images/loan_details.png"><img src="/images/loan_details_thumb.png" alt="Loan details" /></a></p>
<p><a href="/images/loan_details_hover.png"><img src="/images/loan_details_hover_thumb.png" alt="Loan details hover" /></a></p>
<p>It clearly shows the file name and that’s also a hyperlink. Let’s click then.</p>
<p>The PDF opens in my browser. This is expected, but what happens if we take the URL and try to open it in a private window?? Guess what?</p>
<p>You guessed it.</p>
<p>Let’s have a look to the URL again. It’s in the form: <code>https://<host>/media/mutuo/file/d/o/document_2.pdf</code>.</p>
<p>That’s tempting, isn’t?</p>
<p>I wanted to have some fun and I tried the following:</p>
<p><a href="/images/loan_curl.png"><img src="/images/loan_curl_thumb.png" alt="Loan download" /></a></p>
<p>Both the <code>curl</code> output and the checksums are enough to understand that some document has been downloaded there (but discarded since I didn’t download them to my disk…).</p>
<p>Thus, since the <code>d</code> and <code>o</code> parent folders match the two initial letters of my file, I successfully tried with stuff like:</p>
<ul>
<li><code>/c/o/contratto.pdf</code>, <code>/c/o/contratto_2.pdf</code>, …</li>
<li><code>/c/o/contract.pdf</code>, …</li>
<li><code>/p/r/prospetto.pdf</code>, …</li>
</ul>
<p>and it does also work with numbers too (to find this out I had to upload a file named <code>1.pdf</code> 😇), e.g. <code>https://<host>/media/mutuo/file/1/_/1_10.pdf</code>.</p>
<h2 id="conclusion">Conclusion</h2>
<p>If you have uploaded your amortisation schedule to this platform, that in its website says it has more than 300k users from 3k different companies, well someone may have downloaded it.</p>
<p>I reported this privacy flaw to the <a href="https://csirt.gov.it/">CSIRT Italia</a> via a PGP encrypted email; the CSIRT is supposed to write to the company that owns the platform to alert them to the problem, but a week later I still hadn’t heard from either of them. So after a week I pinged the CSIRT again, and they replied with a plain text email telling me that they had opened an internal ticket and were nice enough to embed my initial PGP encrypted email.</p>
<p>Two weeks later (about 21 days since my first mail) the platform fixed the problem (the uploaded file path isn’t deterministic anymore and authentication is in place), but I still haven’t heard from them.</p>
<h2 id="addendum">Addendum</h2>
<p>Since <code><host></code> is a third-level domain in my case, I used stuff like <a href="https://github.com/aboul3la/Sublist3r"><code>Sublist3r</code></a> and <a href="https://github.com/OWASP/Amass"><code>Amass</code></a>, but you can also use the online version hosted on <a href="https://www.nmmapper.com/sys/tools/subdomainfinder/">nmmapper.com</a>, to perform DNS enumeration and I found ~50 websites, 30 of which are aliases pointing to the same host. In fact, I could replace <code><host></code> with each of them and I would always download my <code>document_2.pdf</code> file.</p>
tag:scarpino.dev,2020-02-07:/posts/sway-and-the-dock-station.htmlSway and the Dock station2020-02-07T00:00:00Z2020-02-07T00:00:00Z<p>I just moved permanently from <a href="https://awesomewm.org/">awesome</a> to <a href="https://swaywm.org/">Sway</a> because I can barely see any difference. Really.</p>
<p>The whole Wayland ecosystem has improved a LOT since last time I used it. That was last year, as I give Wayland a try once a year since 2016.</p>
<p>However, I had to ditch an useful daemon, <a href="https://libthinkpad.github.io/projects/dockd/">dockd</a>. It does automatically disable my laptop screen when I put it in the dock station, but it does relies over xrandr.</p>
<p>What to use then?</p>
<p>ACPI events.</p>
<p>The <a href="https://sourceforge.net/projects/acpid2/">acpid</a> daemon can be configured to listen to ACPI events and to trigger your custom script. You just have to define which events are you interested in (it does accept wildcards also) and which script acpid should trigger when such events occurs.</p>
<p>I used <code>acpi_listen</code> to catch the events which gets triggered by the physical dock/undock actions:</p>
<pre><code># acpi_listen
ibm/hotkey LEN0068:00 00000080 00004010
[...]
ibm/hotkey LEN0068:00 00000080 00004011
[...]
</code></pre>
<p>Then, I setup an <code>acpid</code> listener by creating the file <code>/etc/acpi/events/dock</code> with the following content:</p>
<pre><code>event=ibm/hotkey
action=/etc/acpi/actions/dock.sh %e
</code></pre>
<p>This listener will call my script only when an event of type <code>ibm/hotkey</code> occurs, then it tells <code>sway</code> to disable or enable the laptop screen based on the action code. Here’s my <code>dock.sh</code> script:</p>
<pre><code>#!/bin/sh
pid=$(pgrep '^sway$')
if [ -z $pid ]; then
logger "sway isn't running. Nothing to do"
exit
fi
user=$(ps -o uname= -p $pid)
case "$4" in
00004010)
runuser -l $user -c 'SWAYSOCK=/run/user/$(id -u)/sway-ipc.$(id -u).$(pidof sway).sock swaymsg "output LVDS-1 disable"'
logger "Disabled LVDS-1"
;;
00004011)
runuser -l $user -c 'SWAYSOCK=/run/user/$(id -u)/sway-ipc.$(id -u).$(pidof sway).sock swaymsg "output LVDS-1 enable"'
logger "Enabled LVDS-1"
;;
esac
</code></pre>
<p>Don’t forget to make it executable!</p>
<pre><code>chmod +x /etc/acpi/actions/dock.sh
</code></pre>
<p>And then start the <code>acpid</code> daemon:</p>
<pre><code>systemctl enable --now acpid
</code></pre>
<p>Happy docking!</p>
tag:scarpino.dev,2019-05-05:/posts/external-encrypted-disk-on-libreelec.htmlExternal encrypted disk on LibreELEC2019-05-05T00:00:00Z2019-05-05T00:00:00Z<p>Last year I replaced, on the Raspberry Pi, the <a href="https://archlinuxarm.org/">ArchLinux ARM</a>
with just Kodi installed with <a href="https://libreelec.tv/">LibreELEC</a>.</p>
<p>Today I plugged an external disk encrypted with dm-crypt, but to my full
surprise this <a href="https://forum.libreelec.tv/thread/285-dm-crypt-and-luks/">isn’t supported</a>.</p>
<p>Luckily the project is open source and <a href="https://github.com/sky42src">sky42</a>
already provides a <a href="https://forum.libreelec.tv/thread/13252-le-9-0-x-with-dm-crypt-and-ext4-encryption/">LibreELEC version with dm-crypt</a>
built-in support.</p>
<p>Once I flashed sky42’s version, I setup automated mount at startup via the <a href="https://wiki.libreelec.tv/autostart.sh">autostart.sh</a>
script and the corresponding umount via <a href="https://wiki.libreelec.tv/autostart.sh#shutdownsh">shutdown.sh</a>
this way:</p>
<pre><code>// copy your keyfile into /storage via SSH
$ cat /storage/.config/autostart.sh
cryptsetup luksOpen /dev/sda1 disk1 --key-file /storage/keyfile
mount /dev/mapper/disk1 /media
$ cat /storage/.config/shutdown.sh
umount /media
cryptsetup luksClose disk1
</code></pre>
<p>Reboot it and voilà!</p>
<h2 id="automount">Automount</h2>
<p>If you want to automatically mount the disk whenever you plug it, then create
the following udev rule:</p>
<pre><code>// Find out ID_VENDOR_ID and ID_MODEL_ID for your drive by using `udevadm info`
$ cat /storage/.config/udev.rules.d/99-automount.rules
ACTION=="add", SUBSYSTEM=="usb", SUBSYSTEM=="block", ENV{ID_VENDOR_ID}=="0000", ENV{ID_MODEL_ID}=="9999", RUN+="cryptsetup luksOpen $env{DEVNAME} disk1 --key-file /storage/keyfile", RUN+="mount /dev/mapper/disk1 /media"
</code></pre>
tag:scarpino.dev,2019-05-04:/posts/automated-phone-backup-with-syncthing.htmlAutomated phone backup with Syncthing2019-05-04T00:00:00Z2019-05-04T00:00:00Z<p>How do you backup your phones? Do you?</p>
<p>I use to perform a copy of all the photos and videos from my and my wife’s
phone to my PC monthly and then I copy them to an external HDD attached to a
Raspberry Pi.</p>
<p>However, it’s a tedious job mainly because:</p>
<ul>
<li>I cannot really use the phones during this process;</li>
<li>MTP works one in 3 times - often I have to fallback to ADB;</li>
<li>I have to unmount the SD cards to speed up the copy;</li>
<li>after I copy the files, I have to <a href="https://rsync.samba.org/">rsync</a>
everything to the external HDD.</li>
</ul>
<h2 id="the-syncthing-way">The Syncthing way</h2>
<p><a href="https://syncthing.net/">Syncthing</a> describes itself as:</p>
<blockquote>
<p>Syncthing replaces proprietary sync and cloud services with something open,
trustworthy and decentralized.</p>
</blockquote>
<p>I installed <a href="https://f-droid.org/en/packages/com.nutomic.syncthingandroid">it</a>
to our Android phones and on the Raspberry Pi. On the Raspberry Pi I also
<a href="https://docs.syncthing.net/users/faq.html#how-do-i-access-the-web-gui-from-another-computer">enabled remote access</a>.</p>
<p>I started the Syncthing application on the Android phones and I’ve chosen the
folders (you can also select the whole Internal memory) to backup. Then, I
shared them with the Raspberry Pi only and I set the folder type to “<a href="https://docs.syncthing.net/users/foldertypes.html#send-only-folder">Send Only</a>”
because I don’t want the Android phone to retrieve any file from the Raspberry
Pi.</p>
<p>On the Raspberry Pi, I accepted the sharing request from the Android phones,
but I also changed the folder type to “<a href="[https://docs.syncthing.net/users/foldertypes.html#receive-only-folder">Receive Only</a>”
because I don’t want the Raspberry Pi to send any file to the Android phones.</p>
<p>All done? Not yet.</p>
<p>Syncthing main purpose is to sync, not to backup. This means that, by default,
if I delete a photo from my phone, that photo is gone from the Raspberry Pi too
and this isn’t what I do need nor what I do want.</p>
<p>However, Syncthing supports <a href="https://docs.syncthing.net/users/versioning.html#file-versioning">File Versioning</a>
and best yet it does support a <a href="https://docs.syncthing.net/users/versioning.html#trash-can-file-versioning">“trash can”-like file versioning</a>
which moves your deleted files into a <strong>.stversions</strong> subfolder, but if this
isn’t enough yet you can also <a href="https://docs.syncthing.net/users/versioning.html#external-file-versioning">write your own</a> file versioning script.</p>
<p>All done? Yes! Whenever I do connect to my own WiFi my photos are backed up!</p>
tag:scarpino.dev,2017-05-11:/posts/how-my-car-insurance-exposed-my-position.htmlHow my car insurance exposed my position2017-05-11T00:00:00Z2017-05-11T00:00:00Z<p>As many car insurances companies do, my car insurance company provides a
satellite device that can be put inside your car to provide its location at any
time in any place.</p>
<p>By installing such device in your car, the car insurance profiles your conduct,
of course, but it could also help the police in finding your car if it gets
stolen and you will probably get a nice discount over the insurance price (even
up to 40%!). Long story short: I got one.</p>
<p>Often such companies also provide an “App” for smartphones to easily track your
car when you are away or to monitor your partner…mine (the company!) does.</p>
<p>Then I downloaded my company’s application for Android, but unluckily it needs
the Google Play Services to run. I am a FLOSS evangelist and, as such, I try to
use FLOSS apps only and without gapps.</p>
<p>Luckily I’m also a developer and, as such, I try to develop the applications I
need most; using <a href="https://mitmproxy.org/">mitmproxy</a>, I started to analyze the
APIs used by the App to write my own client.</p>
<h2 id="authentication">Authentication</h2>
<p>As soon as the App starts you need to authenticate yourself to enable the
buttons that allow you to track your car. Fair enough.</p>
<p>The authentication form first asks for your taxpayer’s code; I put mine and
under the hood it performs the following request:</p>
<pre><code>curl -X POST -d 'BLUCS§<taxpayers_code>§-1' http://<domain>/BICServices/BICService.svc/restpostcheckpicf<company>
</code></pre>
<p>The Web service replies with a cell phone number (WTF?):</p>
<pre><code>2§<international_calling_code>§<cell_phone_number>§-1
</code></pre>
<p>Wait. What do we already see here? Yes, besides the ugliest formatting ever and
the fact the request uses plain HTTP, it takes only 3 arguments to get a cell
phone number? And guess what? The first one and the latter are two constants.
In fact, if we put an inexistent taxpayer’s code, by keeping the same values,
we get:</p>
<pre><code>-1§<international_calling_code>§§-100%
</code></pre>
<p>…otherwise <strong>we get a cell phone number for the given taxpayer’s code</strong>!</p>
<p>I hit my head and I continued the authentication flow.</p>
<p>After that, the App asks me to confirm the cell phone number it got is still
valid, but it also wants the password I got via mail when subscribing the car
insurance; OK let’s proceed:</p>
<pre><code>curl -X POST -d 'BLUCS§<taxpayers_code>§<device_imei>§<android_id>§<device_brand>-<device_model>_unknown-<api_platform>-<os_version>-<device_code>§<cell_phone_number>§2§<password>§§-1' http://<domain>/BICServices/BICService.svc/restpostsmartphoneactivation<company>
</code></pre>
<p>The Web service responds with:</p>
<pre><code>0§<some_code>§<my_full_name>
</code></pre>
<p>The <em>some_code</em> parameter changes everytime, so it seems to work as a
“registration id”, but after this step the App unlocked the button to track my
car.</p>
<p>I was already astonished at this point: how the authentication will work? Does
it need this <em>some_code</em> in combination with my password at reach request? Or
maybe it will ask for my taxpayer code?</p>
<h2 id="car-tracking">Car tracking</h2>
<p>I start implementing the car tracking feature, which allows to retrieve the
last 20 positions of your car, so let’s analyze the request made by the App:</p>
<pre><code>curl -X POST -d 'ASS_NEW§<car_license>§2§-1' http://<domain>/BICServices/BICService.svc/restpostlastnpositions<company>
</code></pre>
<p>The Web service responds with:</p>
<pre><code>0§20§<another_code>§DD/MM/YYYY HH:mm:SS#<latitude>#<longitude>#0#1#1#1-<country>-<state>-<city>-<street>§DD/MM/YYYY HH:mm:SS#<latitude>#<longitude>#0#1#1#1-<country>-<state>-<city>-<street>§DD/MM/YYYY HH:mm:SS#<latitude>#<longitude>#0#1#1#1-<country>-<state>-<city>-<street>§DD/MM/YYYY HH:mm:SS#<latitude>#<longitude>#0#1#1#1-<country>-<state>-<city>-<street>§DD/MM/YYYY HH:mm:SS#<latitude>#<longitude>#0#1#1#1-<country>-<state>-<city>-<street>§DD/MM/YYYY HH:mm:SS#<latitude>#<longitude>#0#1#1#1-<country>-<state>-<city>-<street>§DD/MM/YYYY HH:mm:SS#<latitude>#<longitude>#0#1#1#1-<country>-<state>-<city>-<street>§DD/MM/YYYY HH:mm:SS#<latitude>#<longitude>#0#1#1#1-<country>-<state>-<city>-<street>§DD/MM/YYYY HH:mm:SS#<latitude>#<longitude>#0#1#1#1-<country>-<state>-<city>-<street>§DD/MM/YYYY HH:mm:SS#<latitude>#<longitude>#0#1#1#1-<country>-<state>-<city>-<street>§DD/MM/YYYY HH:mm:SS#<latitude>#<longitude>#0#1#1#1-<country>-<state>-<city>-<street>§DD/MM/YYYY HH:mm:SS#<latitude>#<longitude>#0#1#1#1-<country>-<state>-<city>-<street>§DD/MM/YYYY HH:mm:SS#<latitude>#<longitude>#0#1#1#1-<country>-<state>-<city>-<street>§DD/MM/YYYY HH:mm:SS#<latitude>#<longitude>#0#1#1#1-<country>-<state>-<city>-<street>§DD/MM/YYYY HH:mm:SS#<latitude>#<longitude>#0#1#1#1-<country>-<state>-<city>-<street>§DD/MM/YYYY HH:mm:SS#<latitude>#<longitude>#0#1#1#1-<country>-<state>-<city>-<street>§DD/MM/YYYY HH:mm:SS#<latitude>#<longitude>#0#1#1#1-<country>-<state>-<city>-<street>§DD/MM/YYYY HH:mm:SS#<latitude>#<longitude>#0#1#1#1-<country>-<state>-<city>-<street>§DD/MM/YYYY HH:mm:SS#<latitude>#<longitude>#0#1#1#1-<country>-<state>-<city>-<street>§DD/MM/YYYY HH:mm:SS#<latitude>#<longitude>#0#1#1#1-<country>-<state>-<city>-<street>
</code></pre>
<p>WTH?!? No header?!? No cookie?!? No authentication parameters?!?</p>
<p>Yes, your assumption is right: <strong>you just need a car license and you get its
last 20 positions</strong>. And what’s that <em>another_code</em>? I just write it down for
the moment.</p>
<p>It couldn’t be real, I first thought (hoped) they stored my IP somewhere so I’m
authorized to get this data now, so let’s try from a VPN…oh damn, it
worked.</p>
<p>Then I tried with an inexistent car license and I got:</p>
<pre><code>-2§TARGA NON ASSOCIATA%
</code></pre>
<p>which means: “that car license is not in our database”.</p>
<p>So what <strong>we could</strong> get here with the help of <a href="https://sourceforge.net/projects/crunch-wordlist/">crunch</a>?
Easy enough: <strong>a list of car licenses that are covered by this company</strong> and
<strong>last 20 positions for each one</strong>.</p>
<p>I couldn’t stop now.</p>
<h2 id="the-web-client">The Web client</h2>
<p>This car insurance company also provides a Web client which permits more
operations, so I logged into to analyze its requests and while it’s hosted on a
different domain, and it also uses a cookie for almost any request, it performs
one single request to the domain I previously used. Which isn’t authenticated
and got my attention:</p>
<pre><code>curl http://<domain>/<company>/(S(<uuid>))/NewRemoteAuthentication.aspx?RUOLO=CL&ID=<another_code>&TARGA=<car_license>&CONTRATTO=<foo>&VOUCHER=<bar>
</code></pre>
<p>This one replies with an HTML page that is shown in the Web client:</p>
<pre><code><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
<HEAD>
<title>NewRemoteAuthentication</title>
<meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1" />
<meta name="CODE_LANGUAGE" Content="C#" />
<meta name="vs_defaultClientScript" content="JavaScript"/>
<meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie7" />
<!--<meta content="IE=EmulateIE10" name="ie_compatibility" http-equiv="X-UA-Compatible" />-->
<meta name="ie_compatibility" http-equiv="X-UA-Compatible" content="IE=7, IE=8, IE=EmulateIE9, IE=10, IE=11" />
</HEAD>
<body>
<form name="Form1" method="post" action="/<company>/(S(<uuid>))/NewRemoteAuthentication.aspx?RUOLO=CL&amp;ID=<another_code>&amp;TARGA=<car_license>" id="Form1">
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwULLTIwNzEwODIsJFNAgEPKAJDIeBsdSpc2libGVnZGRic5McHC9+DqRx0H+jRt5O+/PLtw==" />
<iframe id="frm1" src="NewRicerca.aspx" width="100%" height="100%"></iframe>
<SCRIPT language="JavaScript">
<!--
self.close
// -->
</SCRIPT>
</form>
</body>
</HTML>
</code></pre>
<p>It includes an iframe (sigh!), but that’s the interesting part!!! Look:</p>
<p><a href="/images/car_history.png"><img src="/images/car_history_thumb.png" alt="Car history" /></a></p>
<p>From that page you get:</p>
<ul>
<li>the full name of the person that has subscribed the insurance;</li>
<li>the car model and brand;</li>
<li>the total amount of kilometers made by the car;</li>
<li>the total amount of travels (meant as “car is moving”) made by the car;</li>
<li>access to months travels details (how many travels);</li>
<li>access to day travels details (latitude, longitude, date and time);</li>
<li>access to months statistics (how often you use your car).</li>
</ul>
<p><a href="/images/car_month_history.png"><img src="/images/car_month_history_thumb.png" alt="Car month history" /></a>
<a href="/images/car_day_history.png"><img src="/images/car_day_history_thumb.png" alt="Car day history" /></a>
<a href="/images/car_month_statistics.png"><img src="/images/car_month_statistics_thumb.png" alt="Car month_statistics" /></a></p>
<p>There are a lot of informations here and these statistics are available
<strong>since the installation of the satellite device</strong>.</p>
<p>The request isn’t authenticated so I just have to understand the parameters to
fill in. Often not all parameters are required and then I tried by removing
someone to find out which are really needed. It turns out that I can simplify
that as:</p>
<pre><code>curl http://<domain>/<company>/(S(<uuid>))/NewRemoteAuthentication.aspx?RUOLO=CL&ID=<another_code>&TARGA=<car_license>
</code></pre>
<p>But there’s still a <em>another_code</em> there…mmm, wait it looks like the
number I took down previously! And yes, it’s!</p>
<p>So, <code>http://<domain>/<company>/(S(<uuid>))/NewRicerca.aspx</code> is the page that
really shows all the informations, but how do I generate that uuid thing?</p>
<p>I tried by removing it first and then I got an empty page. Sure, makes sense,
how that page will ever know which data I’m looking for?</p>
<p>Then it must be the <em>NewRemoteAuthentication.aspx</em> page that does something; I
tried again by removing the uuid from that url and to my full surprise it
redirected me to the same url, but it also filled the uuid part as path
parameter! Now I can finally invoke the <em>NewRicerca.aspx</em> using that uuid and
read all the data!</p>
<h2 id="conclusion">Conclusion</h2>
<p>You just need a car license which is covered by this company to get <strong>all the
travels made by that car, the full name of the person owning it and its
position in real time.</strong></p>
<p>I reported this privacy flaw to the <a href="https://www.certnazionale.it/">CERT Nazionale</a>
which wrote to the company.</p>
<p>The company fixed the leak 3 weeks later by providing new Web services
endpoints that use authenticated calls. The company mailed its users saying
them to update their App as soon as possible. The old Web services have been
shutdown after 1 month and half since my first contact with the CERT Nazionale.</p>
<p>I could be wrong, but I suspect the privacy flaw has been around for 3 years
because the first Android version of the App uses the same APIs.</p>
<p>I got no bounty.</p>
<p>The company is a leading provider of telematics solutions.</p>
tag:scarpino.dev,2016-09-25:/posts/arch-audit.htmlarch-audit2016-09-25T00:00:00Z2016-09-25T00:00:00Z<p>I started a tiny project a couple of days ago: <a href="https://github.com/ilpianista/arch-audit">arch-audit</a>.</p>
<p>arch-audit main (and unique) goal is to display the Arch Linux packages that are affected by known vulnerabilities on your system.</p>
<p>To do that, arch-audit parses the <a href="https://wiki.archlinux.org/index.php/CVE">CVE page</a> on the Arch wiki, which is maintained by the <a href="https://wiki.archlinux.org/index.php/Arch_CVE_Monitoring_Team">Arch CVE Monitoring Team</a>.</p>
<p>arch-audit output is very verbose when it’s started without any argument, but two options <code>--quiet</code> (or <code>-q</code> or <code>-qq</code>) and <code>--format</code> (or <code>-f</code>) allows to change the output for your use case.
There’s also a third option <code>--upgradable</code> to display only packages that have already been fixed in the Arch Linux repositories.</p>
<p>In my opinion a great use case is the following:</p>
<pre><code>$ ssh www.andreascarpino.it
openssl>=1.0.2.i-1
lib32-openssl>=1:1.0.2.i-1
Last login: Sat Sep 24 23:13:56 2016
$
</code></pre>
<p>In fact, I added a <a href="https://github.com/ilpianista/arch-audit/tree/master/systemd">systemd timer</a> that executes <code>arch-audit -uq</code> everyday and saves its output to a temporary file that is configured as banner for SSH.
Then, every time I log into my server, I get notified about packages that have vulnerabilities, but that already have been fixed. Time to do a system update!</p>
<p>So, now I’m waiting your feedbacks!
Have fun!</p>
<p>BTW, <a href="https://cisofy.com/lynis/">Lynis</a> already <a href="https://github.com/CISOfy/lynis/commit/db419495bf8daa3bc996aeb3992e0b2ae65649a4">added arch-audit support</a>!</p>
tag:scarpino.dev,2016-06-17:/posts/choqok-1-6-beta-1.htmlChoqok 1.6 Beta 12016-06-17T00:00:00Z2016-06-17T00:00:00Z<p>I’m happy to announce that we will release <a href="http://choqok.gnufolks.org/">Choqok</a> 1.6 next month! (mid July)</p>
<p>This will be the first release after <a href="/posts/choqok-and-kde-frameworks.html">the KDE frameworks port</a> and many things have been fixed in those 16 months, including:</p>
<ul>
<li>Twitter: fix user lists loading (<a href="https://bugs.kde.org/show_bug.cgi?id=345641">BUG:345641</a>)</li>
<li>Twitter: allow to select any follower when sending a direct message</li>
<li>Twitter: fix searches by username</li>
<li>Twitter: fix searches by hashtag</li>
<li>Twitter: show original retweet time (<a href="https://bugs.kde.org/show_bug.cgi?id=343438">BUG:343438</a>)</li>
<li>Twitter: fix external URL to access direct messages and tweets</li>
<li>Twitter: send direct message without text limits</li>
<li>Twitter: support to send and view tweets with quoted text</li>
<li>Twitter: allow to delete direct messages</li>
<li>Twitter: always show ‘Mark as read’ button</li>
<li>GNU Social: fix medium attachment to post</li>
<li>GNU Social: allow to send direct messages</li>
<li>Pump.IO: do not show resend button for own posts</li>
<li>Pump.IO: display avatar image in own posts on the right</li>
<li>Pump.IO: do not create a post if there’s no text</li>
<li>Fix removal of accounts with spaces in their name</li>
<li>Add scalable versions of Choqok icon</li>
<li>Check the result of external URL opening to report any failure (<a href="https://bugs.kde.org/show_bug.cgi?id=347525">BUG:347525</a>)</li>
<li>Fixed a bug that overwrite an account with the same alias if you use the same alias</li>
<li>Do not allow to send quick posts with no text</li>
<li>Always use HTTPS when available</li>
<li>ImageView: dropped Twitpic and Tweetphoto support (service are dead)</li>
<li>A couple of segmentation fault fixed</li>
</ul>
<p>Oh, we also added official support for <a href="http://friendica.com/">Friendica</a>!</p>
<p>But there’s still a lot to do!</p>
<p>Please join the <a href="https://community.kde.org/Get_Involved/translation">KDE translation team</a> and help us with translations or try <a href="http://download.kde.org/unstable/choqok/1.5.80/src/choqok-1.5.80.tar.xz">this 1.6 beta</a> and <a href="https://bugs.kde.org">report any bug</a> or, still, join the development team and fix <a href="https://bugs.kde.org/buglist.cgi?bug_status=UNCONFIRMED&bug_status=CONFIRMED&bug_status=ASSIGNED&bug_status=REOPENED&list_id=1364389&product=choqok&query_format=advanced">the open bugs</a>.</p>
<p>Together we can make the next release a new starting point for Choqok!</p>
tag:scarpino.dev,2015-10-06:/posts/from-ghost-to-nanoc.htmlFrom Ghost To Nanoc2015-10-06T00:00:00Z2015-10-06T00:00:00Z<p>I completed my blog migration from <a href="https://ghost.org">Ghost</a> to <a href="http://nanoc.ws">nanoc</a>.</p>
<p>About <a href="/posts/my-blog-again.html">2 years ago</a> I did setup a blog on blog.as.it using Ghost. It’s UI was very minimal and I liked the default theme (Casper) a lot.</p>
<p>However, I kept nanoc for my main website, until I decided to give <a href="http://jaspervdj.be/hakyll/">Hakyll</a> a try. It’s not that nanoc didn’t satisfy me at that time, but that I was fascinated by Haskell - I’m still fascinated by Haskell, but I’ve no much time to play with it, while I play with Ruby more often.</p>
<p>Someday ago I thought it was time to merge my website and my blog; both could be handled by a static site generator and since I’m fluent in Ruby more then Haskell, I went for nanoc again.</p>
<p>The migration has not been hard because one of the main features of Ghost is that you write your post using Markdown, then I wrote <a href="https://gitlab.com/snippets/11208">this shell script</a> to migrate my posts from Ghost to a “nanoc compatible format” like:</p>
<pre><code>---
kind: article
created_at: 2015-10-06
title: My Ghost Post
tags: ['example']
---
This is a post in **Ghost**!
</code></pre>
<p>With that script my posts were split and ready in the content folder to be built by nanoc. Nothing more to do! Well, in truth I had to fix the path to the linked images manually…</p>
<p>The second step was to put some redirect to allow the old links around the web to continue to work, specifically the Ghost pattern was <em>http://blog.as.it/my-ghost-post/</em> while in nanoc I went for <em>/posts/my-ghost-post.html</em>. I fixed this in my blog nginx configuration:</p>
<pre><code>location = / {
rewrite ^ $scheme://www.andreascarpino.it permanent;
}
location / {
rewrite ^(.*) $scheme://www.andreascarpino.it/posts$request_uri permanent;
}
location = /rss/ {
rewrite ^ $scheme://www.andreascarpino.it/feed.xml permanent;
}
</code></pre>
<p>While in the website nginx configuration I put:</p>
<pre><code>location /posts/ {
root /srv/http/website;
if ($request_filename ~* ^.+.html$) {
break;
}
if ($request_uri ~* ^.+/$) {
rewrite ^/(.*)/$ /$1.html permanent;
}
}
</code></pre>
<p>And that’s!</p>
<p>Hope this helps someone that plans to do the same migration.
If you are interested at looking at my nanoc setup, the configuration is <a href="https://gitlab.com/ilpianista/ilpianista.gitlab.io">here</a>.</p>
tag:scarpino.dev,2015-09-12:/posts/kde-telepathy-thinklight-plugin.htmlKDE Telepathy ThinkLight Plugin2015-09-12T00:00:00Z2015-09-12T00:00:00Z<p>Do you own a ThinkPad? Good!
Does it have the <a href="https://en.wikipedia.org/wiki/IBM_ThinkPad_ThinkLight">ThinkLight</a>? Good! Then this post might interest you!</p>
<p>I just wrote a <a href="https://userbase.kde.org/Telepathy">KDE Telepathy</a> plugin that blinks the ThinkLight when you get an incoming message.
Sounds almost useless, isn’t? Maybe not.</p>
<p>I found a good use case for it: sometime you could be away from keyboard, but near your ThinkPad (e.g. studying), the screen goes black, sounds are off, but you see the ThinkLight blinking - you got a message!</p>
<p>To enable it you just have to fetch the <a href="http://quickgit.kde.org/?p=scratch%2Fscarpino%2Fktp-thinklight.git">source code</a>, build and install as usual with CMake.</p>
<p>There’s just an annoyance at the moment: you need write permission over <code>/proc/acpi/ibm/light</code>. I’m looking for a solution for this, but found nothing if not changing that file permissions manually. Any idea?</p>
<p>There’s also a tool, <a href="http://www.mike.tl/other/ThinkAlert.html">thinkalert</a> (<a href="https://github.com/floriandejonckheere/thinkalert">mirror</a>), which allows to turn on/off the ThinkLight without being <em>root</em> by using <em>suid</em>. If you prefer this way, you can fetch the code from the <em>thinkalert</em> branch instead.</p>
<p>Have fun!</p>
tag:scarpino.dev,2015-06-06:/posts/cleaning-an-arch-linux-installation.htmlCleaning an Arch Linux installation2015-06-06T00:00:00Z2015-06-06T00:00:00Z<p>We are in springtime and usually in <a href="https://en.wikipedia.org/wiki/Spring_cleaning">springtime you make some cleaning</a>.
Today I decided to clean my old desktop that is running the same Arch Linux installation since 2007.</p>
<p><strong>Warning</strong>: this whole task requires a bit of knowledge about what a package does and why it is installed on your system. You could break something, but IMHO in the worst case you will re-install it later ;-)</p>
<p>So, I started by listing any package I didn’t install:</p>
<ul>
<li><code>$ pacman -Sqg base base-devel | sort -u > /tmp/essentials</code></li>
<li><code>$ pacman -Qqe | sort > /tmp/explicit</code></li>
<li><code>$ comm -13 /tmp/essentials /tmp/explicit > /tmp/unknown</code></li>
</ul>
<p>Read <em>/tmp/unknown</em> and mark as “installed as dependence” any package you didn’t install or simply you don’t know. This last step requires a knowledge of what a package do; <code>pacman -Qi</code> and <code>pacman -Ql</code> are your friend here!
To mark a package as dependence run: <code># pacman -D --asdeps <pkg></code>.</p>
<p>Now, the harmful part! Run <code># pacman -Rscn $(pacman -Qqtd)</code>. It will remove any package installed as dependence plus the packages needed by it because installed as dependence that are no more required without it. <strong>Do not rush</strong> and read the packages you are going to remove!</p>
<p>In my case, even after all those years I only got 14 packages…I’m too careful. I always mark as dependence the package I don’t use anymore and I periodically check the output of <code>pacman -Qqtd</code>.</p>
<p>Now, you could also remove the orphaned files on your system by using <code>lostfiles</code> (<a href="https://aur.archlinux.org/packages/lostfiles/">download from AUR</a>). In fact, <code># lostfiles relaxed > /tmp/lostfiles</code> will produce a list of files that are owned by no package, but it also excludes something from that list which makes things easier for your brain.</p>
<p><strong>Update</strong>: an user suggested to also check the output of <code>pacman -Qqttd</code> (note the extra ‘<em>t</em>’); this one also lists optional dependencies. Thanks!</p>
<p>Happy cleaning!</p>
tag:scarpino.dev,2015-04-08:/posts/choqok-and-kde-frameworks.htmlChoqok and KDE Frameworks2015-04-08T00:00:00Z2015-04-08T00:00:00Z<p>Hi there,</p>
<p>Good news for the <a href="http://choqok.gnufolks.org/">Choqok</a> users out there: we are <a href="https://mail.kde.org/pipermail/choqok-devel/2015-April/000392.html">now</a> using <a href="https://www.kde.org/announcements/kde-frameworks-5.0.php">KDE Frameworks</a> technology!</p>
<p>In fact, I spent the last month porting Choqok bits from Qt 4 to Qt 5, but I also fixed minor bugs you discover when doing this kind of work. Regressions could happen, so please <a href="https://bugs.kde.org">report them</a> and we’ll fix them!</p>
<p>To try this version you just need to install qca-qt5 and qoauth-qt5, build our code from git and you have done. Check the <a href="http://quickgit.kde.org/?p=choqok.git&a=blob&f=README&o=plain">README</a> for more info about the steps on how to build it.</p>
<p>…and from now on I’ll focus on fixing bugs \o/</p>
<p>I’m also interested in improving <a href="http://pump.io">Pump.io</a> and <a href="https://gnu.io/social/">GNU Social</a> support because I’m a supporter and advocate of the <a href="https://www.gnu.org/philosophy/free-sw.html">Free Software</a>, but I also believe in the <a href="http://freeyourdata.org/">FreeYourData</a> movement and decentralized social networks are the way to go.</p>
<p>Before someone ask, I’m also a <a href="https://joindiaspora.com/">Diaspora*</a> supporter, but Choqok cannot support it until they <a href="https://github.com/diaspora/diaspora/issues/3467">get some API</a>.</p>
<p><a href="/images/choqok_kf5_thumb.ong"><img src="/images/choqok_kf5_thumb.png" alt="Choqok using KDE Frameworks" /></a></p>
tag:scarpino.dev,2015-01-10:/posts/firefox-kde-wallet-for-kf5.htmlFirefox KDE Wallet for KF52015-01-10T00:00:00Z2015-01-10T00:00:00Z<p>Hi there,</p>
<p>I have a good news for Firefox and Plasma 5 users: I ported <a href="https://addons.mozilla.org/en-US/firefox/addon/kde-wallet-password-integratio/">KDE Wallet password integration</a> extension to KDE Frameworks 5!</p>
<p>It seems to me that this plugin is unmaintained because both the released version and the <a href="http://svn.guillermomolina.com.ar/firefox-kde-wallet-2/">SVN one</a> do not support Firefox 33 or newer. So, as first step I took Guillermo’s code and bumped the Firefox version.</p>
<p>After that I did work on the KF5 version: I updated the CMakeLists file, replaced some <code>kDebug()</code> usage and fixed the QString initializations. The plugin built at first shot!</p>
<p>And then the first issue.</p>
<p>There’s a C test file which failed to find the exported symbols from the C++ library, therefore the extension would not work in Firefox. Turns out <code>Q_DECL_EXPORT</code> macro was needed. I guess with Qt 5 you need to explicitly define which symbols to export?</p>
<p>Rebuilt, the plugin runs and… segfaults.
After some debugging it turns out <code>KWallet::openWallet()</code> invokes KWindowSystem that <a href="https://projects.kde.org/projects/frameworks/kwindowsystem/repository/revisions/master/entry/src/kwindowsystem.cpp#L48">needs a QCoreApplication instance</a> otherwise it segfaults.</p>
<p>Fixed that one, I rebuilt the plugin and… it works!</p>
<p>The code is <a href="http://quickgit.kde.org/?p=scratch%2Fscarpino%2Ffirefox-kde5-wallet.git">here</a>, and <a href="https://share.kde.org/index.php/s/UCO0s7RASvgJpZG">here</a> you can download an XPI for x86_64. Try it!</p>
<p>In the meantime, I’m going to clean it a bit.</p>
tag:scarpino.dev,2014-08-20:/posts/how-i-lost-my-blog-content.htmlHow I lost my blog content2014-08-20T00:00:00Z2014-08-20T00:00:00Z<p>…and, luckily, how I restored it!</p>
<p>Let me say this before you start reading: <strong>backup your data NOW!!!</strong></p>
<p>Really, do it. I post-poned this for so long and, as result, I had a drammatic weekend.</p>
<p>Last Friday I had the wonderful idea to update my Ghost setup to <a href="http://blog.ghost.org/ghost-0-5/">the newer 0.5</a>. I did this from my summer house via SSH, but the network isn’t the culprit here.</p>
<p>You have to know that some months ago, maybe more, I switched from a package installation, through <a href="https://aur.archlinux.org/packages/ghost">this PKGBUILD</a>, to an installation via <code>npm</code>. So, as soon as I typed <code>npm update</code>, all my <code>node_modules/ghost</code> content was gone. Yep, I must be dumb.</p>
<p>After some minute, which helped me to better understand how the situation was, I immediately shutdown the BeagleBone Black.</p>
<p>The day after I went home, I installed Arch Linux ARM on a microSD and obviously the super <a href="http://www.cgsecurity.org/index.html?testdisk.html">TestDisk</a> which got SQLite support since a while now. Cool!</p>
<p>This way I restored the Ghost database, BUT it was corrupted. However, <a href="http://stackoverflow.com/questions/5274202/sqlite3-database-or-disk-is-full-the-database-disk-image-is-malformed">a StackOverflow search</a> pointed me to this commad:</p>
<p><code>
cat <( sqlite3 ghost.db .dump | grep "^ROLLBACK" -v ) <( echo "COMMIT;" ) | sqlite3 ghost-fixed.db
</code></p>
<p>After that, I was able to open the database and to restore 14 of 40 posts.</p>
<p>My second attempt has been to use the Google cache. Using this method I recovered about 10 posts. Nice, I already had more than 50% of the total content! I was feeling optimistic.</p>
<p>The <a href="https://planet.archlinux.org">Arch Linux Planet</a> let me recover 3 posts more, which however I could recover anyway using <a href="http://bd.summit.net">Bartle Doo</a>; I never heard of this website before, but thanks to it I recovered some posts by looking for my First and Last Name.</p>
<p>I was almost here. About 10 posts missing, but how to recover them?? I didn’t remember titles and googling without specific keywords didn’t help neither.</p>
<p>I went back on the broken SQLite database, Vim can open it so let’s look into for some data. Bingo! The missing posts titles are still there!</p>
<p>And then I started googling again, but for specific titles, which pointed me to websites mirroring my posts content.
At the end of this step I had 38 of 40 posts!</p>
<p>I can’t stop now, it’s more than a challenge now.</p>
<p>I went back again on the broken database where posts content is corrupted: there’s some text, then symbols and then another text which doesn’t make any sense in union with the first part. This looks like a tedious job. This Saturday can end here.</p>
<p>It’s Sunday; I’m motivated and I can’t lose those 2 posts because of my laziness.
I’ve the missing posts titles and I now remember their content, so I started to look for their phrases in the database and, with all my surprise and a lot of patience, I recovered their content!
This mainly because Ghost keeps both the markdown and the HTML text in the database and then the post content is duplicated which decrease the chance of a corruption in the same phrase.</p>
<p>Another summer, another <a href="/posts/linux-survival.html">Linux survival</a> experience (that I’m pleased to link to!).</p>
tag:scarpino.dev,2014-06-24:/posts/bringing-back-my-data.htmlBringing back my data2014-06-24T00:00:00Z2014-06-24T00:00:00Z<p>The past days have been very “FLOSS” for me.</p>
<p>Let’s start from the beginning: Tuesday I managed (= it means I found money) to became a <a href="https://fsfe.org/fellowship/">supporter of the FSFE</a>! This is something that I had in mind since <a href="/posts/linux-day-2013-bari.html">the last Linux Day</a> (I’m sorry, that post is in Italian!) because I meet <a href="https://wiki.fsfe.org/groups/Bari">the FSFE Bari</a> guys there and we had a nice chat.</p>
<p>I already knew the <a href="https://fsfe.org/campaigns/android/android.en.html">FreeYourAndroid</a> campaign, but on Thursday I stumbled upon <a href="http://www.roussos.cc/2014/05/08/free-your-android/">Nikon Roussos’ post</a> and he really motivated me to start replacing closed app with FLOSS app on my phone.</p>
<p>Thanks to <a href="https://f-droid.org/">F-Droid</a>, after some hour I realized there’s a <strong>good</strong> FLOSS alternative for almost every application I use. Notably, I switched from <a href="https://play.google.com/store/apps/details?id=com.mapfactor.navigator">Navigator</a> to <a href="https://f-droid.org/repository/browse/?fdfilter=osmand&fdid=net.osmand.plus">OsmAnd~</a>, from Google Keep to <a href="https://f-droid.org/repository/browse/?fdfilter=tasks&fdid=de.azapps.mirakelandroid">Mirakel</a>, from Google Translator to <a href="https://f-droid.org/repository/browse/?fdfilter=quickdic&fdid=com.hughes.android.dictionary">QuickDic</a>, from Google Hangout (SMS) to <a href="https://play.google.com/store/apps/details?id=org.thoughtcrime.securesms">TextSecure</a>, from Twitter to <a href="https://f-droid.org/repository/browse/?fdfilter=twidere&fdid=org.mariotaku.twidere">Twidere</a>.</p>
<p>Luckily I was already using <a href="https://f-droid.org/repository/browse/?fdfilter=apollo&fdid=com.andrew.apollo">Apollo</a>, <a href="https://f-droid.org/repository/browse/?fdfilter=Connectbot&fdid=org.connectbot">ConnectBot</a>, <a href="https://f-droid.org/repository/browse/?fdfilter=document%20viewer&fdid=org.sufficientlysecure.viewer">Document Viewer</a>, <a href="https://f-droid.org/repository/browse/?fdfilter=keepass&fdid=com.android.keepass">KeePassDroid</a>, <a href="https://f-droid.org/repository/browse/?fdfilter=barcode&fdid=com.google.zxing.client.android">Barcode Scanner</a>, <a href="https://f-droid.org/repository/browse/?fdfilter=diode&fdid=in.shick.diode">Diode</a>, <a href="https://f-droid.org/repository/browse/?fdfilter=episodes&fdid=org.jamienicol.episodes">Episodes</a>…</p>
<p>The list was not so short as I thought initially and this scared me because there were too many Google apps. Yes, that’s because it has the best services out there, but this means it had my location, my SMSs, my todos, my translations, my mails, my contacts, my events,… even my website stats! - I bet Google knows me better than I do.</p>
<p>On Monday, next step was to move away from Google Analytics. I did a quick search and found <a href="http://piwik.org/">Piwik</a>. The setup was simple and faster and it even allows (through a third-party script) to import your data from Google Analytics.</p>
<p><a href="/images/piwik.png"><img src="/images/piwik_thumb.png" alt="Piwik Analytics" /></a></p>
<p>Tuesday. It was time to remove the Dropbox client and switch to <a href="http://owncloud.org/">ownCloud</a>. I never really used Dropbox to store my private files, I just did install the client because others co-workers did and we needed a quick way to work on a folder at the same time. Luckily I don’t have to share a folder with co-workers anymore, and even if I had I would use the website instead - Yep, downloading and uploading the file every time.</p>
<p>I used this day to remove that package from my system and setup an ownCloud server that I’m using for remote backups. Now I can put my private files on the cloud because I trust the service this time :-)</p>
<p>Only GMail and Google+ left and then I free-ed my Android.</p>
<p>Google+ is harder. I don’t want to quit Google+ because of the FLOSS development around it. It’s a great place where to look for FLOSS news, look for people reactions and even people issues. It’s a real pity <a href="http://pump.io/">Pump.IO</a> or even <a href="https://joindiaspora.com/">Diaspora</a> aren’t at the same level. However, I always publish my staff as ‘Public’ audience, so Google doesn’t really own anything.</p>
<p>On the contrary, GMail is a bit easier because I already use my aliases everywhere so I just need to open a <a href="https://mykolab.com/">Kolab account</a> and update my forwarding rules. However <a href="http://blogs.fsfe.org/gerloff/2014/05/13/were-all-gmail-users-now/">we’re all Gmail users now</a>.</p>
<p>Let me say that I don’t want to quit every closed service and use my own instance (it would be cool, but you know it isn’t realistic), instead I guess we should look for a FLOSS alternative first and in the case there’s none we could split our data between many companies…and start making the FLOSS implementation!</p>
<p>Oh I almost forgot, keep an eye upon the <a href="https://tox.im/">Tox Project</a>! It’s the free alternative to Skype/Hangout.</p>
<p><strong>FLOSS <3</strong></p>
tag:scarpino.dev,2014-05-17:/posts/kf5-official-packages-for-arch.htmlKF5 Official Packages for Arch2014-05-17T00:00:00Z2014-05-17T00:00:00Z<p>Hi everybody,</p>
<p>This morning I uploaded last <a href="https://www.archlinux.org/groups/x86_64/kf5/">KDE Framework 5 packages</a> to the [extra] repository in Arch Linux.</p>
<p>Since Beta 2, KF5 packages are co-installable with KDE 4 and for this reason those packages are built with the <em>/usr</em> prefix, not <em>/opt/kf5</em> as previously on AUR.</p>
<p>The only exception here was <em>kactivities</em>: both versions (the KDE 4 version and the KDE Framework one) ship a <em>kactivitymanagerd</em> binary.</p>
<p>Thanks to <a href="http://ivan.fomentgroup.org/home/">Ivan Čukić</a> tip both <em>kactivities</em> packages have been split between binary and libraries. In fact, Ivan told me <strong>KDE 4 needs kactivities 4.x</strong> libraries, but it works with <em>kactivitymanagerd</em> ship by <em>kactivities</em> from KDE Frameworks.</p>
<p>For this reason <em>kactivities4</em> and <em>kactivities-framework</em> Arch Linux packages provide a <em>kactivities</em> virtual package which allows KDE 4 users to install KDE Framework 5 on the same system under <em>/usr</em>.</p>
<p>The packages are part of two groups to simplify installation: <a href="https://www.archlinux.org/groups/x86_64/kf5/">kf5</a> and <a href="https://www.archlinux.org/groups/x86_64/kf5-aids/">kf5-aids</a> (PortingAids).</p>
<p><em>Plasma Next</em> packages will (hopefully!) follow in the next days, but they will go in [kde-unstable] instead. Also, their prefix will be <em>/opt/kf5</em> so they are co-installable.</p>
<p>Happy <code>pacman -S kf5 kf5-aids</code> and enjoy KDE Frameworks libraries!</p>
<p><strong>PS:</strong> <em>KWin 5</em> is already in [kde-unstable]!</p>
<p><strong>UPDATE:</strong> I’ve been asked several times now, so here are the instructions on how to run Plasma Next components, e.g. <em>KWin 5</em>:</p>
<p><code>
# pacman -S kwin oxygen
$ export KF5=/opt/kf5
$ export QML2_IMPORT_PATH=$KF5/lib/qt/qml:/usr/lib/qt/qml
$ export QT_PLUGIN_PATH=$KF5/lib/qt/plugins:/usr/lib/qt/plugins
$ export XDG_CONFIG_DIRS=$KF5/etc/xdg:/etc/xdg
$ export PATH=$KF5/bin:$PATH
$ kwin --replace
</code></p>
tag:scarpino.dev,2014-05-02:/posts/disabling-baloo-the-arch-way.htmlDisabling Baloo, the Arch way2014-05-02T00:00:00Z2014-05-02T00:00:00Z<p><strong>DISCLAIMER</strong>: I don’t think this is the right way to fix broken stuff: every time something doesn’t work as expected users should file a bug report and ask developers to fix it.</p>
<p>Since its introduction <a href="http://community.kde.org/index.php?title=Baloo">Baloo</a> has been accused to <a href="https://bbs.archlinux.org/viewtopic.php?id=180313">sucking</a> <a href="https://bbs.archlinux.org/viewtopic.php?id=180916">system</a> <a href="https://bbs.archlinux.org/viewtopic.php?id=180456">resources</a>.</p>
<p>I don’t want to write about it’s problems - <strong>if there’s any</strong> - because the Web is already full of posts about this. Instead, since I’ve been ask several times about how to disable it, I’ll propose “the Arch way” to disable it.</p>
<p>While the libraries are an hard dependency because they are used by KMail, Dolphin and Gwenview, the executables are not. In particular <em>baloo_file</em> and <em>baloo_file_extractor</em> could be removed from your system.</p>
<p>I read OpenSuSE already provides two baloo packages to allow this and in fact I’ve been ask to <a href="https://bugs.archlinux.org/task/40161">split our baloo package</a> too. But I’ll not do that.</p>
<p>Also, in that bug report Pierre Schmitz provides a valid point why you shouldn’t do that:</p>
<blockquote>
<p>How would this work on a multi user system where some users want a file index and some don’t?</p>
</blockquote>
<p>However, if you still don’t want to help in fixing issues Baloo causes on your system and if you still don’t care about a multi-user system, on Arch Linux you can disable baloo by putting this line in your <code>/etc/pacman.conf</code>:</p>
<p><code>NoExtract = usr/bin/baloo_file usr/bin/baloo_file_extractor</code></p>
<p><strong>Note</strong>: you should re-install the baloo package after that or manually remove those files.</p>