Il n'est pas possible de poster de commentaires, mais vous pouvez toujours m'envoyer un mail pour que je mette à jour le billet.
(Note: Ce billet date d'environ six mois mais j'ai trop procrastiné pour le relire et le publier. Ca m'a aura au moins permis de mettre à jour certaines sections.)
Le système des capabilities sous UNIX est le parcellement du droit root en de multiples privilèges : lecture RAW du disque, capture du trafic sur la carte réseau, chargement de module, etc.
Ce travail a été débuté par le comité POSIX avec l'écriture de POSIX 1.e, mais après une dizaine d'années de travail, les sponsors ont quitté le navire et le comité a annonçé en 1998 : So the Standard Posix.1e is not likely to be "finished" or "released" anytime soon.
Bien que la standardisation ait été un échec, les développeurs des différents systèmes d'exploitation n'ont pas abandonné les capabilities pour autant, en particulier pour le noyau Linux qui a fait quelques avançées majeures l'année dernière, en particulier avec le 2.6.24 et le 2.6.25
Capabilities
Introduction
Toutes les capabilities existantes sont disponibles dans /usr/include/linux/capability.h elles sont au nombre de 34 (à l'heure actuelle) :
CAP_CHOWN CAP_NET_ADMIN CAP_SYS_RESOURCE CAP_DAC_OVERRIDE CAP_NET_RAW CAP_SYS_TIME CAP_DAC_READ_SEARCH CAP_IPC_LOCK CAP_SYS_TTY_CONFIG CAP_FOWNER CAP_IPC_OWNER CAP_MKNOD CAP_FSETID CAP_SYS_MODULE CAP_LEASE CAP_KILL CAP_SYS_RAWIO CAP_AUDIT_WRITE CAP_SETGID CAP_SYS_CHROOT CAP_AUDIT_CONTROL CAP_SETUID CAP_SYS_PTRACE CAP_SETFCAP CAP_SETPCAP CAP_SYS_PACCT CAP_MAC_OVERRIDE CAP_LINUX_IMMUTABLE CAP_SYS_ADMIN CAP_MAC_ADMIN CAP_NET_BIND_SERVICE CAP_SYS_BOOT CAP_NET_BROADCAST CAP_SYS_NICE
On peut traçer une ligne dans ce groupe avec les capabilities
correspondant une autorisation (c'est à dire "je suis autorisé à
effectuer ce type d'action") et celles élévant les privilèges comme
CAP_MAC_OVERRIDE qui permet d'inhiber l'effet des
permissions du filesystem.
Les capabilities sont acquises soit par héritage du père, par des capabilities attachées au filesystem ou forçée par un processus externe.
La capability CAP_SET_CAP est nécessaire afin de modifier
les capabilities.
Thread capabilities
Un processus, ou thread, possède en fait trois ensembles de capabilities :
Permissions effectives, les privilèges que le processus peut utiliser dès à présent.
Permissions permises, ce sont les privilèges que peut acquérir le processus s'il le désire. En d'autres termes, ce sont les permissions qui peuvent être déplaçées dans l'ensemble des permissions effectives.
Permissions héritées, les privilèges léguées.
Nous verrons dans les sections suivantes comment sont calculées
automatiquement lors d'un execve().
capget permet de consulter les capabilities d'un
processus, le noyau Linux offre également une entrée dans
/proc :
# grep Cap /proc/self/status
CapInh:000000000673b200
CapPrm:0000000000000000
CapEff:0000000000000000
CapBnd:ffffffffffffffff
File capabilities
Les file capabilities étaient jusqu'au 2.6.24 la pièce manquante dans l'implémentation de Linux qui lui permettait d'être complète. Ces privilèges prennent leurs sens lorsqu'un fait un execve sur ce fichier, le processus exécutant le programme verra ses thread capabilities modifiées en conséquence.
Il existe également trois ensemble de file capabilities :
Permissions permises (ou forçées), un processus gagnera automatiquement ces capabilities.
Permissions héritées (ou autorisées), cet ensemble permet de réduire les capabilities héritées d'un thread : un "ET LOGIQUE" sera fait entre les permissions héritées du processus et les permissions héritées du fichier.
Permission effective, cet "interrupteur" pousse les nouvelles permissions permises directement dans les permissions effectives du thread. Autrement, les permissions effectives sont écrasées à 0.
capability bounding set
Grossièrement, c'est l'ensemble des capabilities autorisées sur le système.
Transfert entre processus
Il n'y a que deux moyens pour modifier ses capabilities :
- Manuellement, avec
cap_set_procouprctl - Lors d'un
execve()
Lors d'un fork(), tous les ensembles de capabilities sont
copiées du père vers le fils sans modification. Nous ne nous
intéresserons qu'aux règles de transmission des capabilities lors d'un
execve.
Les règles de transfert sont les suivantes, extraites de la page de manuel capabilities(7) :
P'(permitted) = (P(inheritable) & F(inheritable)) |
(F(permitted) & cap_bset)
P'(effective) = F(effective) ? P'(permitted) : 0
P'(inheritable) = P(inheritable)
where:
P denotes the value of a thread capability set before the
execve(2)
P' denotes the value of a capability set after the execve(2)
F denotes a file capability set
cap_bset is the value of the capability bounding set
On constate que les permissions héritées sont toujours conservées. Les capabilities permises sont quand à elles adaptées avec "P(inheritable) & F(inheritable)" mais sont surchargées par le contenu de F(permitted) (modulo le capability bounding set).
Enfin, les permissions effectives du thread dépend de la permission effective du fichier, si elle est activée, les nouvelles permissions permises sont poussées au processus, autrement, elles sont vidées.
Comportement du Capability bounding set
En d'autres termes, cela signifie que les file capabilities l'emportent toujours sur les thread capabilities. C'est d'ailleurs le seul moyen d'élever ses capabilities, ce qui peut être problématique : dans un environnement cloisonné comme une sandbox, on voudrait bannir cette possibilité d'élevation. C'est le rôle du capability bounding set qui a changé de comportement au 2.6.25.
Pre-2.6.25
Avant, cette variable était globale au système : tous les processus la
partagaient. Cette approche avait au moins un avantage, c'était qu'au
moment où une capability était supprimée, il était garanti qu'elle ne
serait jamais distribuée à nouveau. Les sysadmins aimaient donc
enlever la capacité CAP_SYS_MODULE afin d'empêcher tout
chargement de module.
En réalité, la vérité est moins rose puisque d'une part, le capability bounding set n'a d'impact que sur le transfert des capabilities, tous les processus root, comme init, qui existaient avant la modification ont conservé la capability, si on est root sur un système, on peut toujours injecter du code dans init afin de charger notre module.
Deuxièmement, il est toujours possible de charger un module sans cette
capability : à l'aide de CAP_SYS_RAWIO, on peut par exemple utiliser
/proc/kcore et modifier à la volée la mémoire du noyau.
Post-2.6.25
Depuis le 2.6.25, la capability bounding set est devenu local à un
thread. L'appel système prctl() a été enrichi de la
commande PR_CAPBSET_DROP qui permet de supprimer des
privilèges de son capability bounding set.
Étant donné que toutes les règles de transfert de privilèges respectent cette variable, il est dès lors impossible de récupérer une capability perdue.
Exemple:
# cat > dummy.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/capability.h>
#include <sys/prctl.h>
int main(void) {
char *args[]= {"bash", "-i", NULL };
if (prctl(PR_CAPBSET_DROP, CAP_NET_RAW, 0, 0, 0) != 0) {
perror("prctl()");
return 1;
}
execve("/bin/bash", args, NULL);
}
# gcc -o dummy dummy.c
# ./dummy
inside# getpcaps $$
Capabilities for `17817': =ep cap_net_raw-ep
inside# tcpdump -ni eth0
tcpdump: eth0: You don't have permission to capture on that device
(socket: Operation not permitted)
inside# su - guest
guest@local:~$ su -
Password:
local:~# getpcaps $$
Capabilities for `17966': =ep cap_net_raw-ep
local:~# tcpdump -ni eth0
tcpdump: eth0: You don't have permission to capture on that device
(socket: Operation not permitted)
Ici, malgré les changements d'identité, il n'a pas été possible de récupérer la capability perdue.
Implémentation
Erreurs de jeunesse
Oubli de checks
Après de multiple séries de patches interminables, toutes les vérifications dans le noyau se basent sur une capability particulière plutôt que de simplement vérifier si on est root ou non.
Néanmoins, des vulnérabilités sont de temps en temps remontés sur le manque de check, comme c'était le cas samedi dernier.
Ce changement de méthode d'autorisation impose donc de conserver une compatibilité sur l'existant. Dans le cas normal, les choses sont relativement simples, mais dès qu'on se penche plus en avant sur les détails, les choses se compliquent : prendre en compte les binaires avec bit set-user-id, la complexité de l'appel système setuid(), etc.
L'introduction des capabilities a ouvert une vulnérabilité dans des logiciels mal programmés à cause d'une erreur de logique.
Vulnérabilité userspace
Pour émuler les capabilities sur des processus classiques, le noyau
est obligé de donner des valeurs initiales aux différents ensembles
de permission afin de calquer le comportement UNIX traditionnel, c'est
pour cette raison que les permissions héritées de tous les processus
avaient pI = ~0 (c'est à dire toutes les privilèges étaient hérités).
À l'époque, les règles de transition étaient les suivantes :
pI' = pI
pP' = (X & fP) | (pI & fI)
pE' = fE & pP'
Contrairement au comportement actuel, les capabilities permises
étaient écrasées par les capabities héritées masquées par les file
capabilities héritées (pI & fI) et ces permissions permises étaient
rendues effectives (modulo fE).
Puisque par défaut pI = ~0, un processus pouvait s'enlever des
privilèges de ses capabilities héritées, donc de ses permissions
permises et donc de ses permissions effectives.
Les règles de transition pour émuler le bit setuserid0 était le suivant :
if (uid==0 or file-to-exec-is-setuid0) {
fE = fI = ~0;
fP = 0;
} else {
fI = fP = fE = 0;
}
C'est à dire que si un processus lambda se supprimait une capability héritée (qu'on notera pI-) et qu'il executait un programme setuserid0, alors la formule de transition se transformait en :
pE' = (pI & fI) = pI- & ~0 = pI-
Quel intérêt ? Comme beaucoup de logiciels (ou de crackme :p),
sendmail ne vérifiait pas le code de retour de setuid(), comme dans
l'exemple suivant qui tournait avec uid=0 :
setuid(user);
execve(user_controlled_program);
Dans le noyau, setuid() vérifie la capability CAP_SETUID
pour autoriser ou non le changement d'utilisateur.
L'attaquant avait alors à supprimer cette capability de son héritage,
exécuter sendmail en demandant d'exécuter /bin/bash. Au
moment du setuid(), le noyau refuserait et le programme continuerait
son flot en restant uid=0.
Bien qu'ici, la vulnérabilité soit majoritairement la faute de sendmail et non du noyau, les développeurs du noyau ont modifiés les règles de transitions et de valeurs initiales d'émulation.
Intérêt
Supprimer tous les programmes setuserid0
Fedora a décidé de supprimer tous les binaires setuserid0 afin de d'utiliser les capabilities à la place, par exemple pour ping :
# ls -alh /bin/ping
-rwsr-xr-x 1 root root 33K 2007-12-10 05:20 /bin/ping
# chmod -s /bin/ping
# setcap cap_net_raw=e /bin/ping
# setcap cap_net_raw=ep /bin/ping
# ls -alh /bin/ping
-rwxr-xr-x 1 root root 33K 2007-12-10 05:20 /bin/ping
# getcap /bin/ping
/bin/ping = cap_net_raw+ep
L'intérêt est évident : si le programme est exploité par un attaquant,
seul la capability est compromise et pas le reste du système (même
s'il faut garder à l'esprit l'histoire du CAP_SYS_MOD et
CAP_SYS_RAWIO).
Pourquoi cela n'est pas applicable sur toutes les distributions ? Deux raisons :
La première est que le noyau nécessite le support des file capabilities, ce qui a été ajouté dans le 2.6.24 (donc Debian Etch est hors concours).
La deuxième est que les file capabilities sont stockées dans les attributs étendus des fichiers (xattr). Ces xattr ne sont pas compatibles avec tous les filesystems. De plus, il faut que les outils d'installation (comme dpkg, ou tar au bout du compte) les supportent également.
Pour toutes ces raisons, il est difficile d'imposer cette
solution. Alors il y a 284 jours (d'après le rapport de bug), un
patch avait été soumis afin de supporter les capabilities dans start-stop-daemon, le logiciel qui démarre la majorité
des daemons sous Debian.
start-stop-daemon / minijail
L'idée est : puisqu'on ne peut pas modifier les paquets existant, on peut toujours modifier la façon dont ils sont lançés.
L'option --dropcap permet alors de jeter certaines capabilities
avant de lançer le daemon. In fine, le plan était de :
- Pousser les modifications dans
start-stop-daemon - Déterminer les capabilities nécessaires à chaque daemon d'un serveur classique
- Pousser ces données à chaque mainteneur de paquet
284 jours plus tard, la situation est restée bloquée au premier point par manque de temps (et de réaction côté Debian) :)
À vrai dire, c'est grâce à ChromeOS que je me suis rappellé de ce
post en cours d'écriture et du travail non achevé pour
start-stop-daemon. En effet, les développeurs de Google
ont implémenté
minijail qui implémente la relache de capabilities (et plein d'autres fonctions).
L'année dernière, le noyau Linux a vu un nombre impressionnant de patches avec le mot "namespace" dedans, tout s'est vu "namespacisé" : de l'espace des PID, aux points de montages en passant par les politiques IPSec.
Dans ce post, on va se focaliser sur la partie réseau et son utilisation dans le cadre d'un processus qu'on voudrait restreindre (au sens d'une chroot améliorée). On utilisera indifférement les termes machines virtuelles (VM), container, jail, etc.
Chacun cherche son chat
La partie réseau a été particulièrement polémique chez les développeurs du noyau car il y a de nombreuses façons de réaliser cet espace de nommage : il y a autant de façons que de couches protocolaires comme le détaille l'article de J. Corbet.
Il y a les partisans d'une approche légère où la virtualisation est simplement faite au niveau des sockets et d'autre qui voudraient pouvoir complétement virtualiser la pile TCP/IP afin d'avoir des interfaces, adresses IP, routes et politiques IPSec complétement distinctes entre les machines virtuelles.
La solution qui a été finalement choisie est celle virtualisant la couche 2, cela permet ainsi d'avoir des interfaces complétement indépendantes entre les VM (et donc d'adresses IP, routages, etc.) et l'hôte.
Cette fonctionnalité est disponible dans le noyau Linux depuis le 2.6.27.
La création d'un namespace
Au niveau du noyau, il n'y a qu'un seul moyen de déclarer un nouvel espace de nommage, c'est via l'appel système unshare() (ou via clone() de manière indirecte). Cette fonction a pour effet de désassocier un namespace de son contexte d'exécution.
Son seul argument est le composant que l'on veut désassocier (réseau, système de fichier, descripteurs de fichiers). Cela signifie donc qu'un processus désirant se créér un nouvel espace de nommage est obligé d'être modifié afin d'appeller cet appel système. Un workaround est l'utilisation d'un programme qui va faire cet appel à unshare() puis faire un execve() du programme cible.
Néanmoins, cela implique alors la distribution de deux fichiers (un programme qui exécute l'autre) car il n'existe pas de logiciel standards pour cette tâche, on pourra toujours utiliser netunshare extrait de la suite lxc.
Gestion des interfaces
Lorsqu'on créé un nouvel espace de nommage, le processus se retrouve avec une seule interface, un nouveau loopback uniquement. Pour enrichir sa collection d'interface, il est donc nécessaire de soit créér une nouvelle interface virtuelle, soit transférer une interface déjà existante.
Création d'interface
La création d'une interface virtuelle unique n'a de sens que si elle est connectée à quelque chose (de la même façon qu'un tunnel, il faut qu'il y ait un bout dans la VM, l'autre vers l'extérieur), il faut donc choisir autre chose qu'une interface du style 'dummy' qui peut être considéré comme un puit sans fond.
Une solution de tunnel existe depuis longtemps sous Linux, les tunnels TUN/TAP, or ils ont pour but de fournir un tunnel entre un descripteur de fichier et une interface réseau. Il faudrait donc créér un programme qui ouvrirait deux tunnels et qui passerait son temps à passer les paquets d'un côté à l'autre.
C'est pour cette raison qu'a été implémenté les interfaces de type Virtual Ethernet (veth) qui crééent une paire d'interfaces liées entre elles : ce qui rentre par l'une sort par l'autre et vice versa.
# ip link
4: lo: <LOOPBACK> mtu 16436 qdisc noop state DOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
# ip link add type veth
# ip link
4: lo: <LOOPBACK> mtu 16436 qdisc noop state DOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
9: veth0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN qlen 1000
link/ether fe:d8:a2:71:23:ae brd ff:ff:ff:ff:ff:ff
10: veth1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN qlen 1000
link/ether 3e:3e:90:3b:3f:c0 brd ff:ff:ff:ff:ff:ff
Si on créé une telle paire d'interface, on reste toujours avec le même problème : on a bien deux interfaces, mais elles restent confinées dans le container, il est donc nécessaire d'avoir un moyen de transférer une interface entre des espaces de nommage, ça tombe bien, c'est supporté :)
Transfert d'interfaces
Lorsqu'on transfère une interface, plutôt que de désigner explicitement un namespace, on précise à la place un PID, l'interface sera alors attachée au namespace de ce PID.
ip link set veth1 netns PID_DESTINATION
Lorsqu'un espace de nommage est détruit, toutes ses interfaces (sauf loopback) sont transférées automatiquement au namespace parent.
Possibilité
À l'intérieur d'un namespace, il est possible de faire tout ce que vous pouvez attendre d'un système normal : changement des routes, des adresses IP, etc.
L'intérêt de ce genre de cloisonnement est qu'une jail n'a qu'un seul point d'entrée et de sortie : l'interface réseau qui a été déportée par l'hôte.
C'est la grande différence avec vserver qui ne permet pas d'identifier clairement les flux entre VM en écrivant vos règles en terme d'interfaces (vous vous retrouvez obligé de jouer sur les adresses sources).
Ce qui n'est pas encore supporté
Pour le moment, Netfilter n'a pas encore le support des namespaces. Cela signifie qu'un container ne peut pas avoir ses propres règles de firewall, mais le problème principal est que Netfilter ne peut voir passer que les paquets sur l'espace de nommage initial. Cela signifie que si vous mettez en place un tunnel entre deux espaces de nommages, Netfilter ne pourra pas pas voir passer les paquets entre eux.
C'est pour cette raison qu'il est préférable de ne pas dédier une VM à la tâche de routeur : tout doit passer à travers l'hôte qui peut alors appliquer une politique de filtrage assurant le cloisonnement. Il faut alors travailler dans la cible FORWARD qui décidera de la politique à adopter.
Dans sa version 2.1.0, le serveur FTP sécurisé vsftpd de Chris Evans a intégré un mécanisme de sandboxing, son auteur le décrivant simplement comme :
An ambitious new built-in sandbox. Think of it as privsep++, but more
on this in an upcoming post and paper.
De quoi nous rendre curieux ! Hop, on télécharge les sources de la
2.0.7 et la 2.1.0 et on fait un diff entre les deux répertoires : pas
grand chose, on peut juste observer qu'il y a des appels à
ptrace_sandbox_alloc() et ptrace_sandbox_run() et c'est tout : cela
signifierait donc que la sandbox est complètement transparent pour le
code de l'application, une bonne chose !
Introduction à la sandbox
On constate néanmoins l'ajout de deux fichiers : ptracesandbox.c et
ftppolicy.c. Les choses sérieuses commencent enfin...
D'après le nom de fichier, on peut se douter que la sandbox repose sur
ptrace() (aka "the unique and arcane syscall"). Effectivement, elle
utilise PTRACE_SYSCALL qui permet d'interrompre le processus traçé à
l'entrée dans un appel système (dans la routine syscall_trace_entry
et de passer la main au traceur. vsftpd implémente ainsi toute sa
logique dans la fonction ptrace_sandbox_handle_event() qui vérifie la
provenance du signal puis regarde quel appel système est demandé.
Vérification de l'appel système
Ce check n'est pas aussi simple que prévu, Chris Evans a ainsi trouvé
la vulnérabilité CESA-2009-001 dans le noyau Linux
le mois dernier permettant de contourner des mécanismes de protection
basés sur ptrace() (comme systrace).
L'astuce est que sur les architectures supportant à la fois le mode 32
et 64 bits, les numéros d'appel systèmes ne sont pas les mêmes suivant
le mode dans lequel on est (le syscall numéro 2 est open() en 32 bits,
mais correspond à fork() en 64 bits). Il faut alors prendre des
précautions particulières pour s'assurer que tout le monde parle la
même architecture :
Si on a intercepté un
int80ousysenter, on est sûr d'être en 32 bits.Si c'est par l'instruction
syscall, les dés sont lançés, il faut alors consulter le sélecteur CS afin de vérifier s'il référence une table dont on connait son "type" (32 ou 64 bits).
Une fois le numéro d'appel système (vraiment) connu, la sandbox va
consulter deux tables, toutes deux indexées par numéro d'appel
système. La première indique si le syscall est autorisé ou non, la
deuxième donne le callback associé à l'appel système (par exemple, il
y a un callback pour open() qui permet de vérifier l'utilisation de
O_RDONLY).
Création de processus
Toutes les méthodes de création de processus sont interdites dans la policy. Chaque déviation à la politique est fatale pour le processus qui est tué par un SIGKILL, cette brutalité est ici problématique comme nous allons le voir. En effet, lorsque le traceur est prévenu, il est en mesure de modifier le numéro d'appel système que voulait exécuter le processus afin de le rendre inoffensif. Le noyau exécute alors l'appel système, puis rend la main au processus en délivrant tous les signaux en attente.
Ici, le problème est que lorsque la sandbox voit que c'est un fork() qui veut être exécuté, elle tue le processus (en fait, elle ajoute un signal SIGKILL dans la liste des signaux en attente) mais le noyau continue de dérouler la routine syscall et donc d'exécuter la création du fils.
Néanmoins, lorsque le parent est schedulé, le SIGKILL est délivré et
il est effectivement tué. Mais le fils existe toujours! C'est pour
cela que la sandbox utilise PTRACE_SETOPTIONS avec
TRACE_{VFORK,FORK,CLONE} pour tracer par défaut tous les fils que
pourrait créer un processus et les tuer quand bon lui semble.
C'est là que je suis perplexe puisqu'on a vu qu'on pouvait dire au
noyau "Non en fait, le processus a voulu exécuter le syscall exit(),
pas fork() mais tue le quand même après". Et c'est effectivement ce
que fait la sandbox : avant de tuer le processus par trois moyens
différents, elle ré-écrit les registres afin de pointer sur exit() donc
tout est fait proprement et le SETOPTIONS précédent est ici
superflu. Vu que Chris est sûrement paranoïaque, dans le doute, il a
préfèré mettre ceinture et bretelles.
Protection du processus monitorant
On comprend bien que la sécurité de la sandbox repose uniquement sur
le processus monitorant. Si celui-ci tombe, tous les mécanismes de
sécurité sont compromit, c'est pour cette raison que lors de
l'initialisation d'un nouveau processus, chaque fils fait un
prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0) afin que le noyau tue le
processus si son père (le moniteur) meurt.
Conclusion
Y a pas à dire, Chris Evans a réalisé ici un véritable chef-d'œuvre ! C'est la première fois que je vois une sandbox qui fait vraiment son rôle sans être vulnérable à la première attaque. Le design a été particulièrement travaillé, tout est clean et on sent qu'il y a eu de la réflexion derrière chaque fonction.
Impressionnant ! En plus, tout le moteur n'est contenu que dans un seul fichier C rendant son importation dans d'autres projets très simple.
D'humeur joyeuse, j'ai décidé de faire quelques analyses sur la quantité de spam reçu sur l'un des serveurs de messagerie que j'administre.
Voici le top 8 des raison de rejet sur plus de 113 000 messages considérés comme spam :
Top mail rejection reasons by message count
-------------------------------------------
Messages Mail rejection reason
61119 Rejected RCPT: Unrouteable address
30085 Spamassassin, score > 5
13099 SMTP protocol synchronization error
5653 Rejected RCPT: Sender verify failed
1615 Rejected RCPT: Spoofed EHLO/HELO
715 Connection refused
446 Rejected HELO/EHLO: syntactically invalid argument
417 Rejected RCPT: Too many bad recipients, now wait!
La première cause est assez facile à expliquer puisqu'elle résulte des robots spammeurs et leurs attaques par dictionnaire.
Le deuxième meilleur filtre reste le vénérable Spamassassin qui est configuré pour rejeter les messages lorsque le score dépasse les 5 points. Auparavant, le seuil était plus haut, autour de 8, mais au fur et à mesure, les spammeurs se sont adaptés et essayent désormais d'avoir un score le plus bas possible, si on analyse la distribution des scores, on obtient la figure suivante. Elle représente en ordonnée le nombre de messages qui ont été rejetés pour un score donné.
[[!img static/spamassassin-score.png ]]
Dommage que je n'ai plus accès aux logs d'il y a quelques années, je suis sûr qu'on aurait observé un glissement vers la droite de la courbe.
Les autres filtres sont beaucoup moins efficaces, en partie car ils ne sont matchés que lorsque le client a un comportement non légal avec les RFC :
Problème de synchronisation : les clients sont censés attendre la bannière EHLO avant de se présenter eux-mêmes. Les robots spammeurs n'ont pas cette politesse et envoient tout le plus vite possible.
Sender verify : c'est ce qu'on appelle un callout, à la réception d'un mail, vérifier que l'expéditeur pourrait bien recevoir une réponse (en gros, c'est vérifier que l'adresse existe bien).
Usurpations d'identité dans les présentations, le client se fait passer pour nous.
Trop de connexions simultanées depuis le même client
Syntaxe invalide des clients
Le client a généré trop d'erreurs de destinations (bruteforce)
Rendez moi mon entropie !
Toute la cryptographie repose sur la génération de nombres aléatoires, on a ainsi pû en voir les effets à de nombreuses reprises. Tout le monde citera la fameuse débacle Debian/OpenSSL mais c'est un incident parmi tant d'autres... Par exemple, un des CVE d'aujourd'hui concerne un défaut dans l'initialisation de la graîne (CVE-2009-0255) dans un CMS, "hier" c'était le générateur pseudo-aléatoire Microsoft qui était prit la main dans le sac par newsoft et Kostya, etc.
Tout ça, ce sont des problèmes "résolvables" : il y a tout un tas de recommendations pour éviter que cela ne se reproduise, en théorie. Mais si on commençe à regarder ce que le futur nous prévoit, on se rend compte qu'on va vers un tas d'ennuis...
L'entropie & ses problèmes
Commençons par expliquer comment on fait aujourd'hui. Tout d'abord, à part avec du matériel dédié, on ne sait générer que des nombres pseudo-aléatoires. Pour cela, on va utiliser des sources de bruit environnementales (température, timing d'accès disque, bruit d'un capteur, accéléromètre, interruptions clavier, etc.). Bref, tout ça relève quand même de la bidouille, mais de la bidouille qui fonctionne :)
Les choses se compliquent avec les nouvelles générations de matériels. On peut considérer qu'on est progressivement en train de changer "on-the-fly" la moquette par du lino tout en laissant les meubles posés. Autrement dit, on se repose sur les hypothèses de la dernière décennie pour montrer la solidité d'un système d'aujourd'hui.
Hardware 2.0
L'exemple du temps d'accès disque est flagrant, il avait été montré en 1995 que le temps d'accès pouvait être considéré comme aléatoire grace aux turbulences à l'intérieur des disques dur donc cela validait son utilisation pour contribuer à l'entropie du système. Mais là où ça devient embetant, c'est que l'on n'a pas remit en question cette propriété pour les disques dur SSD qui sont pourtant dépourvus de système mécanique. Hypothèse fail
Les mini-ordinateurs (NAS, bornes d'accès Wifi, boxes Internet, etc.) sont dépourvus de disques dur (remplaçés par de la CF ou équivalent), n'ont pas de clavier et ont tous une configuration exactement identiques en sortie d'usine (à part l'adresse MAC et le numéro de série marqué en NVRAM), comment peuvent ils avoir une entropie suffisante pour générer des clefs robustes (administration HTTPS, clefs SSH, clefs Wifi, etc.) lors du premier démarrage ? Rien ne l'indique... Il y a quelques "work-arounds" comme l'obligation de se plugger en Ethernet à la box afin de l'administrer pour la première fois (ça charge ainsi un peu d'entropie) mais les cryptographes ne considèrent pas les évenements venant du réseau comme "sûr" pour alimenter l'entropie.
Hypothèses fail
Virtualisation
La virtualisation apporte aussi son lot de problème : on utilise par exemple les interruptions car on considère qu'elles sont décorrélées de l'horloge du processeur (puisqu'elles sont normalement déclenchées par un évenement externe). Or avec un hyperviseur logiciel comme Xen, ce n'est plus le cas puisque c'est le dom0 qui génère ces interruptions, donc l'hypothèse de départ est encore invalidée. FAIL
De plus, avec la virtualisation matérielle, étant donné que les guests et le host partagent quelques ressources matérielles, sommes-nous vraiment certains qu'un guest ne peut pas prévoir le PRNG de son host ou de son voisin ?
Mutualisation
Beaucoup plus simplement, on a vu que la mutualisation de virtual hosts PHP pouvait mener à en partager un peu trop : s'ils ne sont pas utilisés en CGI, deux scripts PHP de vhosts différents peuvent tourner dans le même processus. Grossièrement, cela signifie que si le premier script fixe la graine d'aléa, le deuxième script utilisera le PRNG laissé dans l'état précédent. FAIL
Solution
La solution ? L'utilisation de RNG matériel est la seule possibilité. Les chipsets Intel et Via intègrent déjà cette fonctionnalité en XOR-ant les sorties d'oscillateurs libres fonctionnant à des horloges différentes.
Il n'y a plus qu'à espérer que ces HW-RNG soient vraiment robustes et que les implémentations soient correctes (pas comme NetBSD qui croyait détecter un HW-RNG alors que ce hub ne fournissait qu'un flux de 0xff :)...
Mise à jour du 30 janvier 2009 : En fait, c'est newsoft qui avait souligné le problème de clef dans Windows en lisant la note du CERTA.
Ça fait maintenant plus d'un mois que j'utilise le multi-tty dans Emacs et depuis, je n'arrête pas d'évangéliser à son sujet.
Si je devais donner une pseudo-définition, ca serait : le multi-tty permet de partager des buffers entre plusieurs instances d'emacsclient. Mais donnons plutôt un cas d'utilisation : chez vous, vous travaillez sur un fichier et vous partez au travail sans fermer votre Emacs mais vous avez vraiment envie d'y toucher, vos seules solutions sont :
Tuer emacs en espérant que vous n'aviez pas de changement non sauvegardés (ou alors se taper un diff avec les fichiers d'autosave)
Éditer le fichier comme une brute en forçant Emacs à piquer le fichier.
Dans tous les cas, c'est un plan lose. Alors qu'avec multi-tty, vous n'avez qu'à lancer votre emacsclient et changer de buffer pour récupérer le fichier oublié. Vous pouvez donc partager un buffer entre plusieurs emacsclients (chacun pouvant être en mode terminal ou X11), ce qui laisse la possibilité de faire une sorte de travail collaboratif sommaire si besoin.
Auparavant, cette fonctionnalité était un patch non
officiel. Mais elle a été intégrée il
y a quelques mois dans la version CVS d'Emacs, comme l'option
--daemon d'Emacs qui permet de le faire tourner en mode serveur.
L'essayer, c'est l'adopter, en plus sous Debian, il suffit d'installer les paquets Debian de Romain Francoise :
deb http://emacs.orebokech.com sid main
Ils sont marrant les codes de retour des serveurs SMTP d'AOL :
550 We would love to have gotten this email to mamanours@aim.com.
But, your recipient never logged onto their free AIM Mail account.
Please contact them and let them know that they're missing out on
all the super features offered by AIM Mail. And by the way,
they're also missing out on your email. Thanks.
Lors de la sortie d'OpenBSD 4.4, j'avais été choqué de lire dans l'interview de Kurt Miller que leur OS n'était toujours pas capable de faire du PIE. Pour ceux à qui ça ne leur dirait rien, c'est une option du compilateur permettant de rendre le code totalement "déplacable" dans la mémoire : toutes les instructions sont relatives (comme c'est le cas dans les bibliothèques), aucune adresse n'est marquée en dure.
Ainsi, lorsqu'un processus est lançé, on peut placer toutes les sections du binaire à des adresses aléatoires. Cela permet de boucler la boucle dans toutes les protections mémoires : l'ASLR est complète, protections NX, PaX, W^X, mise en lecture seule de la GOT & Co. Autant dire que la tâche est beaucoup plus compliquée pour exploiter un buffer overflow, à vrai dire, à part un off-by-one chanceux, je ne vois pas comment exploiter ça (vous avez le droit de m'envoyer vos idées).
Bon, tout ça pour en revenir à OpenBSD qui se dit être l'OS le plus sécurisé et tout ça et annoncer aujourd'hui qu' ils commencent tout juste à avoir une toolchain complète supportant le PIE. Ca me fait penser aux affaires dans le passé où on s'est rendu compte que W^X ne s'appliquaient pas à toutes les sections, etc.
Conclusion : A false sense of security is worse than a true sense of insecurity.
Astuce du jour (ou de l'année vu ma fréquence de posts) pour vsftpd qui n'est pas capable d'écouter à la fois en IPv6 et en IPv4. La solution, c'est de savoir que c'est pas possible.
Il faut en fait passer par (x)inetd qui n'a pas de telle limitation et qui passera la main() à vsftpd en temps voulu.
Faisons une constation assez simple : si votre lecteur portable (tournant sous Rockbox bien évidemment) a un disque de grande capacité, vous l'avez chargé une fois et vous tournez avec la même musique depuis maintenant 4 mois car vous avez la flemme de faire le DJ.
On va donc emprunter une fonctionnalité qui parait-il se trouve sur Itunes : remplir son lecteur avec des fichiers complétement aléatoires.
Ce qui donne le script (zsh) suivant :
#! /bin/zsh
setopt extendedglob
MUZBUS="\/media\/muzbus"
MUSIC="/music"
muzfiles=($MUSIC/**/*mp3(.))
fillme=$(df "${(Q)MUZBUS}" | awk -F" " "/${MUZBUS}/ { print \$4*1024}")
zmodload -F zsh/stat b:zstat
i=0
while [ "$fillme" -gt "0" ]; do
rndfile="$muzfiles[(($RANDOM % $#muzfiles))]"
size=$(zstat +s "$rndfile")
fillme=$((fillme - size))
print -l -- "$i -- $rndfile"
cp -- "$rndfile" "${(Q)MUZBUS}/music/"
((i++))
done
Attention ! Ne lançez pas ce script sous Debian, ils ont quelques problèmes d'aléa :)
Je suis en train d'évaluer quelques distributions dîtes sécurisées, et la première à laquelle je me suis intéressé est Gentoo Hardened.
C'est la distribution qui semble la plus "maintenue", avec une quantité de "paquets" importante et une base d'utilisateurs importante, sa communauté semble bien étoffée par des personnes telles que Solar Designer ou même pageexec.
De plus, pas mal de personnes que je respecte utilise cette distribution, ca doit pas être si mauvais ?
Attention, j'ai essayé de tester le truc en restant en mode non-troll, j'ai vraiment essayé, je le jure... Mes critères de jugement ont été les suivants : imaginons que je sois le sysadmin d'une moyenne entreprise avec un parc d'une trentaine de serveurs hétérogènes en architecture, modèle, technologie (une pré-image d'installation unique est donc impossible).
Le seul critère (subjectif) qui compte, c'est l'efficacité du truc.
Installation
Wahoo. Comment dire, si on vient du monde Linux (par opposition aux installs BSD), l'installation est loin d'être une promenade de santé, tout est très spartiate.
Autant il est facile d'installer une Debian en moins de 20 minutes, autant c'est impossible avec une Gentoo. Quand bien même c'était ma 3ème installation comparé à la centaine de Debian que j'ai pû mettre en place, il est impossible de faire aussi efficace qu'un Debian-Installer (mon seul référentiel).
Et puis tout irait bien si ça c'était bien passé, ça aurait été trop facile. Eh ben non! Tout a pété avec leurs maudits "Broken packages" ou "Masked package". Heureusement, je testais dans une machine virtuelle donc j'étais confortablement installé dans mon fauteuil, à une température correcte, en tee-shirt+caleçon (oui, c'est mon bleu de travail favori) et surtout, j'avais un navigateur Web pour regarder la documentation, bug reports et mailing list. Je n'imagine même pas en salle machine, coinçé entre deux rangées de baies où les ventilateurs expulsent l'air chaud dans le dos alors que je tape sur un KVM merdique mi-azerti, mi-dvorak, mi-stupide (oui ça fait 3/2 tout ça, mais les KVM ont un nombre bizarre de touches).
À l'issu de l'install, je me réconfortais en me disant qu'au moins, j'aurais vraiment le strict minimum installé.
localhost ~ # df -h
Filesystem Size Used Avail Use% Mounted on
/dev/hda1 37G 2.4G 33G 7% /
udev 10M 100K 10M 1% /dev
shm 60M 0 60M 0% /dev/shm
Oups. Disk usage failed! WTF? J'imagine que ce sont les sources, portage ou je ne sais quoi qui sont supprimables sans problème, mais je suis pourtant sûr d'avoir suivi le Gentoo Handbook à la lettre (sinon je m'en sortais jamais), comment est-ce possible d'en arriver à 2.4 Go !
Dans les trucs qui choquent encore, c'est que la liste des terminaux graphiques reconnus est vraiment "light", si vous vous connectez en ssh à partir d'un terminal rxvt-unicode, vous vous retrouverez avec un shell ne permettant pas d'utiliser vim, quelques shortcuts comme ^L, etc. Ca coûte rien qu'ils soient installé par défaut for god sake!
Passons à la configuration.
Configuration du système
Conf système et réseau
Le réseau... Comment on configure ce truc? Me dites pas que... Bienvenue dans les années 70, avec les adresses, routes et gateway dans des variables d'environnement sourcées par les scripts /etc/rc*.
Et si! Il est vrai que sur un serveur, c'est peut-être largement suffisant, mais si on considère le cas d'un routeur, ou d'un serveur un peu bizarre (machines virtuelles) avec des bridges et vlans c'est ingérable. On en revient alors à écrire un script qui fait tout ça, mais c'est tout autant ingérable, le /etc/network/interfaces que je connais sous Debian est irréprochable sur ce coup, en particulier quand on a lu sa doc.
La création d'utilisateur est resté BSDienne avec un useradd où il faut connaître par coeur toutes les options de ligne de commande sous peine de revenir éditer les fichiers passwd et shadow à la main. Le adduser Debian est peut-être écrit en Perl, mais il est pratique.
On voulait un système durçi, va falloir recompiler le noyau pour activer toutes les options de sécurité (PaX, Grsecurity, SELinux). C'est là où je me dis que finalement, make-kpkg, c'est vachement bien : en tant qu'administrateur conscencieux, on aurait compilé le noyau du serveur sur une autre machine et on aurait utilisé un scp tout crassou vers le serveur après ? Holly sh*t. Y a des tas de façons de se louper quelque part...
Mais en bon seigneur, j'avoue avoir bien aimé le /etc/modules.autoload.d/ qui permet de spécifier les modules à charger au boot, simple, clair, efficace.
Light is right, uh?
Ouch, quel sens du mauvais goût ! Le seul éditeur texte qui est installé par défaut est nano, ok, il y a toujours la vieille querelle vi-emacs, en tant qu'utilisateur des deux, je hais nano, passons.
Travail de base, protégeons au minimum la machine en écrivant quelques règles de firewall :
# iptables
bash: iptables: command not found
Youpi! Quand je vous disais que c'était une installation light! Y a plus qu'à downloader les sources et dépendances, heureusement que c'est pas un Windows XP SP1 branché en live sur un modem ADSL, sa durée de vie serait pas longue...
Ça permet alors de se faire une première idée du système de package, emerge. C'est un autre style : y a des smileys partout, c'est super verbeux, y a des jolis choix de couleurs (non c'est une blague).
Vu que j'y comprends rien, je me mets à lire la page de manuel et qu'est-ce qu'on peut lire : Les dépendances inverses ne sont pas gérées, si je comprends bien, je peux très bien supprimer la zlib sans qu'emerge ne s'en émeuve ? F34r.
Et on continue sur les rebondissements, on se retrouve à réaliser des workarounds tels que ceux-ci (indiqués dans le handbook) :
# emerge checkpolicy policycoreutils # FEATURES=-selinux emerge selinux-base-policy
Enfin ça, c'est ce qu'il y a marqué car je n'ai jamais réussi à déployer le bousin, j'obtiens toujours un truc comme ça :
localhost ~ # FEATURES=-selinux emerge selinux-base-policy
Calculating dependencies |
!!! All ebuilds that could satisfy ">=sys-apps/checkpolicy-1.30.12" have been masked.
!!! One of the following masked packages is required to complete your request:
- sys-apps/checkpolicy-1.34.4 (masked by: package.mask, ~amd64 keyword)
/usr/portage/profiles/default/linux/package.mask:
# Shouldn't be merging these SELinux packages on this profile
# but this keeps repoman happy since they require >=glibc-2.4
# 20061009 pebenito
- sys-apps/checkpolicy-1.34.3 (masked by: package.mask, ~amd64 keyword)
- sys-apps/checkpolicy-1.34.0 (masked by: package.mask)
For more information, see MASKED PACKAGES section in the emerge man page or
refer to the Gentoo Handbook.
(dependency required by "sec-policy/selinux-base-policy-20070928" [ebuild])
J'ai beau eu modifier plusieurs fichiers, je tombe toujours sur une erreur fatale. Alors que j'ai suivi toute la procédure.
Je vous laisse le meilleur pour la fin, la gestion des mises à jour des fichiers de configuration expliquée par la page de manuel :
When Portage installs a file into a protected directory tree like /etc, any
existing files will not be overwritten. If a file of the same name already
exists, Portage will change the name of the to-be-installed file from 'foo' to
'._cfg0000_foo'. If '._cfg0000_foo' already exists, this name becomes
'._cfg0001_foo', etc. In this way, existing files are not overwritten, allowing
the administrator to manually merge the new config files and avoid any
unexpected changes.
Soyons honnête, heureusement qu'il existe des outils qui aident comme l'indique le man :
Tools such as dispatch-conf, cfg-update, and etc-update are also available to
aid in the merging of these files. They provide interactive merging and can
auto-merge trivial changes.
Finalement, ce test qui devait être "juste" s'est transformé en un joli bash en règle alors qu'il y a plein de trucs intéressants dans cette distribution. Désolé.
Période de recrutement oblige, c'est le moment de remettre au gout du jour son CV, sauf que dégainer OpenOffice juste pour ça m'embarassait quelque peu...
Ca faisait longtemps que je cherchais une classe LaTeX belle, pratique et structurée et je l'ai enfin trouvé : moderncv, je vous laisse voir un exemple de CV.
La killer-feature, c'est le support de la bibliographie BibTeX, bien pratique pour lister les publications.
L'essayer, c'est l'adopter.
$ cat > fakegetpid.c
#include <sys/types.h>
#include <unistd.h>
pid_t getpid(void) {
return 1;
}
^D
$ gcc -shared fakegetpid.c -o fakegetpid.so
$ LD_PRELOAD=$PWD/fakegetpid.so ssh-keygen -t rsa -N '' -f
% ssh-keygen -f foobar -t rsa -N ''
Generating public/private rsa key pair.
Your identification has been saved in foobar.
Your public key has been saved in foobar.pub.
The key fingerprint is:
a9:65:93:0d:02:1d:e4:43:03:da:06:ab:24:73:13:7e foo@bar
% ssh-keygen -f foobar -t rsa -N ''
Generating public/private rsa key pair.
foobar already exists.
Overwrite (y/n)? y
Your identification has been saved in foobar.
Your public key has been saved in foobar.pub.
The key fingerprint is:
a9:65:93:0d:02:1d:e4:43:03:da:06:ab:24:73:13:7e foo@bar
Les deux fingerprints sont identiques !
Donc si je résume, la seule graine d'aléa est en fait le PID du processus. Ce qui signifie qu'il n'existe que 2^32 bits possibilités de clef sur x86, bruteforcons... pendant 400 ans.
$ cat > fakegetpid.c
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
pid_t getpid(void) {
pid_t fakepid;
fakepid = atoi(getenv("FAKEPID"));
return fakepid;
}
^D
$ gcc -shared fakegetpid.c -o fakegetpid.so
% export FAKEPID
% for FAKEPID in $(seq 0 $((2**32))); do
LD_PRELOAD=$PWD/getpid.so ssh-keygen -t rsa -N '' -f foo.$((FAKEPID)) |grep foo@bar
done
70:e2:6b:54:e8:46:b7:64:b7:9a:d6:a8:5d:3e:41:2f foo@bar
65:23:e0:30:76:cb:9c:f6:a9:72:64:1c:f0:4d:90:b9 foo@bar
fd:21:36:80:2b:df:ac:e8:09:7a:2d:62:cc:38:88:ec foo@bar
17:e5:ba:34:97:1d:2f:63:be:0a:7e:25:eb:3c:b0:fb foo@bar
bd:6f:c2:ca:3f:ad:49:d1:4b:20:ac:6f:27:35:5a:0d foo@bar
a6:9b:60:e0:ce:13:9b:68:6a:36:60:3e:60:82:62:2c foo@bar
ca:d7:2f:8f:c0:42:12:df:d2:5f:78:41:86:6e:63:0e foo@bar
29:ea:08:3a:61:91:55:e9:cb:93:46:b2:55:cc:87:e6 foo@bar
b5:6d:f1:3f:47:ce:ab:11:d1:1a:6f:0f:e6:a5:04:8d foo@bar
13:c2:e7:0f:f1:cf:a8:22:8f:7b:a4:b0:f3:83:64:25 foo@bar
Ensuite, vous loadez toutes ces clefs dans votre ssh-agent et boum!
Update@23:04: H D Moore s'en mêle et a eu la même idée, sauf que lui n'a pas oublié que les PID étaient sur 15 bits et pas sur 32 bits, soient 32 768 possibilités ce que j'avais réussi à calculer en quatre heures (j'ai pas 31 Xeon moi !).
Pour ceux que ça intéresse, je suis sur le point d'avoir les clefs pour 0 < PID < 300 000. Ok, ca n'a aucun intérêt.
OMG ! Le DSA-2008-0166 qui vient de sortir est peut-être l'un des pire jamais existé. Sa conclusion est assez claire :
It is strongly recommended that all cryptographic key material which has
been generated by OpenSSL versions starting with 0.9.8c-1 on Debian
systems is recreated from scratch.
Si on fait un interdiff avec la version précédente, on obtient ça :
diff -u openssl-0.9.8c/crypto/rand/md_rand.c openssl-0.9.8c/crypto/rand/md_rand.c
--- openssl-0.9.8c/crypto/rand/md_rand.c
+++ openssl-0.9.8c/crypto/rand/md_rand.c
@@ -271,10 +271,7 @@
else
MD_Update(&m,&(state[st_idx]),j);
-/*
- * Don't add uninitialised data.
MD_Update(&m,buf,j);
-*/
MD_Update(&m,(unsigned char *)&(md_c[0]),sizeof(md_c));
MD_Final(&m,local_md);
md_c[1]++;
diff -u openssl-0.9.8c/debian/changelog openssl-0.9.8c/debian/changelog
--- openssl-0.9.8c/debian/changelog
+++ openssl-0.9.8c/debian/changelog
@@ -1,3 +1,19 @@
+openssl (0.9.8c-4etch3) stable-security; urgency=high
+
+ * Re-introducing seeding of the random number generator. Patch from the
+ maintainer.
+
+ -- Florian Weimer <fw@deneb.enyo.de> Thu, 08 May 2008 01:58:40 +0200
+
WTF ? Pourquoi le maintaineur Debian modifie le code en lui-même ? Autant je comprends qu'il le fasse quand ça l'arrange pour le packaging, mais ce n'est pas son rôle de "corriger" le code tout seul comme un grand. Tout pour ça pour corriger un bug esthétique !
J'entends d'ici Theo De Raadt qui rigole.
Ubuntun, rigolez pas, vous êtes autant vulnérable.
Ce récit d'un sauvetage de système me fait un penser à la bourde qu'il m'était arrivée il y a quelques mois en cassant libssl à distance.
Dans les bonnes pratiques de l'admin, installez toujours busybox-static sur chaque serveur, vous ne le regretterez jamais...
Certains osent aussi dire qu'il faut toujours avoir une backdoor SSLifiée statique. Ca me rappelle un serveur qui avait compilé ce genre de truc sur une très ancienne version d'OpenSSL et qui n'avait jamais mis à jour sa backdoor...
De plus en plus de constructeurs s'intéressent à l'ouverture de leurs produits sur des plateformes libres, chaque semaine, nous entendons des nouvelles du type "Des spécifications ont ou vont être libérées" (Via, AMD, Intel et Xorg, etc) "Un développeur vient de rejoindre le constructeur X", etc.
Aujourd'hui, c'est un développeur qui est débauché par Atheros pour intégrer le support des célèbres cartes Wifi dans le noyau upstream. Il est vrai que la moitié des annonces d'ouverture des constructeurs ne débouchent pas forcément sur quelque chose de concret mais les derniers mois ont de quoi nous réjouir : on a de vrai drivers Xorg pour les cartes Intel et ATI, le support des cartes Wifi s'améliorent de jour en jour (les Intel avec leur nouvelles piles iwlwifi, le projet ath5k, etc.), la gestion de l'énergie fait des bonds en avant avec la publication des spécifications ACPI de certaines cartes mères, etc.
Question trollesque : Y a t'il un effet Vista ? Dans la mesure où les constructeurs sont désormais obligés de payer^Wcertifier leurs drivers et que personne ne veut de Vista, est-ce que les constructeurs n'espéraient pas faire développer leurs pilotes par la communauté pour baisser les coûts (non je ne crois plus à la philantropie) ?
Y a t'il un rapport avec une déclaration qu'avait fait Dell ou HP annonçant que leur matériel sera totalement supporté sous Linux ?
J'ai enfin recompilé tous les paquets Debian avec les fonctionnalités de "protection de code" activées (stack guard, prévention de formats strings, mise en read-only de sections ELF et génération d'un binaire PIE). Bref tout ce qui vous rend très confiant si vous tournez sous un noyau PaXé.
Puisqu'un bon parano n'utilisera pas un repository tier et recompilera ses propres packages, j'ai documenté la procédure de recompilation ici. Pour les autres qui me truste :
server$ gpg --export nico@chdir.org| sudo apt-key add -
server# echo "deb http://debian.chdir.org/debian/ stable/" >> /etc/apt/sources.list
server# apt-get update
server# apt-get upgrade
Vu que je l'utilise en production, je devrais le tenir très à jour. Si vous avez des remarques sur le document ou des idées de flags à rajouter...
Pourquoi ne pas utiliser Google Mail ? Par pure paranoïa, mais c'est trop bête de se passer de plusieurs gigaoctets d'espace libre non ? Autant s'en servir comme mécanisme de sauvegarde, avec l'aide de procmail, GnuPG et MIME-construct on peut faire tout ce qu'on veut :)
Pour forwarder les mails que vous recevez vers un autre compte, vous pouvez tout bêtement utiliser procmail avec une règle "pipant" les messages dans GnuPG comme cela :
:0c
| gpg -r mamanours@gmail.com --encrypt | mail -s "Bla" mamanours@gmail.com
Le problème est que vous recevez les mails chiffrés, certes, mais complétement détruits, votre MUA ne l'interprète plus comme un mail mais comme une suite d'octets au déchiffrement, donc si le message est codé en Quoted Printable, il ressemble plus ou moins à de la boue au final, et je ne vous parle même pas de la tête que font vos pièces jointes qui ne sont plus manipulables sans reconstruire les parties MIME avec un logiciel tier.
Non, la solution, c'est d'implémenter la même logique qu'un vrai MUA : forwarder les mails avec du MIME, et chiffrer le résultat avec du MIME encore :
#! /bin/bash
TMPCLAIR="$(mktemp)"
FINALADDR="nico@chdir.org"
TXTINTRO="$HOME/.etc/introduction_forward-me-gpgified"
### ALWAYS wipe the $TMP
trap "wipe -qsf -- $TMPCLAIR" TERM QUIT EXIT
mime-construct --part-header 'Content-Disposition: inline' --type 'message/rfc822' --file - --subpart --output > "$TMPCLAIR"
gpg -r "$FINALADDR" --encrypt < "$TMPCLAIR" | mime-construct --multipart \
'multipart/encrypted; protocol="application/pgp-encrypted"' \
--type 'application/pgp-encrypted' --file "$TXTINTRO" \
--type 'application/octet-stream' --file - \
--to "$FINALADDR" --subject "$RANDOM"
Avec un fichier $HOME/.etc/introduction_forward-me-gpgified contenant juste :
Version: 1
Et votre règle Procmail ressemblant à :
:0c
| forward-me-gpged-mail
Désormais, lorsque votre MUA ouvre un mail forwardé, il interprète correctement les en-têtes du message (codage, chiffrement s'il y en a encore, etc.) et normalement, les pièces jointes sont directement accessibles (pas eu le temps de tester).
Note: Donc pour ceux qui ont le mauvais goût de forwarder leurs mails corporate vers Gmail, utilisez au moins quelque chose dans ce goût là!
Mais pourquoi je ne l'ai pas fait avant ? C'est la question que je me pose depuis que j'ai redémarré mon Sandisk Sansa e280 après avoir mis un firmware Rockbox à la place du truc officiel qui était très... "girly" pour rester poli.
Désormais l'interface est réactive, tout est configurable (par exemple, pourquoi est-ce que l'ancien tenait tant à garder la roulette allumée ?), y a plein de jeux et d'applications (par exemple un métronome ! Inutile donc indispensable non ?) et je n'ai plus de bugs. Le plus difficile en fait, c'est d'oublier ses réflexes, oublier le fait que l'interface va réagir en 3 ms au lieu de 30 et donc ne pas anticiper ce qu'on compte faire !
En plus, l'installation est triviale en suivant le manuel Sansa e200 ! Si votre lecteur est supporté, sautez le pas, ca vaut le coup ! Ok, je dis ça mais j'ai pas encore vérifié la durée de la batterie de 15h30 annoncée (d'après les spécifications commerciales de SanDisk, ca devrait tenir ~20h), mais il semblent que les développeurs tentent de l'optimiser encore plus.
Si vous voulez plus de détails, allez voir son status sur le Wiki et si vous cherchez un lecteur MP3, faîtes un tour sur le guide d'achat listant comment les modèles sont supportés.
Petit moment de nostalgie lorsque j'ai voulu tester Weave, cette extension, prometteuse, nécessite Firefox 3 (beta), ça m'a alors rappelé l'époque où on attendait fébrilement chaque Milestone du projet Mozilla. Ces gros binaires qui apportaient à chaque fois des tas de nouvelles fonctionnalités (ou des bugs) étaient toujours attendus avec impatience. Ca c'était sympa, surtout avec une connexion 56K!
C'était un peu Noël à chaque release. C'était beau.
Et puis toute cette tristesse pour rien puisqu'il n'y a pas de binaire de
Firefox3 pour AMD64 de prêt et j'ai pas envie d'installer tous les paquets
ia32-* juste pour 4 minutes de test. Vous me raconterez ?