mardi 17 janvier 2017

De la notion de harcèlement

Une partie du web français est sans-dessus-dessous suite à la publication du SMS non-désiré d’un technicien à domicile envoyé à une femme chez qui il était intervenu.

Je ne vais pas revenir sur les hectolitres d’insultes en tout genre qui ont fusé (des deux côtés, reconnaissons le en toute objectivité). Juste en me remettant à ma place d’homme cis hétéro, quelques remarques m’ont un peu parlées :

  • elle n’aurait pas dû le publier, un seul SMS, c’est mignon et ça ne mange pas de pain (en plus le type avait l’air vraiment réservé / gêné)
  • elle ne devrait pas en parler comme étant du harcèlement. C’était juste un SMS.

Vu comme ça la réaction de la femme en question semble un tant soit peu disproportionnée. Allez quoi, il nous est tous arrivé d’imaginer sortir avec une femme croisée par hasard (dans le métro, au guichet de la poste, à la caisse du supermarché…) et autres pensées impures.

Sauf que.

Sauf que là c’est différent. Et ça le sera toujours. Je ne peux pas me permettre de juger cette femme sur cet acte, n’ayant ni son vécu, ni n’ayant été présent ce jour là ou n’étant pas directement parti prenante de l’affaire. Par contre je peux entendre. Et ce que j’entends est extrêmement important : on parle ici d’un homme qui a abusé de son emploi pour pénétrer l’intimité d’une femme sans son consentement. Oui les mots sont choisis exprès.

Notre numéro de téléphone personnel ou notre adresse physique fait partie intégrante de notre intimité. Seul un groupe restreint de personnes ou d’institutions connaissent le lien qui nous associe en tant qu’individu à tel numéro ou telle adresse. Cette intimité est importante, nul ne pourra le nier. Si tout le monde et n’importe qui commençait à débarquer chez nous à n’importe quelle heure du jour et de la nuit, juste comme ça, en passant… Ça ne serait pas une vie. Tout le monde a besoin d’intimité. De son petit jardin secret qu’on maîtrise.

Il est évident que beaucoup plus de monde que ce qu’on imagine consciemment connaît en fait notre numéro ou notre adresse. À commencer par nos voisins, avec qui l’on n’a pas forcément de relations, avec des amis d’amis étant venus un jour. Avec le vétérinaire du chat, l’huissier de justice de tel jeu concours, etc.

Mais il y a pourtant une règle implicite, normale et importante qui nous pousse tous autant que l’on est à respecter l’intimité de l’autre.

Jamais quand je sais qu’un collègue est au toilette je vais jusque derrière la porte pour continuer à lui parler du dossier chaud du jour. Jamais quand j’héberge chez moi quelqu’un pour la nuit je retourne dans la pièce au milieu de la nuit sans toquer au préalable (oui, même si c’est chez moi). Jamais je n’irai forcer un ami à partager une cabine douche avec moi à la piscine, pour gagner du temps ou que sais-je encore.

Pourtant je pourrais le faire. J’en ai les capacité.

Pour les mêmes raisons, il m’a toujours semblé normal que, même si je pouvais obtenir le numéro de quelqu’un par quelque biais que ce soit, je n’allais pas l’utiliser avant qu’il ne m’en ait explicitement donné l’autorisation. Attention, j’exclue de ce fonctionnement (et c’est bien normal) tous les moyens de communications qui seraient publiquement disponibles. Si l’on publie explicitement ses coordonnées quelques part, ou qu’on les sait accessible mais que l’on ne fait rien pour les masquer (annuaire, etc.), mon propos ne s’applique plus. Je parle réellement des coordonnées privées.

Si quelqu’un s’amuse à montrer qu’il est en capacité de me contacter, alors qu’il n’y est pas autorisé explicitement, c’est directement comparable, à mon sens, à un chien fou qui viendrait ruiner votre grillage, pisserait sur vos fleur et japperait en direction de vos fenêtres en remuant la queue. Que ce soit mignon ou pas, c’est une intrusion. Si en plus cette intrusion a eu lieu en utilisant le matériel d’une société dans laquelle j’avais mis de la confiance (confiance de ne pas être dérangé, entre autre), et donc du vol industriel, on atteint des sommets de gravité.

Publier une telle fraude est donc salutaire et permet d’affirmer que oui, nous avons tous le droit à une vie privée et à contrôler qui peu y aller et venir. Lorsque j’ai envie d’inconnu, de surprise, de rencontre… je sors dans un lieu public. Je vais au cinéma, dans un bar, ou j’invite des amis chez moi. Je contrôle ce qui m’arrive. Ou plus exactement j’ai l’impression de contrôler, ce qui me permettra d’apprécier les surprises.

En d’autres termes, le vol c’est mal, s’imposer dans la vie de quelqu’un d’autre c’est mal.

Ok, c’était une connerie. Mais maintenant le mec était conscient hein ! Il a même mis désolé dans son seul et unique SMS. On ne peut pas appeler ça du harcèlement. Ça fait du mal à c·ell·eux qui sont réellement harcelé·e·s.

C’est vrai qu’un seul SMS, ça fait pas lourd. En tout cas de mon point de vue de mec cis. Quoique.

Je ne sais pas vous, mais ça me rappelle cette histoire récente. Traînant pas mal sur les interouebs depuis pas mal de temps, j’ai laissé deux ou trois adresses mails là où il ne fallait pas et je reçois pas mal de Spam. Au cours de l’an dernier, il y a eu un changement de la législation sur les bâtiments amené à recevoir du public. Ne me demandez pas quoi, objectivement je n’en sais rien. Ce que je sais par contre c’est que pour une raison inconnue, pendant deux semaines j’ai reçu jusqu’à vingt messages par jours (j’ai compté) de divers organismes plus ou moins crapuleux pour me vendre des formations, des prestations d’architectes, de maçons, de mise aux normes etc. pour mon entreprise. Spoiler: je n’ai jamais eu la moindre entreprise. Du spam massif et mal orienté quoi. Sauf que j’ai fini par craquer. Sans faire de distinction, j’en ai chopé un un jour et fait une déclaration CNIL d’utilisation frauduleuse de mes données. J’ai appris après coup que je venais de déclarer un artisan maçon qui essayait de vivre comme il le pouvait dans cette ère du digital (la faute exprès).

