dimanche 10 janvier 2016

Dnssec chez vous

Cela faisait un certain temps que j'avais installé un résolveur DNS sur ma machine, tout d'abord parce que le DNS de mon fournisseur d'accès à Internet avait la fâcheuse tendance à planter, et ensuite parce que ça le fait d'aller interroger directement les serveurs racine.

Il y a quelques jours, ayant lu un article sur Dnssec, je me suis donc demandé si mon installation utilisait ce système qui permet de sécuriser la résolution de nom en s'assurant que personne de bidouille l'info, typiquement pour nous router vers un site de malware plutôt que le site recherché. Une rapide recherche m'amena vers un site de test qui me démontra que non. Retroussons nous donc les manches!

Déjà, il faut vérifier que votre résolveur fonctionne avec dnssec. Un petit "dig +dnssec" pour résoudre un nom qui supporte ce standard nous informe que c'est bon:

$ dig +dnssec http://www.dnssec-deployment.org/

; <<>> DiG 9.9.5-12.1-Debian <<>> +dnssec http://www.dnssec-deployment.org/
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 62323
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 0, AUTHORITY: 6, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;http://www.dnssec-deployment.org/. IN  A

;; AUTHORITY SECTION:
.                       10797   IN      SOA     a.root-servers.net. nstld.verisign-grs.com. 2016011000 1800 900 604800 86400
.                       10797   IN      RRSIG   SOA 8 0 86400 20160120050000 20160110040000 54549 . MTlQxI92KqWfL5GsAk6eBL3T9KHsQIt3lWkC9jmiyYBl7+qCcOJUZOvG 4oEN1JizSsEhpp76oM0Fg9svRHryV5oZZr7Od2CHbI9jfuiYYPhvO16E o6EkPwoXZcnm6Y6JgLXKd/UOQK+J+WhlyqFP8swSgynv/FwvaRIFgkf/ cNw=
.                       10797   IN      RRSIG   NSEC 8 0 86400 20160120050000 20160110040000 54549 . uhX0FXBilUV7ZCP3sC/tPYVA5Srlu8MknbmGKZLLUf5FzRDH0tCk+HZb wy/2MGTnISsFnRftRgw4mR5tmBW6jgeYsR4PS46360GAqT1h5mvBAmHv gEE+5/g1kVsSi/MDJ075VduVHD+yMwCS5KZ/ynywsq7uj93gescPj+0V TbE=
.                       10797   IN      NSEC    aaa. NS SOA RRSIG NSEC DNSKEY
org.                    10797   IN      RRSIG   NSEC 8 1 86400 20160120050000 20160110040000 54549 . hPeKkCWTQbKtMBSDf/sGOnX1CHBXez4kuG2ulIc94USFgWR6Oz+R7OIs qCzjursXz+79hYd3HFrYFYX0KlWj08zpZHtTB4zz9TRoH1ep3ARoPWkR iyPDEkLgFyGlYnqQD3VuiIHQ478BUlgQ8vmKE/5REMsTXKIJxIG+kO95 YSs=
org.                    10797   IN      NSEC    organic. NS DS RRSIG NSEC

;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Sun Jan 10 15:40:46 GMT 2016
;; MSG SIZE  rcvd: 669

La présence de lignes RRSIG indique que la requête est revenue avec la signature demandée.

Maintenant, il suffit de configurer son résolveur pour que la résolution se fasse correctement. Avec bind9 sur Debian, c'est:

  • Ouvrir le fichier /etc/bind/named.conf.options
  • S'assurer que les 2 options dnssec-enable et dnssec-validation sont présentes
  • Mettre dnssec-enable à "yes" et dnssec-validation à "auto"

Mon fichier ressemble à cela:

options {
        directory "/var/cache/bind";
        dnssec-enable yes;
        dnssec-validation auto;
[...]

Notez que dnssec-validation doit être à "auto" et non à "yes", ce qui va lui permettre d'utiliser le fichier de signature présent avec la distribution. Avec l'option "yes", il faut en fournir un à la mimine.

Maintenant, redémarrez bind9. Un "dig www.dnssec-failed.org" devrait vous renvoyer un beau "status: SERVFAIL". Essayez également de visualiser le site depuis un navigateur, il devrait vous dire que le serveur n'a pu être trouvé. Yeah!

Petite astuce: assurez vous que le résolveur de noms de votre fournisseur est complètement ignoré, et pas simplement mis après votre résolveur local. Il m'a fallu enlever "domain-name-server" de mon dhclient.conf que la résolution DHCP ne charge pas le serveur DNS de mon fournisseur. Dans le doute, regardez votre resolv.conf.

samedi 19 septembre 2015

std::make_shared et allocations

J'avais rapidement et indirectement parlé de std::make_shared ici, et en particulier l'optimisation qui consiste à allouer la structure de contrôle avec l'objet lui même, économisant ainsi une allocation. Prouvons donc que la bibliothèque C++ standard fournie avec g++ le fait effectivement. Prenons un programme qui alloue 100 pointeurs partagés:

#include <memory>
#include <vector>

int main()
{
  std::vector<std::shared_ptr<int> > v;

  for(int i = 0; i < 100; ++i)
  {
    //v.push_back(std::make_shared<int>(5));
    v.push_back(std::shared_ptr<int>(new int(5)));
  }
  
  return 0;
}

Faisons tourner la chose avec valgrind. Quand la première ligne à l'intérieur de la boucle est commentée, c'est à dire que l'on alloue un entier, puis qu'on le passe à un pointeur partagé, valgrind nous indique ceci:

==4484== HEAP SUMMARY:
==4484==     in use at exit: 72,704 bytes in 1 blocks
==4484==   total heap usage: 209 allocs, 208 frees, 79,584 bytes allocated

Le chiffre important, ici, c'est les 209 allocations: 100 allocations d'entiers, 100 allocations de structure de contrôle, et j'aurais envie de dire 8 allocations pour le vecteur et 1 allocation en dehors de notre contrôle. Maintenant, commentons la deuxième ligne et décommentons la première. Valgrind nous dit alors:

==4491== HEAP SUMMARY:
==4491==     in use at exit: 72,704 bytes in 1 blocks
==4491==   total heap usage: 109 allocs, 108 frees, 79,184 bytes allocated

Yay! Nous avons effectivement une seule allocation dans la boucle au lieu de 2, le make_shared a donc bien alloué la structure de contrôle avec l'objet. À noter que la taille totale allouée est légèrement plus basse, peut-être grâce à des histoires d'alignement?

vendredi 21 août 2015

Gcc et link time optimisation

Comme promis, je vous parle un peu de cette récente fonctionnalité de gcc, qui permet au compilateur d'optimiser à travers les unités de compilation. Le compilateur de Microsoft avait cette fonctionnalité depuis bien longtemps, et gcc était donc un petit peu à la traine, mais à chaque release, de nouvelles améliorations sont apportées à ce qui pourrait bien donner un sérieux coup de fouet aux performances (à l'exécution, parce qu'en revanche, les temps de compilation vont exploser...).

L'idée est que plutôt que de compiler chaque unité de compilation vers du code machine, le compilo s'arrête à une représentation moins bas niveau. C'est cette représentation qui est passée à l'éditeur de liens, qui peut alors refaire une passe d'optimisation en ayant l'ensemble des unités de compilation disponibles. La plus évidente des optimisations possibles est d'inliner les fonctions d'une unité de compilation vers une autre unité de compilation.

Pour comprendre ce qui se passe, je vous propose deux programmes. Voici le premier :

// p1.c
int f(int a, int b)
{
  return a + b;
}

int main()
{
  return f(3, 5);
}

Voici le deuxième, divisé en 2 fichiers

// p2.c
int f(int a, int b);

int main()
{
  return f(3, 5);
}

// p2l.c
int f(int a, int b)
{
  return a + b;
}
Compilons le premier programme avec l'optimisation à fond : "gcc -O3 p1.c -o p1". Puis désassemblons le programme avec "objdump -d -S p1". La partie intéressante est :
00000000004003c0 <main>:
  4003c0:       b8 08 00 00 00          mov    $0x8,%eax
  4003c5:       c3                      retq   

Sans surprises, le compilo a bien inliné le tout, et renvoie simplement la valeur calculée 8.

Maintenant, le deuxième programme: "g++ -O3 p2.c p2l.c -o p2". Le code désassemblé montre bien le passage des deux paramètres 5 et 3 suivi d'un appel de fonction, puisque la fonction "main" ne peut pas voir le contenu de la fonction f.

0000000000400480 <main>:
  400480:       be 05 00 00 00          mov    $0x5,%esi
  400485:       bf 03 00 00 00          mov    $0x3,%edi
  40048a:       e9 01 01 00 00          jmpq   400590 <_Z1fii>

0000000000400590 <_Z1fii>:
  400590:       8d 04 37                lea    (%rdi,%rsi,1),%eax
  400593:       c3                      retq   
  400594:       66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
  40059b:       00 00 00 
  40059e:       66 90                   xchg   %ax,%ax

Et maintenant, voyons avec la lto: g++ -flto -O3 p2.c p2l.c -o p2_lto. Ah ah! Nous retrouvons quelque chose d'identique au tout premier programme. Le compilateur a en effet été capable d'inliner la fonction f dans main, quand bien même sa définition n'était pas accessible. Ça marche!

0000000000400480 <main>:
  400480:       b8 08 00 00 00          mov    $0x8,%eax
  400485:       c3                      retq   

mardi 4 août 2015

Ubuntu Phone - Top des applications

Bon, des applications sur Ubuntu Phone, y'en a pas tellement. Raison de plus pour savoir quelles sont celles qui sortent du lot. Voici mon top 5, tous logiciels libres:

Shorts

Jusqu'à présent, je ne me servais pas d'un aggrégateur de flux RSS. Mais, sur un téléphone, lire des articles sur un navigateur est assez pénible, surtout quand la bestiole n'est pas très véloce. Je m'y suis donc mis, et ça change la vie. Shorts permet de chercher des flux RSS et de les catégoriser, et affiche les articles dans une interface claire et efficace. Tout est mis en cache lors du rafraichissement, ce qui permet de se garder des choses à lire pour les endroits où il n'y a pas de réseau. J’agrège donc LinuxFR, Portail Aviation, l'Odieux Connard et Xkcd.

Dekko

Dekko est une très bonne application de courrier électronique, qui me permet de garder un œil sur mes boites en IMAP. C'est assez véloce, et ça marche vraiment très bien. Un petit bug m'empêchait de faire fonctionner l'IMAP sur une boite OVH, mais les forums expliquent quel paramètre changer dans quel fichier de configuration pour que tout tourne sans histoires.

OSMTouch

OSMTouch, c'est l'application qui permet d'accéder aux cartes d'OpenStreetMap. C'est une application native plutôt qu'un conteneur Web, et c'est redoutablement efficace. Attention cependant, ne fonctionne qu'en mode connecté et ne permet pas de mettre des cartes en cache. À noter que je n'ai pas réussi à faire fonctionner le GPS sur mon BQ Aquarius 4.5, mais les autres applications n'ont pas l'air de le voir non plus, donc ce n'est pas la faute d'OSMTouch

Twitter

Alors d'accord, ce n'est qu'un conteneur Web, et la qualité de l'application est plus un testament du talent des développeurs Twitter. Mais il est bon à savoir que ça marche particulièrement bien sur Ubuntu Touch. À noter que je ne suis que consommateur de Tweets, je n'ai donc aucune idée s'il est aisé d'en écrire via cette interface.

2048

C'est un petit jeu qui rappelle vaguement le taquin, dans le sens où il faut pousser des carrés sur une grille. Mais le principe de 2048 est de combiner les carrés de même valeur pour la faire doubler. Donc combiner deux 2 devient 4, deux 4 devient 8, et ainsi de suite, jusqu'au mythique 2048. Rudement addictif, et raisonnablement stratégique.

mercredi 15 juillet 2015

The Talos Principle - Fini!

Il m'a quand même fallu 27 heures pour compléter le jeu, et voir une de ses fins (à priori, la plus intéressante) en ayant résolu tous les problèmes. Pfiou! À noter que j'ai quand même raté beaucoup d'Easter Eggs, lesquels sont recensés dans de nombreuses vidéos sur Youtube. Je demeure très impressionné par l'intelligence de ce jeu, aussi bien dans le gameplay que dans l'histoire. Une très bonne expérience, entièrement sous Linux!

Je vais donc pouvoir revenir à une activité normale, comme on dit. En particulier, je n'ai vraiment plus qu'à trouver 3 heures de libre d'un seul tenant pour enfin charger mes vieux SMS dans mon Ubuntu Phone. Faut pas se laisser aller.

jeudi 18 juin 2015

Ubuntu Touch - Transférer ses SMS - Phase 1: reconnaissance (suite)

Reprenons, et regardons de plus près les deux tables restantes, thread_participants et text_events.

thread_participants

ChampTypeCommentaire
accountIdchaîneClé vers la table "threads"
threadIdchaîneClé vers la table "threads"
typeentierClé vers la table "threads"
participantIdchaîneLe nom du participant à ce fil de discussions. Pour les SMS simples, c'est simplement notre correspondant. De ce que je vois des données, utiliser la même valeur que le threadId fonctionne

text_events

ChampTypeCommentaire
accountIdchaîneClé vers la table "threads"
threadIdchaîneClé vers la table "threads"
eventIdchaîneProbablement un identifiant unique pour le message. Dans mes données, c'est à une valeur qui ressemble à "/ril_0/message_" suivi d'une chaîne qui ressemble furieusement à un hash pour les messages envoyés, et à une date au format ISO (par exemple 2015-06-01T22:35:52+0100-1) pour les messages reçus
senderIdchaîneL'envoyeur, à "self" pour les messages envoyés, et au numéro de tel de l'envoyeur pour les messages reçus
timestampdatetimeLa date et l'heure auxquelles le message a été reçu
newEventbooléenAucune idée. Toujours à faux dans mes données.
messagechaîneLe message proprement dit
messageTypeentierLe type de message, manifestement toujours à 0
messageStatusentierManifestement là pour indiquer si le message a été lu, envoyé, etc. Les bonnes valeurs semblent être 4 pour les messages envoyés, et 0 pour les messages reçus
readTimestampdatetimeLa date et l'heure auxquelles le message a été lu. Peut probablement être mis à la même valeur que timestamp pour les messages reçus, et à null pour les messages envoyés.
subjectchaîneLe sujet du message, manifestement non-existant pour les SMS (peut-être là pour les MMS?). Doit probablement être mis à null pour les messages envoyés et à la chaîne vide pour les messages reçus

Maintenant, il va me falloir passer à la deuxième phase: massage de mes données en CSV pour pouvoir les insérer dans la base et retrouver mes SMS.

mercredi 10 juin 2015

Ubuntu Touch - Transférer ses SMS - Phase 1: reconnaissance

Les SMS sur un Ubuntu Phone sont situés dans une base de données sqlite à l'emplacement ~/.local/share/history-service/history.sqlite. En théorie, pour importer ses SMS, il suffit de les ajouter à la base dans le format qui va bien. Téléchargeons donc la base et jetons un coup d'oeil:

$ sqlite3 history.sqlite
sqlite> .schema
CREATE TABLE schema_version (
    version int
);
CREATE TABLE threads (
    accountId varchar(255),
    threadId varchar(255),
    type tinyint,
    lastEventId varchar(255),
    lastEventTimestamp datetime,
    count int,
    unreadCount int
);
CREATE TABLE thread_participants (
    accountId varchar(255),
    threadId varchar(255),
    type tinyint,
    participantId varchar(255)
);
CREATE TABLE text_events (
    accountId varchar(255),
    threadId varchar(255),
    eventId varchar(255),
    senderId varchar(255),
    timestamp datetime,
    newEvent bool,
    message varchar(512),
    messageType tinyint,
    messageStatus tinyint,
    readTimestamp datetime,
    subject varchar(256)
);

Rien de très méchant à priori (j'ai laissé la partie du schéma qui décrit les "triggers" qui mettent à jour certaines dates, ainsi que les voice_events, correspondant aux conversations téléphoniques, et aux text_event_attachments, correspondant aux pièces jointes, j'imagine pour les MMS). L'on comprend qu'il y a un certain nombre de "threads", qui regroupent un certain nombre de "thread_participants", et que l'on peut ensuite ajouter chaque message dans text_event. Voici ce que j'ai réussi à en comprendre de la première table d'après les données déjà présentes après quelques appels et quelques SMS:

threads

ChampTypeCommentaire
accountIdchaîneUn nom de compte, probablement une constante pour tous les téléphones. Chez moi, c'est systématiquement la valeur "ofono/ofono/account0"
threadIdchaîneL'identifiant du thread. C'est apparemment le numéro de téléphone de son correspondant, sauf quand il s'agit de correspondants nommés, comme "Ikea" ou "Orange"
typeentierUne valeur qui peut être 0 ou 1. En regardant les numéros de téléphone associés, je pense que cela indique s'il s'agit d'un thread de message, avec le code 0, ou d'un historique d'appel, avec un 1. Pour l'import des SMS, on mettra 0 partout.
lastEventIdchaîneC'est un identifiant assez moche, qui contient soit un numéro de téléphone, soit une date, suivi d'une date et d'une heure. J'imagine que c'est le dernier eventId de la table text_events, et qu'il est mis à jour via une trigger
lastEventTimestampdate et heurela date et l'heure du dernier message
countentierLe nombre de messages dans le thread
unreadCountentierLe nombre de messages non lus. Pour l'import, un 0 sera bien suffisant.

Suite au prochain numéro, car il est temps d'aller se coucher!