Est-ce que j’ai mal réagis ? Est-ce que je n’aurai pas dû le déclarer à la CNIL ? Il y avait manifestement, dans toute cette histoire, une utilisation frauduleuse d’un fichier contenant mes données perso. Mais pourquoi lui ? Il ne m’avait envoyé qu’un mail. Et il croyait bien faire sans doute : il voulait sans doute vraiment protéger mon entreprise.

Ça ne vous est jamais arrivé d’engueuler l’un de vos enfants alors qu’ils étaient tous objectivement coupable du bordel ambiant ? Ça ne vous est jamais arrivé d’en vouloir à un con qui vous fait un refus de priorité alors que vous avez échappé à douze autres abrutis sur le périph’ la dernière demi-heure ?

Le harcèlement ça n’a pas besoin de venir d’une seule et même personne bien identifiée. La plupart du temps, ça vient même plutôt d’un groupe. Harcèlement scolaire ? On ne compte plus le nombre de jeunes qui sont détruit à petit-feu à force de servir de bouc émissaire au reste de la classe. Harcèlement pro ? Votre chef à bien d’autres chat à fouetter que de vous en vouloir à vous particulièrement. Par contre les rumeurs entretenus l’air de rien par les autres collègues, ça l’aide à vous penser coupable.

Harcèlement de rue ? Tu ne peux pas sortir de chez toi l’été venu sous peine de voir des types que tu ne connaît ni d’Eve ni d’Adam te courir après, te solliciter alors que tu veux juste prendre l’air. Te faire siffler, alpaguer…

Je ne connaît pas cette femme. Mais soyons honnête : le fait que les hommes soient massivement, toujours, en train de les solliciter dans la rue est suffisant pour comprendre son coup de sang lorsque l’un de nous s’est imposé à elle jusque dans sa sphère privée.

Lui ne l’a contacté qu’une fois, mais c’était la fois de trop pour elle. Son message s’est additionné à la trop longue liste des comportements déplacés, chiants, gênant, effrayant qu’elle ait eu à subir. Il a bien participé à un acte de harcèlement.

En conclusion, n’oublions jamais que si une situation nous turlupine, qu’on aimerait faire quelque chose mais qu’on a peur de gêner la personne, c’est qu’il y a des chances que ce soit le cas. Et dans ce cas mieux vaut attendre une meilleure occasion. Et voler les données de son entreprise pour arriver à ses fins ne sera jamais une bonne occasion.

Par ailleurs, nous sommes tous coupable à des degrés divers, de harcèlement. Ça peut aller de proposer un restaurant grill à un groupe de potes comportant des végétariens, porter un adorable t-shirt « les bébé, je les aime bien avec du ketchup » dans le même bureau qu’une jeune maman qui vient de perdre son enfant, etc. Et surtout tout simplement en transportant des rumeurs. Être sociable ne veut pas dire aller emmerder les autres sans autorisation. Ça veut dire prêter attention aux gens et vérifier que nos actes ne peuvent pas les gêner. Donc au lieu de toujours chercher des boucs émissaires et des coupables, faisons preuve d’un peu d’introspection.

lundi 19 décembre 2016

Fonction shell pour récupérer la dernière version du navigateur Tor

This article is only available in french. It begins with a quick reminder of what the Tor project and the Tor browser are. This introduction is followed by a shell function I wrote to check if a new version of the Tor browser is available, and download it if needed.

Tor est un dispositif numérique permettant d’anonymiser sa navigation internet. Son principe de fonctionnement, reposant sur un réseau décentralisé de serveurs au sein duquel les requêtes vont transiter, garantit à de nombreuses personnes (lanceurs d’alerte, journalistes, activistes) la possibilité de consulter des sites interdits dans leurs pays ou une plus libre expression sans craindre la répression d’États autoritaires.

Son utilisation sur sa machine de tous les jours peut cependant s’avérer un rien complexe car il faut veiller à ne pas se trahir soit même en laissant transiter sur le réseau des informations permettant de nous identifiant en parallèle de notre utilisation de Tor. C’est pour cela que le projet Tor met à disposition depuis quelques temps déjà un produit tout packagé : le Tor Browser.

Ce dernier est construit autour de la version offrant un support à long terme de Firefox (Firefox ESR). L’utilisation de cette base très stable n’empêche pas le Tor Browser de se mettre à jour fréquemment, afin de corriger les problèmes ou failles de sécurité pouvant compromettre l’anonymat de ses utilisateurs.

Comme souvent en informatique, il devient vite intéressant d’automatiser les tâches répétitives. En l’occurrence : se rendre sur le site du Tor Browser, vérifier la dernière version disponible, comparer avec la version que l’on possède déjà et au besoin la télécharger à nouveau. C’est long et fastidieux. J’ai donc commis la fonction shell ci-après, à placer dans votre .bashrc ou .zshrc ou que sais-je, afin de simplement avoir à taper un dl_latest_tor_browser avant de l’utiliser la conscience tranquille.

dl_latest_tor_browser() {
    OLD_PWD=$(pwd)
    LAST_VER=$(\curl -s 'https://www.torproject.org/projects/torbrowser.html.en' | sed -n "s|^.*\.\./dist/torbrowser/\([0-9]\.[0-9]\.[0-9]\)/tor-browser-linux64-\([0-9]\.[0-9]\.[0-9]\)_fr\.tar\.xz\".*$|\1|p")
    if [ ! -n "$LAST_VER" ]; then
        LAST_VER=$(\curl -s 'https://www.torproject.org/projects/torbrowser.html.en' | sed -n "s|^.*\.\./dist/torbrowser/\([0-9]\.[0-9]\)/tor-browser-linux64-\([0-9]\.[0-9]\)_fr\.tar\.xz\".*$|\1|p")
    fi
    cd "$HOME/Téléchargements"
    if [ -d 'tor-browser_fr' ]; then
        CUR_VER=$(sed -n 1p tor-browser_fr/Browser/TorBrowser/Docs/ChangeLog.txt | sed -n "s/^Tor Browser \(.*\) -- .*$/\1/p")
        if [ "$LAST_VER" = "$CUR_VER" ]; then
            echo "You already have the last stable release: $LAST_VER"
            echo ''
            echo "Start it with: ${HOME}/Téléchargements/tor-browser_fr/Browser/start-tor-browser --detach"
            cd "$OLD_PWD"
            return
        fi
        rm -rf tor-browser_fr
    fi
    TOR_BUNDLE="tor-browser-linux64-${LAST_VER}_fr.tar.xz"
    [ -f "$TOR_BUNDLE" ] && rm "$TOR_BUNDLE"
    [ -f "$TOR_BUNDLE.asc" ] && rm "$TOR_BUNDLE.asc"
    wget "https://dist.torproject.org/torbrowser/${LAST_VER}/${TOR_BUNDLE}"
    wget "https://dist.torproject.org/torbrowser/${LAST_VER}/${TOR_BUNDLE}.asc"
    gpg --verify ${TOR_BUNDLE}{.asc,}
    tar xJf ${TOR_BUNDLE}
    rm "$TOR_BUNDLE" "$TOR_BUNDLE.asc"
    echo ''
    echo "The TOR browser v${LAST_VER} is here: ${HOME}/Téléchargements/tor-browser_fr"
    echo ''
    echo "Start it with: ${HOME}/Téléchargements/tor-browser_fr/Browser/start-tor-browser --detach"
    cd "$OLD_PWD"
}

Comme vous pouvez le constater, cette fonction effectue les tâches suivantes :

  1. récupérer le numéro de la dernière version stable
  2. comparer avec le numéro de la dernière version téléchargée et laissée dans le dossier $HOME/Téléchargements/tor-browser_fr
  3. si nécessaire télécharger la nouvelle version
  4. si une nouvelle version a été téléchargée, vérifier la signature numérique du paquet et l’extraire si tout va bien en lieu et place de l’ancienne version si elle existait

La vérification de la signature numérique implique que vous ayez déjà ajouté à votre trousseau de clefs publiques gpg celle utilisée par le projet Tor pour signer ses paquets :

gpg --keyserver pool.sks-keyservers.net --recv-keys 0x4E2C6E8793298290

Attention cependant, je n’ai pas (en tout cas pas dans cette version) mis en place de barrières strictes autour de cette vérification de signature. Si elle échoue, rien ne vous empêchera d’utiliser tout de même le Tor Browser téléchargé. Je vous encourage donc vivement à bien observer les messages affichés à l’écran au cours de l’utilisation de cette fonction.

mardi 29 novembre 2016

Recompile ruby on archlinux after libreadline 7 upgrade

Although it was not specifically announced on the official archlinux website, the recent update of libreadline (package readline) from version 6 to 7 could lead to several problem. One of them was the concomitance of its release with the availability of a new kernel. Upgrading both of them in the same pacman transaction produces a broken kernel image if you use lvm. Bugs reported problems with cinnamon desktop – which I don’t use – and nearer me, the readline upgrade broke my different rubies, installed through rvm.

The problem was in fact the same everywhere: upgrading one of the most used library without recompiling all impacted packages, or at least warned the users is wrong. But here is not the point of this article. In the best cases, readline upgrade should have been smooth for you if you don’t use exotic packages. All impacted packages from core and extra had been recompiled.

But if you are used to compile yourself some of your day to day tools, this upgrade may have bothered you. I refuse to install ruby as a system app, given the fact we can use a tool like rvm to manage several different version in userspace. The bad news is: rvm compiles the rubies you install, and as irb depends on readline, you must recompile them after each readline upgrade – the same thing might be required for python installed through virtualenv. To do so, you just have to execute the following command: rvm reinstall --disable-binary <your ruby version>. In my case for exemple: rvm reinstall --disable-binary ruby-2.1.2.

vendredi 23 septembre 2016

Two custom headers for mu4e

Tl;dr: you can jump to the custom headers part.

In this article I’ll present two usefull (at least for me) headers for mu4e. But before this, I’ll make a quick introduction on how I discovered this cool mail client.

Introduction

The date is 2006, the 18th april. At some point at night. I don’t remember why I wasn’t using my computer but the fact is: I was reading my emails directly on my provider webmail. Back in the time, that was one of the first roundcube version, hosted by Gandi. The first thing I loved – and currently always enjoy – with linux, is the possibility to use simpler, cleaner console software. That’s why I quickly adopt alpine around 2005. But still, that night I was on roundcube. Reading my emails, deleting the non-interesting ones and keeping the others. I browse from my Inbox to the Trash, try to empty it. Doesn’t work. Crap. Click again on Inbox and back again on Trash to reload the folder. Click on Empty folder. That’s the very moment when shit happened. Some ajax request failed at some point and I’d just deleted my entire mail history. Obviously, the younger me was a bit unconscious and didn’t keep any backup. #Yolo.

The day after, I discovered offlineimap (or something similar at that time) and promise myself to never do it again. Since that day, I always keep something like two or three different snapshots of all my inboxes. Of course, they growth with the year until a point where alpine was no more a viable solution. As it do all of its works directly on the imap server, browsing or searching through my ~25000 mails begin to take too long to be acceptable. Thus I look for a replacement and found my happyness in the mu project. Its aim is to provide an indexer for local email collections. But an emacs module is also provided as a side-project: the previously mentioned mu4e (mu for emacs). As I already have a local copy of my emails, thanks to offlineimap, mu was just the right tool to use. It’s blazingly fast, has very nice search tricks, is able to retrieve and manage contacts even if they are not in my addressbook. A pleasure.

But it needs some little improvement to cover all of my needs.

The custom headers

These headers will be visible in the message view.

I begin to wrote a generic function to retrieve any mail header content from a mail stored somewhere in a maildir folder. I should have done something more lispy, but I know a little more sed than lisp and it works well so I stopped there:

(defun ed/get-mail-header (header-name path)
(replace-regexp-in-string
"[ \t\n]*$"
""
(shell-command-to-string
(concat "/usr/bin/sed -n '/^" header-name ":/I{:loop t;h;n;/^ /{H;x;s/\\n//;t loop};x;p}' " path " | sed -n 's/^" header-name ": \\(.*\\)$/\\1/Ip'"))))

To use it, you just have to call it like this, saying your email file is /home/toto/Mail/INBOX/cur/trololo: (ed/get-mail-header "x-spam-level" "/home/toto/Mail/INBOX/cur/trololo").

Mail client of your interlocutor

During a time I used Thunderbird and enjoyed a lot the display user agent addon. I cannot explain why I like it, but I found sometime interesting to know what mail client people where using (like their mobile, gmail etc.). Thus I try to get it on mu4e. After some lisp work, here are the required bits to achieve that:

(defun ed/get-origin-mail-system-header (msg)
(let ((path (or (mu4e-message-field msg :path) "")))
(if (or (string= path "")
(not (file-readable-p path)))
"no path found"
(let ((xmailer (ed/get-mail-header "x-mailer" path))
(useragent (ed/get-mail-header "user-agent" path)))
(if (string= xmailer useragent)
xmailer
(cond
((string= xmailer "") useragent)
((string= useragent "") xmailer)
(t (concat xmailer " (xmailer)\n" useragent " (user-agent)"))))))))

As you can see, all the hard work is done by the previous ed/get-mail-header function.

OpenPGP informations

The openpgp header is mainly added by the enigmail addon of Thunderbird. I like the idea behind it. We often add our PGP Id in our mail signatures, but it may be disturbing for non-technical people. With this header, you can send your id without poluting your signature. It’s even better as you can use it either to just communicate you PGP id or an URL to your public key, allowing your recipients to download it.

We retrieve this header the exact same way as user-agent information:

(defun ed/get-openpgp-header (msg)
(let ((path (or (mu4e-message-field msg :path) "")))
(if (or (string= path "")
(not (file-readable-p path)))
"Mail file is not accessible"
(ed/get-mail-header "openpgp" path))))

Add these headers to the visible headers list

You must customize the mu4e-view-fields like this:

(add-to-list 'mu4e-header-info-custom
'(:useragent . (:name "User-Agent"
:shortname "UserAgt."
:help "Mail client used by correspondant"
:function ed/get-origin-mail-system-header)))
(add-to-list 'mu4e-header-info-custom
'(:openpgp . (:name "PGP Info"
:shortname "PGP"
:help "OpenPGP information found in mail header"
:function ed/get-openpgp-header)))

(setq mu4e-view-fields '(:from :to  :cc :subject :flags :date :maildir
:mailing-list :tags :useragent :attachments
:openpgp :signature :decryption))

You should also customize the mu4e-compose-hidden-headers variable to hide them from the composing buffer:

mu4e-compose-hidden-headers '("^References:" "^Face:" "^X-Face:"
"^Openpgp:" "^X-Draft-From:"
"^X-Mailer:" "^User-agent:")

What does it look like?

From: John Doe <john@doe.fr>
To: Me <you@know>
Subject: Prochaine réunion
Flags: seen, signed, attach
Date: ven. 23 sept. 2016 15:13:55 CEST
Maildir: /Posteo/INBOX
User-Agent: Alpine 2.20 (LNX 67 2015-01-07)
Attachments: [1]signature.asc(836)
PGP Info: id=ABCDEF0123456789[…];
preference=signencrypt
Signature: verified (Details)

Add theses headers in our own emails

Now that we are able to display these information from the emails we got, I think it’s fair to play the game and to be sure we add these headers in the emails we send from mu4e.

The hardest header to add is the openpgp one, as we want to add it only if we’re currently sending a signed email, and of course we want to send the right PGP ID for our current identity. Starting from the new Emacs 25, the later is as simple as setting the mml-secure-openpgp-sign-with-sender variable to t.

First we need a function, which will insert the right PGP ID for your current identity. As I use mu4e new context feature, for me this function look like:

(defun ed/insert-gpg-headers()
(save-excursion
(goto-char (point-min))
(let ((pgp-info
(cond
((string= (mu4e-context-name (mu4e-context-current)) "posteo")
"id=2EBD3E9457B6316DBD100ABCA714ECAC8C9CEE3D;\n url=https://etienne.depar.is/8c9cee3d-public.gpg\n")
((string= (mu4e-context-name (mu4e-context-current)) "umaneti")
"id=72D9729DF611D2BA65552E3D47E5AFEA8FB5F5D3;\n url=https://etienne.depar.is/8fb5f5d3-public.gpg\n")
((string= (mu4e-context-name (mu4e-context-current)) "iRaiser")
"id=F119A4DA3FB7343E590A83DCE9491C429882ECD9\n"))))
(insert (concat "Openpgp: " pgp-info)))))

Then we must declare two functions to be called when we declare that the current draft must be signed or signed-encrypted. Then we will replace the default sign and sign-encrypt key binding in order to use our new functions. This can be done with the following code:

(defun ed/sign-this-message ()
"Insert mml gpg command and gnupg header"
(interactive)
(ed/insert-gpg-headers)
(mml-secure-message-sign))

(defun ed/encrypt-this-message ()
"Insert mml gpg command and gnupg header"
(interactive)
(ed/insert-gpg-headers)
(mml-secure-message-sign-encrypt))

We must now bind these functions to the right key bindings. As we do not want to be dirty, we’ll do that only locally in the current composing buffer.

(add-hook 'mu4e-compose-mode-hook
(lambda ()
(local-set-key (kbd "C-c <return> C-s") 'ed/sign-this-message)
(local-set-key (kbd "C-c <return> C-e") 'ed/encrypt-this-message)))

Finally, the easyer header to add is the mail-agent header. Because we’ll add it to all our emails, without distinction. In fact, Emacs (or mu4e, or smtpmail I cannot say which of them) already attach the user-agent header. To cover all cases, we’ll just add the x-mailer one. The mu4e-compose-mode-hook will now look like:

(add-hook 'mu4e-compose-mode-hook
(lambda ()
(set-fill-column 72)
(local-set-key (kbd "C-c <return> C-s") 'ed/sign-this-message)
(local-set-key (kbd "C-c <return> C-e") 'ed/encrypt-this-message)
(save-excursion
(goto-char (point-min))
(insert (concat "X-Mailer: mu4e " mu4e-mu-version "; emacs " emacs-version "\n")))))

Conclusion

This story moral is: you must think about your mail backups, period! You now know why I hate javascript, ajax and webmail in particular. I always fear something terrible will happen.

Regarding the two discussed custom headers, as I said before, I should have used a more pure lisp approach to fetch the mail headers. If you have anything to share about that, do not hesitate to publish it in the comments.

If you already use Emacs, you should definitely give mu4e a try! It worths it. If you don’t but are a pgp user, please try to let your email client add the openpgp header. It’s really helpfull to quickly found which key we must use to answer you.

Finally, I may have spoken about my mu4e-headers-fields configuration to make the headers view look like my good old alpine. But this article is already too long, thus maybe for another time.

mardi 6 septembre 2016

Nouvelle version (alpha) pour hubic-gtk

Cela va commencer à faire un moment que, sur un coup de tête, j’ai commencé à développer une petite icône de statut pour hubiC, le service de stockage de fichier en ligne d’OVH (cocorico). Tout a commencé le 7 avril 2014. J’étais un poil ambitieux et le premier nom de ce petit script a été hubic_client. Je me suis vite rendu compte que ça ne valait certainement pas la peine de voir trop gros et l’ai simplement renommé moins de huit heures plus tard hubic_status.py ou pour tout le monde « HubicStatus ». Il y a de ça un peu plus d’un an, j’ai fait migrer ce script sur son propre dépôt comme il avait pris un peu d’importance. Son nom définitif : hubic-gtk.py ou « hubicGTK ».

Depuis tout ce temps, il m’a permis de me familiariser un peu plus avec le développement d’application de bureau en python à l’aide de pygtk. Le problème sous-jacent étant qu’il s’agit de relativement vieille technos et que le monde regarde désormais plutôt du côté de python3 et des bindings associés pour gtk3.

J’ai donc pris le temps depuis quelques semaines d’effectuer son portage vers python3. Cette nouvelle version, une fois validée, prendra du même coup le numéro de version symbolique 1.0.

Qu’est-ce que propose HubicGTK ?

HubicGTK se présente sous la forme d’une icône venant se glisser dans le systray de votre environnement de bureau (Mate ou XFCE, je n’ai pu tester au sein d’autres environnements, mais rien n’interdit a priori que ça fonctionne).

hubic-gtk-closed.png

La future nouvelle version apporte un nouveau lot d’icône issue d’un clipart dont j’ai adapté la couleur. Elle est visible dans l’image ci-dessus sous la forme d’un nuage bleu-ovh. Cette icône zen signale qu’actuellement tout se passe comme attendu, aucune activité n’est à déclarer. En cas d’anomalie ou plus simplement si le daemon hubic lui-même n’est pas lancé, l’icône pas au rouge sombre. En cas d’activité, des flèches de synchronisation viennent s’ajouter à l’icône.

Un simple clic sur l’icône va vous ouvrir le dossier racine que vous partagez avec hubiC dans votre explorateur de fichier préféré. Un clic droit vous ouvrira un menu vous permettant d’interagir un petit peu avec hubic.

hubic-gtk-opened.png

Ma configuration personnelle est complète et vous permet d’apercevoir toutes les fonctionnalités présentes :

  • les deux premières lignes vous apportent quelques informations sur l’état de votre compte et de la synchronisation
  • les deux lignes suivantes permettent, soit de mettre en pause la synchronisation (ce qui se passe également automatiquement si hubic-gtk détecte une perte de votre connectivité) ou carrément d’arrêter le daemon mono.
  • Le sous-menu « Derniers messages » liste les derniers messages remontés du backend. Souvent abscons, ils peuvent de temps à autre signaler une activité sur un fichier particulier (par exemple si un fichier est ajouté à votre compte ou supprimé. Un clic sur le message en question vous ouvrira le dossier dans lequel se trouve ce fichier).
  • Je reviendrai un peu plus tard sur le sous-menu « Dossiers cryptés[1] »
  • La case à cocher de lancement automatique vous permet de venir placer une entrée de démarrage automatique dans ~/.config/autostart de manière à ce qu’HubicGTK se lance automatiquement au démarrage de votre session. J’ai pris le partie d’écraser le fichier généré par Hubic lui-même de manière à mieux contrôler son démarrage (de cette manière, Hubic ne se lance plus jamais seul a démarrage de votre session).
  • Les trois dernières lignes se suffisent à elles mêmes.

Qu’en est-il de cette histoire de dossiers chiffrés ?

Il est important de toujours se rappeler qu’en allant déposer des fichiers sur un cloud que vous ne controllez pas, quand bien même il est français et cool, vous laissez à un tiers la possibilité d’y accéder. Rien ne prouve, à moins que vous ne controlliez l’intégralité d’une infrastructure, qu’aucune personne à aucun moment ne puisse accéder à vos données, même si le risque semble faible en apparence.

C’est pour cela que je recommande vivement de chiffrer vos données lorsque vous les placez sur un tel espace. Un état de l’art du domaine m’avait amené à la conclusion qu’en la matière, encFS avait le meilleur ratio sécûrité/souplesse d’utilisation. En effet, LUKS ou autre {true,vera}crypt ont l’inconvénient de fonctionner à l’aide de container : la modification d’un fichier entraîne du même coup la resynchronisation du container entier. Une opération impliquant possiblement des gigaoctets de données. De son côté, encFS ne chiffre que les fichiers et les noms de dossiers, laissant l’arborescence telle qu’elle (ainsi que les métadonnées du type heure de modification, taille, permissions…). Encore une fois, on parle de synchronisation de fichier dans le cloud, c’est donc pour moi une perte acceptable.

Bref, partant du principe que vous êtes intéressez par l’utilisation de tels points de montage encFS, j’ai ajouté la possibilité à HubicGTK de piloter le montage/démontage et la supervision de ces points de montage directement dans l’icône de statut. Je vous laisse lire la doc pour voir comment mettre ça en place chez vous.

Où et comment me le procurer ?

Pour la version stable, je maintiens moi-même un paquet AUR pour archlinux. Pour les autres distributions, j’ai mis en place un makefile qui devrait vous aider à l’installer :

$ last_ver=0.6.2
$ wget "https://projects.depar.is/hubic-gtk/tarball/HubicGTK.tar.gz?uuid=$last_ver" -O hubicgtk.tgz
$ tar xzf hubicgtk.tgz
$ cd HubicGTK/
$ PKGVER=$last_ver make build
$ PKGVER=$last_ver sudo make install DEST=/usr

Concernant la dernière version de développement (celle en gtk3, but de cet article donc), j’ai mis à jour le PKGBUILD dans le dépôt, pour les utilisateurs d’archlinux, un simple makepkg dans le dossier archlinux une fois les sources récupérées devrait suffire. Pour les autres, l’installation avec le makefile fonctionne toujours. Dans les deux cas, le lien de téléchargement est le suivant : https://projects.depar.is/hubic-gtk/tarball/HubicGTK.tar.gz?uuid=v1.0-alpha5.

N’hésitez pas à apporter vos commentaires :)

Notes:

[1] Diantre, honte à moi, je constate qu’emporté par mon élan j’utilise depuis un an cette jargonerie au lieu d’utiliser le fort-à-propos « Dossiers chiffrés ». Cela sera réparé au plus vite.

lundi 30 mai 2016

Comment moins déprimer sur son statut (ou pas) de bon programmeur

Un très bon article2 que je partage. Le passage suivant, en plus de me faire rire, résume tout à fait la difficulté que l’on peut rencontrer lorsqu’un proche —- parce qu’il nous sait travailler dans l’informatique —- nous pose une question sur un domaine que l’on ne maîtrise pas du tout. Il y aura toujours, quelle que soit notre spécialité, une personne plus spécialisé dans un autre domaine.

No matter what programming job you have, there will be a vast amount of programming you do not understand. If you manage to learn every programming language in the universe, some Russian twelve year old will mock you for not knowing how to overclock your CPU. Simultaneously, a Korean kid will hack your PS4 account while an American sucks down a latte and asks you why you haven’t closed a series B. The French ops person just spits at you when you ask her to stop smoking in the server room.

Source : Peter Welch, How to Worry Less About Being a Bad Programmer3

mercredi 6 avril 2016

Petit mémo git

J’ai mis du temps à me faire à git. Non pas que son utilisation soit particulièrement compliquée, mais plutôt parce que, comme chaque système de gestion de version, il a ses propres caractéristiques. Venant du monde bazaar et fossil je me suis un peu emmêlé les pinceaux au début. Voici donc sans prétention ma petite cheatsheet.

Création d’une nouvelle branche avec propagation upstream

  1. On se place sur la branche mère
    $ git checkout master
  2. On crée la nouvelle branche locale et on bascule dessus
    $ git checkout -b nouvelle_branche
  3. On push upstream la nouvelle branche
    $ git push -u origin nouvelle_branche

Suppression de branches

  • Localement
    $ git branch -d la_branche_a_supprimer
  • Reporter upstream la suppression
    $ git push origin :heads/la_branche_a_supprimer

Création d’un « serveur »

C’est à dire héberger une instance de votre dépôt git sur un serveur quelconque (pas sur github, donc ^^) pour servir de dépôt upstream. C’est grandement inspiré de cet article.

Mise en place du dépôt sur votre machine distante :

$ cd /var/www/repositories/
$ mkdir my_project.git
$ cd my_project.git
$ git init --bare

Puis, en local :

$ cd my_project
$ git init
$ git add *
$ git commit -m "My initial commit message"
$ git remote add origin user@monserveur:/var/www/repositories/my_project.git
$ git push -u origin master

Toute la magie tiens dans le fait que user doit avoir les droits d’écriture dans /var/www/repositories/ — ce qui est normalement le cas si vous avez réussi à faire votre git init --bare.

Si vous partagez votre dépôt avec des tiers, ils n’auront qu’à faire, pour le cloner, la ligne suivante : $ git clone user@monserveur:/var/www/repositories/my_project.git

Migration d’un dépôt github en interne

Pour le coup une simple reprise de cet article.

Cette commande vous permettra cloner en bare depuis github, transformant une version « clonée » en version « serveur ». Attention, il faut avoir l’autorisation de cloner (ssh, etc) : $ git clone --bare git@github.com:quidam/my_project.git

Puis, sur votre poste de travail, il suffit de spécifier une nouvelle origine à votre copie de travail : $ git remote set-url origin user@monserveur:/var/www/repositories/my_project.git

Mise en place d’un miroir fossil sur github

Le script suivant doit pouvoir fonctionner avec n’importe quel hébergement git. Il faut simplement veiller à modifier la ligne 15 pour filtrer le résultat de git remote avec le bon fragment.

Tout l’intérêt de ce script, comparé au classique — et documentéfossil export --git ../repo.fossil | git fast-import, vient de l’étape intermédiaire au cours de laquelle je modifie les occurrences de mon identifiant fossil vers une identité reconnue par github (ligne 11). À vous d’ajouter les traitements qui vous paraissent nécessaires à la suite de cette ligne.

lundi 4 avril 2016

Analyse des mails de rapport DMARC

Dans le cadre de la mise en place de DMARC sur un serveur mail donné, les prestataires externes s'appuyant sur la vérification des champs DMARC pour filtrer les emails entrant sont tenus de vous envoyer un email récapitulatif des actions entreprises chaque jour où ils ont reçu des mails du serveur en question à minuit.

J'ai découvert un petit script permettant de vérifier l'état de ces remontées d'information.

Installation

Ce script requiert

Configuration

Utiliser la configuration suivante pour offlineimap (ça va récupérer tous les mails de la boîte observée, mais on s'occupera de fine-tuner ça plus tard).

1:  $ cat ~/.offlineimaprc
2:  [Account MonCompte]
3:  localrepository = Local_MonCompte
4:  remoterepository = MonCompte
5:  
6:  [Repository Local_MonCompte]
7:  type = Maildir
8:  sep = /
9:  localfolders = ~/Mail/MonCompte
10: 
11: [Repository MonCompte]
12: type = IMAP
13: remotehost = imap.moncompte.tld
14: ssl = yes
15: cert_fingerprint = lalalalalala
16: remoteport = 993
17: remoteuser = moi@moncompte.tld
18: remotepass = lololololo

Puis, créer un dossier de travail qu'on va appeler intelligemment dmarc

$ mkdir -p dmarc/mails

S'assurer que le script main.go téléchargé juste avant sur github est bien dans le dossier dmarc que l'on vient de créer. Dans le cadre de la surveillance en mode test, il peut être intéressant de connaître plus précisément les IPs ayant généré des erreurs. Pour cela, ajouter les lignes suivantes à la fin du fichier main.go

1:  $ diff -u upstream_main.go main.go
2:  --- upstream_main.go    2016-04-04 15:16:25.552078344 +0200
3:  +++ main.go    2016-04-04 15:13:18.452071510 +0200
4:  @@ -98,6 +98,21 @@
5:       const DATEFMT = "2006-01-02 03:04:05"
6:       printfLock.Lock()
7:       defer printfLock.Unlock()
8:       fmt.Printf("%s,%s,%s,%s,%d,%d,%d\n", fb.DateBegin().UTC().Format(DATEFMT), fb.DateEnd().UTC().Format(DATEFMT),
9:           fb.Organization, fb.Domain, dispos_none, dispos_quarantine, dispos_reject)
10: +
11: +  for _, rec := range fb.Records {
12: +    fmt.Printf("filedetails,,,%s,%s,%s,%s,%s\n",
13: +      rec.SourceIP,
14: +      rec.HeaderFrom,
15: +      rec.Disposition,
16: +      rec.EvalSPF,
17: +      rec.EvalDKIM)
18: +    }
19:  }

Ajouter à côté le script suivant :

1:  $ cat ~/dmarc/parse_dmarc.sh
2:  #!/usr/bin/env bash
3:  
4:  for file in $(ls -1 mails); do
5:      go run main.go mails/${file} &>/dev/null
6:      if [ "$?" = 1 ]; then
7:          echo "Error in file ${file}"
8:      fi
9:  done

Utilisation

Dans un premier temps on va extraire tous les pièces jointes des mails contenus dans le dossier DMARC de la boîte à surveiller.

$ cd ~/dmarc/mails
$ munpack ~/Mail/MonCompte/INBOX/DMARC/cur/*

Puis, on fait un peut de nettoyage

$ rm part*
$ rm *.desc
$ unzip *.zip
$ rm *.zip
$ ls -1 | grep gz
toto.xml.gz
tata.xml.gz
$ gzip -d toto.xml.gz tata.xml.gz
$ ...

Bref, il faut s'assurer qu'on n'a plus que des fichiers XML dans ce dossier. Ceci fait, yapuka appeler une première fois le script parse_dmarc.sh qui va nous afficher tous les fichiers xml pour lesquels on va avoir des problèmes.

$ ./parse_dmarc.sh
Error with file aol_totottatatiansetnset.xml
Error with file fastmail_ututunasetinetsa.xml

Pour chacun des fichiers listé, les ouvrir et tenter de les ré-enregistrer en utf8. Emacs sait faire ça très bien. Attention, certaine fois l'entête même du fichier xml préciser qu'ils s'agit d'un encodage autre (encoding="windows-1252") Dans ce cas, penser à modifier cet entête pour y faire figurer utf-8.

Enfin, lancer le script go

$ go run main.go mails/* > dmarc.csv

Vous avez désormais un super fichier CSV à ouvrir dans le tableur de votre choix.

Filtrage

Dans le cadre d'une analyse pré-filtrage de DMARC, vous pouvez utiliser les deux commandes ci-dessous pour obtenir la liste des IPs qui échoue la vérification SPF ou DKIM :

$ grep filedetails dmarc.csv | cut -d, -f4,5,7 | grep fail | sort | uniq > fail_spf.csv
$ grep filedetails dmarc.csv | cut -d, -f4,5,8 | grep fail | sort | uniq > fail_dkim.csv

Ces échecs s'explique par le fait que des gens ont paramétrés leur client mail pour utiliser le serveur SMTP de leur FAI pour envoyer des mails depuis une adresse moncompte.tld.

mercredi 23 mars 2016

LibreOffice Headless with systemd

I’ve fought a very annoying bug recently and think it’s worth sharing it here. At work we manage different type of user provided documents. For various reason we convert it to pdf. This step is achieved using a headless libreoffice installation. Our server run Debian GNU/Linux Wheezy and everything go smoothly.

Until… one of our client need our software to be hosted on his own servers, running CentOS. Nothing bad here, but it leads us to develop various systemd service files for our systems as recent versions of CentOS switched to systemd. Here come the bug. We were used to run libreoffice as follow, embed in an init.d script:

1: soffice -headless -accept="socket,host=127.0.0.1,port=8101;urp;" -display :5.0 -nofirststartwizard & > /var/log/soffice.log 2>&1

Moving on systemd and more recent version of libreoffice, I learn that single-dotted options are no more. Thus, my first attempt to write a systemd service file, directly inspired by the line above, was:

1:  [Unit]
2:  Description=Control headless soffice instance
3:  After=network.target xvfb.service
4:  Requires=xvfb.service
5:  
6:  [Service]
7:  Type=simple
8:  ExecStart=/opt/libreoffice4.4/program/soffice --headless \
9:      --accept="socket,host=127.0.0.1,port=8101;urp;" --display :5.0 \
10:     --pidfile=/var/run/soffice.pid --nologo --nodefault --nofirststartwizard
11: RestartSec=5
12: ExecStop=/usr/bin/pkill -F /var/run/soffice.pid
13: PIDFile=/var/run/soffice.pid
14: 
15: [Install]
16: WantedBy=multi-user.target

And nothing works as expected. In fact, I’m lying a bit: the daemon was here, systemctl telling me everything is ok and libreoffice showing off in ps axf. But no conversion succeeded. The problem was obvious: looking at netstat -laputn show me that nothing was listening at port 8101.

After weeks of test, we abandoned the problem (I just start the exactly same command by hand and forget it). Yesterday it comes to my face, due to a libreoffice crash, which prevents conversion to occurs. We use monit to monitor our process, but in this case soffice wasn’t monitored, as I didn’t reached to have a functional service. As I was crying blood, because of not understanding the problem source, I try a last thing before fucking all of it and writing a quick’n’dirty shell script. And it works.

1:  [Unit]
2:  Description=Control headless soffice instance
3:  After=network.target xvfb.service
4:  Requires=xvfb.service
5:  
6:  [Service]
7:  Type=simple
8:  ExecStart=/opt/libreoffice4.4/program/soffice --headless \
9:      --accept=socket,host=127.0.0.1,port=8101;urp; --display :5.0 \
10:     --pidfile=/var/run/soffice.pid --nologo --nodefault --nofirststartwizard
11: RestartSec=5
12: ExecStop=/usr/bin/pkill -F /var/run/soffice.pid
13: PIDFile=/var/run/soffice.pid
14: 
15: [Install]
16: WantedBy=multi-user.target

Yes: nothing changes, but the quotation marks on line 9. The solution was simply to remove them from the ExecStart line. I absolutely don’t know why putting here double quotes prevent systemd-started soffice to open a socket, but it does. If anyone has an explanation, I’m very curious. The documentation itself is not very clear about that. Anyway, now we have a working service file for headless execution of libreoffice.

samedi 23 janvier 2016

Matrix review

Encore un film que j'ai du voir trop jeune1 pour en saisir tout l'intérêt. J'aimerais revenir aujourd'hui sur Matrix (le 1) que j'ai revu récemment. Je pense que d'un point de vu général, beaucoup est déjà disponible du point de vue de l'analyse concernant ce film et cet univers. C'est pourquoi je vais surtout revenir ici sur mon point de vue de simple spectateur.

Pour comprendre mon étonnement lors de ce second visionnage, quelque chose comme dix ou quinze ans plus tard, il faut d'abord savoir que le souvenir que j'en avais gardé était assez éloigné de ce que j'ai redécouvert. Pour moi, Matrix était un film de SF classique, dans un univers minimaliste et peu décrit. Mon opinion avait été forgée de telle manière qu'au moment de la sortie des suites je m'étais élevé contre, pensant que rien ne pouvait suivre ou précéder le film initial. Après les avoir vu, je me souviens avoir été vaguement déçu de ce que j'avais perçu comme un éloignement des concepts abordés dans le premier film. Je vous passe les souvenirs tronqués et fantasmés (pour moi, Néo sautait bien du toit au début du film, ou encore l'oracle lui prédisait bien que c'était lui l'élu). Bref, j'étais à côté de la plaque.

Le film que j'ai redécouvert est à l'opposé de ces impressions. Cet article tient donc lieu de mea culpa quant aux avis que j'ai pu essaimer depuis des années à propos de cet univers. Oui, Matrix semble dès l'origine avoir été pensé comme un univers beaucoup plus complexe que mes souvenirs fragiles me laissaient paraître. J'ai été étonné de revoir combien de fois est évoqué Sion qui n'apparaît réellement que dans les opus suivants.

Par ailleurs, je souhaitais souligner le caractère résolument novateur et ouvert d'esprit de l'ensemble de la réalisation, à l'image des Wachowski eux-mêmes. Le nombre d'ethnies différentes visible à l'écran est juste impressionnant dans un monde où, même en 2016, une partie de la population hurle au scandale lorsqu'un noir joue un Stormtrooper. La répartition des genres est également parfaitement maîtrisée puisque la proportion de femme au sein du casting dans des rôles principaux, loin des simple faire-valoir est très correcte : Trinity en second du navire, l'Oracle qui sert de mentor à la résistance ou encore Switch efficace dans son rôle de combattante. Cette dernière illustre d'ailleurs parfaitement la question des transgenres, à mettre en abîme sur le changement de sexe de Lana Wachowski. À ce titre Matrix reste pour l'instant le seul film que je connaisse où cette notion transparaît. Surtout de manière aussi positive.

Bref, j'ai passé un bon moment et je me tâte du coup à revoir les suivants pour me défaire définitivement, peut-être, de mes premières impressions faussées.

1 Vous ai-je déjà parlé de Jurassic Park ?

- page 2 de 38 -