[Atom] [Mail] [Twitter]
Liens : git · hacks · divers · cabale · buzz! · à propos +
Au menu
\/

bluestorm, Emily, et les chameaux

#. Par bluestorm dans Réactions. Mis à jour le 27.02 2010 à 12:08. 3 commentaires.
>. L'innocence est un mythe : les programmes fonctionnels nécessairement impurs
caml capabilities emily langages pola réaction sécurité

Il était une fois un gars sans blog, mais qui voulait publier des choses. Un autre, qui avait un blog (quoique primitif, sans commentaires, sans JavaScript et sans Flash, OMG), vint, et lui proposa astucieusement d’héberger son contenu. Shazam !

Voici donc le premier billet de bluestorm, qui relate ses aventures dans le monde merveilleux des bêbêtes sous haute sécurité (et des concepts liés, bien évidemment), avec l’exemple d’Emily, une belle chamelle s’il en est (et rien à voir avec le modèle de mes dessins). —rz0

C’est ma première réaction. Wouhou ! Je suis débutant, merci d’être indulgent. Comment choisir le paper auquel réagir le premier ? J’ai commencé par rédiger une liste des papers que j’avais envie de traiter, en me promenant au hasard dans mon répertoire ~/Papers, et maintenant je prends arbitrairement le premier de la liste pour me forcer à commencer.

Le paper est How Emily Tamed the Caml (PDF, 16 pages). Il concerne la sécurité informatique, domaine que je connais très mal, et plus précisément une approche qui me fascine : le principe du moindre privilège (POLA, Principle Of Least Authorithy), et la capability-based security.

En deux mots (je vais développer un peu plus ensuite), la question que pose l’article est la suivante : comment faut-il modifier un langage de programmation généraliste pour lui faire respecter les principes du POLA ? On prend un langage de programmation généraliste (ici OCaml), et on le domestique (tame) en lui retirant toutes les fonctionnalités qui cassent le POLA ; un programme écrit dans le langage domestiqué donne donc des garanties de sûreté nettement plus fortes.

Je connais très mal le domaine de la sécurité informatique, donc il faut prendre tout ce que je dis avec prudence. Il y a certainement des imprécisions ou des erreurs dans ce que je vais dire. Si cela vous a intéressé, n’hésitez surtout pas à laisser un commentaire (constructif si possible), mail (note d’édition : bluestorm@, chez GMail, gmail.com, pour ceux qui ne sauraient vraiment pas) ou autres.

POLA, capability-based security

Si vous connaissez déjà tout ça, pas la peine de lire mon introduction, sautez directement aux deux derniers paragraphes de cette réaction, qui résument le contenu du papier.

Privilèges, POLA

On appelle privilège la possibilité de faire quelque chose sur l’ordinateur. Un utilisateur dispose par exemple du droit de renommer ses fichiers, ou d’en ajouter de nouveaux dans son répertoire personnel. Il n’a pas forcément tous les droits, par exemple s’il n’est pas administrateur de la machine il n’a pas forcément le droit d’installer des logiciels ou changer la configuration du système.

Dans la plupart des systèmes actuels, un programme est affilié à un utilisateur (la personne qui l’a lancé) et hérite exactement des droits de l’utilisateur : il a le droit de modifier les fichiers du répertoire personnel, mais pas de modifier la configuration du système. S’il avait plus de droits que l’utilisateur, ce serait une faille de sécurité : il pourrait par exemple modifier la configuration du système pour se lancer au démarrage et se répliquer sur le réseau (c’est comme ça que fonctionnent les virus).

Quand on y pense, il n’est pas forcément normal que chaque programme lancé par l’utilisateur ait accès à tous les privilèges de l’utilisateur. Par exemple si je lance un programme pour me donner l’heure qu’il est, il n’a pas besoin du droit de supprimer des fichiers dans mon répertoire, et s’il essaie de le faire c’est sans doute une erreur de programmation, ou carrément un programme malicieux fournit par un méchant programmeur qui essaie de me faire croire qu’il affiche l’heure pour effacer mes données personnelles. Dans les systèmes d’exploitations modernes, il est donc possible de restreindre les droits de certains programmes.

Le POLA est un principe qui résume cette approche : chacun doit avoir à sa disposition exactement l’ensemble de privilèges dont il a absolument besoin pour faire son travail, et rien de plus.

Lien

Granularité

C’est un principe enfantin qui n’est pas appliqué complètement par les systèmes d’exploitations actuels. En particulier les systèmes dérivés de UNIX utilisent des dérivés de l’approche ugo, où l’on attribue les droits selon un découpage utilisateur/groupe (certains utilisateurs ou groupes d’utilisateurs ont des droits spécifiques sur certains fichiers/programmes/outils), qui est une distinction beaucoup moins fine. Il y a eu des améliorations depuis les premiers temps d’UNIX, mais à ma connaissance aucun système grand public ne respecte vraiment les principes du POLA à un niveau suffisamment fin.

Parce que l’on peut appliquer le POLA à un grand nombre de niveau. Au niveau des utilisateurs, c’est grosso-modo ce que font les administrateurs systèmes consciencieux aujourd’hui. Au niveau des programmes, c’est déjà nettement plus délicat. On pourrait même appliquer le POLA à l’intérieur des programmes en assignant des droits différents aux différents modules et composants logiciels du programme (la couche GUI aurait des droits d’affichage, et pas le reste, par exemple). C’est ce que permettent les langages capability-based.

Il y a donc une idée de granularité : dans l’absolu tout le monde est d’accord sur le fait que le POLA est la meilleure approche de la sécurité, mais jusqu’à quel niveau de détail on peut l’appliquer ?

Capabilities

Les capabilitiesα sont une autre idée qui est fortement reliée au POLA. Elles ne sont pas nécessaires pour construire un système qui respecte le POLA, mais leur élégance fait que les gens qui travaillent dans ce domaine les utilisent très souvent.

Dans les systèmes d’exploitation et les langages actuels, on fait une distinction très nette entre une action, et l’autorisation de faire cette action. Par exemple, n’importe quel programme peut exécuter la fonction qui lit le contenu d’un fichier, il suffit de donner l’adresse du fichier sur le disque. Cependant, cette fonction va parfois échouer si le programme n’a pas les droits nécessaires pour lire ce fichier, et renvoyer une erreur. Le « moyen d’accès » au fichier est son adresse, et il y a une phase de sécurité séparée.

L’idée des capabilities est que le moyen d’accès et le droit d’accès peuvent être réunis en une seule et même entité. Une capability est un objetβ qui contient à la fois la méthode pour faire une action et les droits pour l’effectuer. Si le système donne à un programme la capability « lire le fichier machin », le programme peut l’utiliser pour lire le fichier, ou bien la donner à un autre programme qui aura à son tour le pouvoir de lire le fichier. S’il n’a pas reçu cette capability, le programme n’a pas le droit de le lire, mais il n’a même pas le moyen concret d’essayer de le lire.

α : Je n’ai pas trouvé de traduction en français qui me plaise, je ne sais pas si "capacité" convient.

β : Je parle ici d’objet au sens large et ça n’a aucun rapport avec la Programmation Orientée Objet.

Lien

Rôle des langages de programmation

Support par le système

On a déjà écrit des systèmes d’exploitation miniatures basés sur le concept de capabilities ; par exemple dans le projet EROS/CaprOS. C’est un noyau de système d’exploitation.

Le problème c’est que l’approche par capabilities est radicalement différente des méthodes des systèmes actuels, et il est très difficile d’assurer la compatibilité entre un système d’exploitation capability-based et un logiciel développé pour un système grand public : lui s’attend à ce qu’on lui donne des droits sur tout et n’importe quoi, et si on le fait on perd les bénéfices en matière de sécurité ; il faudrait donc ré-écrire en profondeur le logiciel pour qu’il respecte le POLA. Concrètement, ces projets de recherche ne sont donc utilisés par essentiellement personne parce qu’ils ne sont compatible avec aucun des logiciels existants, et l’effort pour les rendre utilisables serait énorme, bien supérieur au budget des équipes de recherche concernées.

Support par le langage de programmation

Il est cependant possible de mettre en place le POLA localement, au sein d’un programme. Il suffit essentiellement de restreindre l’interface entre le programme et le système d’exploitation (qui est laxiste et donne trop de droits) à une petite couche "administratrice" (qui détient tous les droits du programme), qui se charge de répartir ces droits aux autres composants du programme sans leur en donner trop.

Cela limite un peu le cadre de la chose puisque c’est le programmeur qui s’occupe de sécuriser son propre programme. On ne peut pas faire confiance par exemple à un méchant pour écrire ses programmes de cette manière, il ne va pas se tirer une balle dans le pied ! Cela peut toujours être utile dans le cas où on propose au méchant de coder quelque chose pour notre propre programme : si son code est inclus dans une partie sécurisée, et que la sécurité est vérifiée par le compilateur, il ne peut pas faire de bêtises. C’est aussi utile pour les erreurs qui ne sont pas volontaires mais accidentelles : si on a un bug dans une partie du programme, ça peut mal se passer, mais il ne fera rien qui lui est interdit. S’il y a par exemple une vulnérabilité dans une partie du code qui permet à des attaquants de faire des actions non prévues, ils seront limités par le peu de droits dont dispose cette partie du code, donc c’est très intéressant.

Pour avoir un tel support au sein du programme, il faut des langages de programmation pensés pour. Le langage le plus connu dans ce domaine est E.

Il faut d’une part que le compilateur du langage puisse vérifier que la sécurité est bien respectée (qu’une partie du code qui n’est pas censée lire le contenu de fichiers ne puissse pas quand même demander au système d’exploitation de le faire), et d’autre part que les fonctionnalités du langage ne permettent pas d’écrire du code qui casse cette protection. Par exemple, si une partie du programme peut écrire en mémoire la clé d’accès au contenu du fichier, une partie qui n’est pas censée lire de fichier mais peu lire dans la mémoire peut utiliser cette clé et outrepasser ses droits, sans que le compilateur puisse s’en rendre compte et signaler l’excès de privilège.

Lien

Cas d’Emily

Ce que présente le papier cité c’est la transformation d’un langage généraliste, qui n’a pas été pensé à la base pour respecter le POLA, en un langage sécurisé. Il s’agit essentiellement de retirer toutes les fonctions « dangereuses » de la bibliothèque standard, en les remplaçant par des équivalents « sécurisés » qui rendent explicite les capabilities nécessaires. Par exemple la fonction open_out de Caml, qui permet d’ouvrir un canal en écriture vers n’importe quel fichier, est retirée et n’est plus accessible à l’ensemble du programme. Seule la petite couche d’interface avec le système peut créer des canaux à volonté, et les autres parties du programme doivent lui demander pour recevoir un canal, ou plutôt la capability correspondante, qui encapsule dans un record le canal et les fonctions d’entrée/sortie qui y sont liées.

Le papier décrit donc d’une part les modifications apportées à la bibliothèque standard OCaml, d’autre part la découpe entre la partie « toute puissante » du programme qui a tous les droits donnés par le système, et les parties sécurisées : la partie « toute puissante » doit être la plus petite et la plus simple possible pour ne pas comporter d’erreurs/failles. Il présente des exemples de programmes sécurisés, programmes en ligne de commande ou programmes avec GUI. Il discute aussi les impacts de cette transformation sur le style de programmation, ou les performances des programmes écrits de cette manière.

Pour résumer, je trouve que cet article est une bonne introduction aux problématiques de sécurité d’un langage de programmation. Il est très accessible, n’approfondit pas énormément et ennuirait sans doute un connaisseur du sujet, mais pour un inculte comme moi ça a constitué une lecture agréable.

Lien

[ tag:blog.huoc.org,2009:posts/19 ]
Voir les commentaires · Commenter

/\ \/

shutdown, Emacs, et Firefox

#. Par rz0. Publié le 03.08 2009 à 01:12. Aucun commentaire.
administration emacs firefox

Depuis quelques temps déjà, Emacs 23 dispose de l’option --daemon, qui permet de lancer l’éditeur en tâche de fond. Les connexions s’y font alors avec emacsclient(1), comme avec l’ancien mode serveur. La différence avec server-start est qu’il n’est pas nécessaire d’avoir une frame toujours ouverte. Cela permet entre autre de garder sa session Emacs indépendante de son environnement graphique. Tout cela n’a été rendu possible, bien sûr, que grâce à l’arrivée du multi-tty, qui permet, comme son nom l’indique, à Emacs de se manifester sur plusieurs supports : X, console, etc.

Quel rapport avec shutdown(8) et Firefox, donc ?

Puisque je lance désormais Emacs directement lors de mon login(1) (quelques lignes qui vont bien, dans mon .profile) et que C-x C-c ne supprime plus le processus entier mais seulement sa manifestation sur un terminal donné, il paraît naturel de vouloir tuer Emacs à la fin de ma session.

Or, si je me connecte avec login, je quitte habituellement ma session en éteignant ma machine avec un sudo shutdown -p now. Au-delà des services gérés par rc(8), cette commande a pour effet d’envoyer un SIGTERM à tous les processus vivants. Cela fonctionne à merveille pour tous les programmes ne nécessitant aucune action à leur fermeture ou prenant adroitement en compte SIGTERM. Ce n’est malheureusement ni le cas d’Emacs, ni celui de Firefox, qui se terminent tous deux brutalement, en n’opérant pas la maintenance requise. En utilisant shutdown simplement de cette façon, je me retrouvais donc au démarrage suivant avec un Emacs mécontent de trouver un vieux fichier desktop et un Firefox grognant que la dernière session s’est terminée anormalement.

Il fallait donc trouver un moyen d’obliger Emacs et Firefox à quitter proprement, et ce depuis la ligne de commandes.

Pour Emacs, je n’eus pas trop de mal à trouver comment attacher une fonction ELisp à la réception du signal SIGUSR2 :

(defun my-sigusr2-handler ()
  (interactive)
  (kill-emacs))
(define-key special-event-map [sigusr2] 'my-sigusr2-handler)

Pour Firefox, en revanche, il fallut davantage peiner. La solution que j’ai finalement adoptée n’est sans doute pas la meilleure, mais elle a le mérite de fonctionner. Elle repose sur l’utilisation de MozRepl et de nc(1) (net/netcat dans pkgsrc) pour injecter du JavaScript dans l’instance de Firefox en cours. Le code JavaScript, trouvé dans un module Perl, est le suivant :

var app = repl.Ci.nsIAppStartup;
repl.Cc["@mozilla.org/toolkit/app-startup;1"].
    getService(app).quit(app.eForceQuit);

Après tous ces efforts, j’obtiens enfin un script shell permettant de tuer Emacs et Firefox en toute sérénité (à exécuter en tant qu’utilisateur) :

TIMEOUT=5
waitfor()
{
        while [ $TIMEOUT -gt 0 ] && /usr/bin/pgrep -U $LOGNAME $1 >/dev/null; do
                sleep 1
                TIMEOUT=$((TIMEOUT-1))
        done
}

# Emacs.
/usr/bin/pkill -USR2 -U $LOGNAME emacs
waitfor emacs

# Firefox.
/usr/pkg/sbin/nc localhost 4242 <<EOF >/dev/null
var app = repl.Ci.nsIAppStartup;
repl.Cc["@mozilla.org/toolkit/app-startup;1"].
    getService(app).quit(app.eForceQuit);
EOF
waitfor firefox

À moi les extinctions en une commande ! Encore une fois, on remarquera que c’est la paresse qui guide l’apprenti-administrateur à améliorer son système. :)

[ tag:blog.huoc.org,2009:posts/18 ]
Aucun commentaire · Commenter

/\ \/

Emacs 23.1 est là, pour les grands et les petits

#. Par rz0. Publié le 30.07 2009 à 17:08. Aucun commentaire.
emacs libre

Alors que les die-hard fanatiques de l’Église de Stallman ont sans doute déjà eu le temps de s’amuser avec cette vingt-troisième mouture d’Emacs durant les deux longues années de son incubation dans les caves du GNU, c’est-à-dire depuis la libération de sa grande sœur, la vingt-deux, les impurs et autres voyeurs occasionnels peuvent enfin aujourd’hui — depuis hier, en vérité — s’offrir, en toute sécurité, sans (trop de) risques de corruption et autres joyeusetés, l’occasion d’en admirer les formes nouvelles, plus fraîches et plus rondes.

Car l’argument de vente principal d’Emacs 23 sur ses prédecesseurs est assurément son esthétique. Sa robe GTK, qu’elle revêt maintenant par défaut, galamment accompagnée du nouveau lissage de ses polices par Xft et d’un jeu d’icônes remis au goût du jour, lui confère un charme qui rivalise sans complexes avec les petites jeunettes du marché. Quelques touches trahissent toutefois son âge, notamment si les yeux de l’innocent s’arrêtent sur sa ligne de modes traditionnelle ou devant son maquillage d'origine, devenu quelque peu ringard.

Passée cette première approche, et une fois installée, ses multiples atouts et sa flexibilité, fruits de trente ans d’expérience, sauront cependant, je suis certain, convaincre les plus difficiles, si ceux-ci désirent toutefois se laisser séduire.

En effet, Emacs aura su profiter de ces deux années de développement pour perfectionner son usage de la langue, faisant d’Unicode son nouveau terrain de jeu, et apprenant à s’exprimer dans plusieurs fontes simultanément.

Mais si certaines surprises telles que les multiples changements de l’API ELisp (par exemple au niveau des frames), le partage entre terminaux (multi-tty), ou l’invocation démoniaque, s’adressent aux initiés, Emacs 23 est avant tout, à mon sens, un pas de plus vers la masse de curieux qui n’ose pas se lancer dans l’aventure, et les nouveaux paramètres par défaut tels que l’activation transient-mark-mode ou encore l’apparition du word-wrap à la Notepad sont là pour nous le rappeler. Avis aux amateurs.

Je n’ai pas voulu paraphraser le fichier NEWS, mais n’hésitez pas à le consulter pour un bref aperçu des nombreux changements survenus depuis la 22.3, tous nus cette fois-ci, sans mes commentaires ! :)

À propos de GTK, que les inquiets se rassurent, aucune relation ne semble avoir eu lieu avec l’être GNOME ; par mesure de précaution, il faudra tout de même s’assurer de disposer d’une version de librsvg sans support du svgz qui traîne avec lui son lourd passé gnomiste. Pour les utilisateurs de pkgsrc, j’ai écrit quelques lignes à inclure dans le makefile du port graphics/librsvg pour obtenir l’option de ne pas dépendre de libgsf (-svgz).

[ tag:blog.huoc.org,2009:posts/17 ]
Aucun commentaire · Commenter

/\ \/

xmltools implementation: automata and backtracking

#. Par rz0 dans GSoC 2009 for NetBSD: xmltools. Publié le 20.07 2009 à 00:39. Aucun commentaire.
<. xmltools update: new I/O layer and further plans
>. xmltools: what's done, what's left
backtracking nfa parsing xmltools

At the moment, I’m implementing submatches in patterns, in preparation for xmlsed. Since most of what I do draws from formal languages and automata (except I’m too lazy to write anything formal), I’ve been looking into TNFAs for inspiration. Seeing how TRE seems to implement look-ahead without backtracking, I began to ask myself if such a thing could be done for my pattern matcher. Unfortunately, I can’t seem to figure out a solution by myself, so I’m blogging instead. :)

Basically, the problem is with constructs such as a[b]/c which match c, child of a only if a has a child b. However, when we reach a, we don’t know yet whether it has a child b or not, so we’re in need of some look-ahead.

This is akin to a(?=b)c in Perl regexes, but as you can already see, it’s fairly different. Perhaps the most obvious difference is that a tree has "two dimensions" while a string has only one, so it’s possible for a to have two children b and c, in a tree, while it’s not possible for a to be followed by two different characters, in a string.

Backtracking

The easiest way to solve this problem is to use backtracking. This is how the matcher is currently implemented. Even though about everything else is based solely on states and transitions, the part implementing look-ahead predicates uses backtracking.

The algorithm looks like this: everytime we have to match a look-ahead predicate, we stop, read as many nodes as we need to decide and then either drop the state or keep it, depending on the outcome.

This is a simple approach and it works well (i.e. it gives the expected results). Only, it’s slow. As a comparison, using the patterns I’ve used before for my benchmarks, the difference between hw/.="Ab\"a*cus" and p[hw/.="Ab\"a*cus"]# is the second one is about 2.66 times slower. This can be hand-optimized by rewriting the second pattern as body/p[hw/.="Ab\"a*cus"]#, with knowledge of the input format, where p can only appear as a child of body. This cuts the slowness to a mere 1.62 times slower.

At the same time, it demonstrates a major source of inefficiency in my backtracking implementation: loose (non-anchored) subpatterns, which may potentially apply to a great number of nodes yet would fail immediately for most of them, result in a lot of unwanted short backtracking segments where the matcher tries the subpattern and then immediately backtracks after failing, thus still examining the node twice.

Product automata

In theory, a pattern such as a(?=b)c matches if a is followed by both b and c so another natural idea would be to use a product automaton which transitions between couples of states: if we end up in two final states, then we win.

Only, this works well because we want to know whether the string matches as a whole. However, with an XML pattern such as a[b]/c, we need to identify which node matched the c part. This is where things start to get complicated.

Now we do know how to extract a submatch from a string with tagged transitions. So, great, does this apply to our XML matcher? The answer is "no", as far as I know (I’d be glad if someone proved me wrong, though). Tagged transitions are good at extracting one submatch, the last one, but in our case, the problem is we want all occurrences of c, not just the last one.

Keeping this information globally associated with the state is not an option since there may well be multiple instances of the look-ahead predicate trying to match at the same time. But trying to differentiate between two states based on the matching position is not an option either, because that could easily lead to linear memory usage. Consider, for example, the following XML fragment:

<a/><a/><a/><a/><a/>...<b/>

Trying to match {a%%b} (or (a%%b) using the current syntax in the master branch; sorry, I reverted to the old syntax because () will be used for groups) against that would result in a match at every a element. Hence, keeping the position as a state property is not a solution, since we’d have to distinguish between as many a nodes as there are in the input data.

Optimizing the backtracking method

Although the implementation of the matcher has undergone many changes in order to improve performances recently, mostly so as to accommodate new features while keeping a reasonable running time, I believe there’s still room for much improvement, maybe in the form of algorithmic enhancements rather than implementation optimizations.

Some of my more realistic ideas are:

  • Read one element ahead to reject some subpatterns without entering a backtracking context.

  • Try to predict the outcome of a look-ahead predicate and compute the more likely transitions along with the predicate itself, saving on backtracking (except to prune the tree) in case we’re right (but incuring additional recomputations if we’re wrong).

Also, this is not directly related to the backtracking approach, but I’m thinking of putting more information in the state cache; at the moment, we’re only caching "raw" transitions which account for the old state set and the direction (i.e. successor or child); we could try to cache local information as well, which would move us one step closer to the way NFA transition functions get cached to get DFAs.

Conclusion: do we need performance that badly?

Well, that’s a good question. And the answer is "we probably don’t". This is kind of my hobby, so don’t get the wrong idea. The whole thing is not that slow. On my simple example, xmlgrep was only 0.5s slower than libxml-powered xmlstarlet, taking less than six seconds to look up a word definition in a 58M dictionary, on my 2x2GHz Core 2, while using 100 times less memory.

I doubt anybody is going to use xmlgrep to look up words in dictionaries anytime soon; such a specialized task would best be served using an indexed collection of some sort, although I should mention that there are XML formats which are more suited to being parsed using my tools than others, so converting to a more appropriate (e.g. annotated) XML format using xmlsed then searching with xmlgrep could well be a viable solution too (given the conversion is one-time or infrequent compared to searches). More on that once xmlsed is out!

[ tag:blog.huoc.org,2009:posts/16 ]
Aucun commentaire · Commenter

/\ \/

Le Wifi du CROUS : guide de survie

#. Par rz0. Mis à jour le 20.02 2010 à 10:02. Aucun commentaire.
crous ensimag linux netbsd wifi

Arrivé sur Grenoble, j’étais tout content de découvrir que le CROUS m’offrait gratuitement l’accès à Internet par le biais de Renater et d’installations Wifi. J’ai vite déchanté en voyant la qualité de la connexion. Autant le débit est tout à fait acceptable pour une connexion partagée (il va de soi qu’en téléchargement montant vous n’avez rien ou presque, ceci dit), autant la stabilité de la connexion laisse tout à fait à désirer.

Ce petit guide sans prétention vous fait part de mon expérience avec ce réseau capricieux ainsi que mes petites astuces sur comment y survivre malgré tout.

Cet article ne s’adresse évidemment pas aux gens qui utilisent Windows, n’ayant pas Windows moi-même, sur mon portable, je ne saurais les conseiller.

Avant d’entrer dans le vif du sujet

Je tiens à préciser que ceci n’est pas un guide de configuration (mais plutôt de dépannage), parce que j’estime qu’il y en a déjà suffisamment sur la Toile, mais surtout parce que j’ai la flemme !

Afin de vous donner quelques pistes de recherche, toutefois, voici les programmes dont vous aurez besoin pour faire tourner la machine. Mieux vaut les avoir préparés avant d’atterrir sur le campus !

  • Un noyau qui supporte votre carte Wifi, c’est bête mais…

  • wpa_supplicant, pour établir la connexion avec les points d’accès du CROUS. En vérité, celle-ci s’opère sans authentification (déléguée au VPN), mais wpa_supplicant, malgré son nom, gère également les réseaux en WEP, ou sans sécurité aucune. Entre autres, il permet de gérer plusieurs réseaux alternatifs, ce qui permet de faire cohabiter votre réseau à la maison familiale, pour quand vous rentrez chez vous, avec celui de votre école (p.ex. l’Ensimag a son propre réseau), et celui du CROUS, par exemple.

    Vous pourriez être tenté d’utiliser quelque chose comme NetworkManager. Si tel est le cas, sachez que ce guide ne vous sera pas d’une grande utilité, car ce logiciel a tendance à masquer toutes les manipulations que je présente ici, et je ne saurais dire si les commandes que je donne auront les effets escomptés en présence de NetworkManager.

  • dhclient (ou un autre client DHCP), sans quoi vous aurez une connexion sans avoir d’IP…

  • vpnc, le client libre compatible avec les réseaux VPN de Cisco. Le client officiel, sous licence propriétaire, est à la fois instable et indisponible sous BSD.

  • OpenSSH, si vous souhaitez utiliser des tunnels (et si vous avez un serveur pour les héberger, celui de votre école peut faire l’affaire). Si votre utilisation d’Internet ne se limite pas au Web, vous en aurez sans doute besoin.

Le VPN (Very Private Network)

Il y a beaucoup de gens qui appréhendent l’usage de cette chose qu’est le VPN, alors qu’en vérité, les problèmes commencent après. L’usage du VPN est simple, il suffit de suivre les divers guides (disponibles pour Linux et Unix !) mis à votre disposition, ou de demander à quelqu’un du service informatique de votre école. Ou encore, plus simplement, il vous suffit d’installer vpnc (p.ex. via le gestionnaire de paquets de votre distribution Linux), et de récupérer les paramètres du réseau VPN, voire un fichier de configuration déjà fait (ne pas oublier de le convertir, s’il est au format Cisco VPN, avec pcf2vpnc).

La seule chose à laquelle il faut faire attention est, si vous utilisez un noyau compilé par vos soin : il faut activer le support du tunnel générique (TUN/TAP).

Limitations explicites du réseau

Officiellement, vous êtes encouragé à vous limiter à des activités purement scolaires au sein du réseau ; certains manuels sont plus indulgents et parlent de trafic personnel raisonnable. Il va de soi que je ne vous conseille pas de faire de gros téléchargements depuis le réseau du campus ; ce serait une perte de temps pour vous et un dérangement pour les autres.

Cependant, la tentative de contrôle imposée par l’administration du réseau, consistant à bloquer certains ports en sortie, peut être très gênante pour un nombre de choses utiles, notamment vous connecter en SSH à votre serveur à votre domicile familial, par exemple pour faire une sauvegarde de vos données importantes (on n’est jamais trop prudent). Le FTP ne marche d’ailleurs pas mieux.

13 juin 2009. Depuis quelques jours, j’ai remarqué que le port CVS est ouvert en sortie ; il est donc possible, par exemple, de mettre à jour son arbre de ports ou sa dernière version d’Emacs… Cela paraît d’autant plus aberrant que le port FTP est demeuré fermé.

Sessions et tunnels SSH

Si votre école vous offre un environnement moins restrictif (et c’est mon cas, avec l’Ensimag),α vous pouvez vous connecter en SSH là-bas pour ensuite faire vos petites manipulations. Ou vous pouvez créer un tunnel SSH. Si vous ne connaissez pas, il s’agit de l’option -L de la ligne de commande ou LocalForward du fichier de configuration.

Par exemple :

$ ssh -L 2806:chez.moi:22 telesun

α : 20 février 2010. Depuis fin janvier, l’Ensimag filtre également agressivement sur les ports en sortie. Entre autre, on ne peut plus utiliser ni FTP, ni CVS, ce qui s’avère très gênant pour la mise à jour de ma NetBSD… m’enfin, on se débrouille toujours.

sshd sur un autre port

Si vous avez un peu de contrôle sur votre réseau à votre domicile et que le port 80 n’est utilisé par rien d’autre, simplement faire écouter sshd sur celui-ci marche bien et le réseau du campus ne bronche pas quand vous parlez SSH sur le canal normalement réservé au HTTP.

Vous pouvez également utiliser le port 443, celui d’HTTPS, qui est également ouvert, sur le réseau du campus, si cela vous convient mieux. C’est ce que je fais.

Améliorations : clés SSH et ssh-agent

Honnêtement, si vous prévoyez d’utiliser massivement SSH, pour rediriger votre trafic sur une machine qui vous permet d’accéder à des services indirectement, je vous conseille vivement de vous créer une paire de clés publique/privée et un compte dédié sur votre serveur, acceptant ces clés, dénué de tout droit et servant uniquement à la mise en place du tunnel.

Une alternative, si l’idée d’un tel compte vous semble inacceptable, est d’utiliser ssh-agent, pour n’avoir à taper votre passphrase qu’une seule fois.

Vous pouvez même pousser le vice plus loin en ajoutant le module d’authentification PAM pam_ssh à la configuration de votre gestionnaire de connexion (si bien sûr il utilise PAM). Il s’agit d’inclure une ligne de ce genre au début du fichier du service PAM concerné :

auth	sufficient	pam_ssh.so	no_warn try_first_pass

pam_ssh vous permet de taper votre passphrase en guise de mot de passe de connexion et se charge de lancer ssh-agent pour vous. Que demander de plus ?

Problèmes avec le Wifi

Des problèmes avec le Wifi, j’en ai rencontré un certain nombre : les deux plus agaçants étant, en grand numéro 1, les fréquentes déconnexions, suivi, de très loin par le débit qui décroît parfois assez violemment.

Régulièrement, le VPN ou le Wifi, ou les deux, va périr. Pour diagnostiquer la panne, plusieurs méthodes. Aucune n’est 100% fiable, mais elles donnent toutes des informations utiles, selon le cas.

  1. Le premier réflexe est de regarder la liste des processus. Si certains manquent, vous savez d’où vient le problème…

  2. Un autre moyen de dépister le problème (dans le cas du Wifi, ça ne marche évidemment pas pour le VPN), et qui est peut-être meilleur (entendez par là qu’il s’agit peut-être du problème le plus courant), est d’utiliser wpa_cli status. Regardez par exemple la ligne wpa_state.

  3. Si cela ne résout pas le problème, la netstat -r peut vous aider à y voir plus clair : ils permettent d’identifier les chemins (littéralement « itinéraires », routes en anglais) empruntés par les paquets du réseau.

    En temps normal, vous devriez voir une interface tun (le tunnel VPN) et une interface correspondant à votre carte Wifi (p.ex. wlan sous Linux, ou wpi pour ma carte Intel sous NetBSD).

    En cas de problème, certains chemins au réseau peuvent disparaître. Si l’interface tun n’est plus présente, c’est vpnc qui est mort. Si c’est l’interface de votre carte Wifi, c’est le Wifi qui est en cause.

    Un autre problème assez courant est que certains chemins demeurent alors même que la connexion est morte ou a changé. Les symptômes sont typiquement : vous êtes connecté et wpa_cli status vous retourne des informations crédibles mais vous ne pouvez accéder à aucun autre hôte du réseau, même pas votre passerelle ou vos serveurs DNS. Dans ce cas, il faut supprimer les chemins erronés avec route del (Linux) ou route delete (NetBSD) (généralement la passerelle par défaut, default, suffit) et rétablir la connexion.

  4. Enfin, un simple ping sur TCP (ICMP est bloqué, vous pouvez utiliser par exemple echoping) peut également vous être utile pour apprécier l’état général de la connexion.

Solutions

Si c’est vpnc, il suffit de le relancer, en revanche, si c’est le Wifi (et il m’a fallu pas mal de temps pour m’en rendre compte), c’est probablement que vous avez été déconnecté et qu’en même temps, votre liste de points d’accès s’est vidée ! La solution ? Rescanner la liste des points d’accès, avec par exemple :

# wpa_cli scan

Quelques fois, wpa_cli status vous indiquera un état valide (ASSOCIATED) mais vous n’aurez aucune IP attribuée : relancer le client DHCP peut être nécessaire. La plupart du temps, il s’agit de dhclient, mais selon le système, cette démarche peut être couplée avec le redémarrage du service réseau tout entier : par exemple, /etc/init.d/net.wlan0 restart sous Gentoo mais simplement /etc/rc.d/dhclient restart sous NetBSD.

Quant au problème de débit misérable, si iwconfig (sous Linux) ou autre wlanctl (sous NetBSD) vous indique un [Bit] rate minable, vous pouvez sans doute y remédier avec un wpa_client reassociate.

Automatiser le processus

Toute cette surveillance est fastidieuse et l’on est vite tenté de vouloir l’automatiser. Cela peut se faire par exemple avec un script tournant en fond qui échantillonne périodiquement l’état de la connexion et tente de remédier aux problèmes.

Ce n’est pas une tâche aisée, cependant, car le diagnostic peut être délicat. Un petit script peut toutefois du moins vous épargner de retaper les trois ou quatre commandes servant à relancer l’ensemble des services nécessaires.

Je vous mets à disposition mes deux petits scripts pour NetBSD, qui sont très loin d’être parfaits (je me retrouve de temps en temps à devoir faire sudo do_wifi all à la main), mais qui peuvent servir de point de départ ou de source d’inspiration pour élaborer les vôtres. :)

do_wifi
Le script principal.
do_sshtunnel
Trois lignes de shell qui démarrent mon tunnel SSH.

Fin

Bah voilà, c’est fini et c’est la vie, mais avec ça et un peu de documentation, vous devriez avoir une connexion Internet correcte sur le campus, si ce n’était pas déjà fait, mais cette fois, aux frais du CROUS.

[ tag:blog.huoc.org,2009:posts/41 ]
Aucun commentaire · Commenter

/\

xmltools update: new I/O layer and further plans

#. Par rz0 dans GSoC 2009 for NetBSD: xmltools. Publié le 08.07 2009 à 15:45. Aucun commentaire.
<. xmlsed preview: writing XML
>. xmltools implementation: automata and backtracking
io xml xmltools

It has been nearly two weeks since my last update on my plans for xmlsed. Since that time, David and I have come to an agreement on the (hypothetical) syntax and my hybrid model has been retained.

Rewriting the I/O module

Although I now have a fair idea of what xmlsed should look like and how to implement it, some elements introduced after the recent discussions with my mentor required changes to the existing code.

In particular, the new template syntax required an XML parser able to handle partial XML documents. Besides, I wanted some syntactic sugar on top of XML to make writing templates easier. Expat being a well-behaved XML parser is quite strict about the syntax and there is no easy way to work around that. Though I did spend some days trying, at first, I eventually gave up, as it proved hard to write, let alone maintain in the future.

At the same time, I began to realize the original I/O abstraction I designed was showing its limits. I initially wanted to be able to read and write multiple tree representation formats, but in the end, the need to fully support XML, with all its specifics (doctypes, PIs, etc.), has convinced me to drop the idea and focus on XML alone.

All these reasons led me to rewrite the I/O layer (almost) completely. This work is being committed to yet another temporary branch: xmlpush.

Maybe the most visible change is that multi-backend support was dropped and the I/O module now consists of only two drivers: the Expat-based parser (the strict parser) and a home-made loose parser.

All tools now support two modes: the strict mode (-s flag) and the default loose mode.

  • In the strict mode, compliance with the XML standard is a priority: all extensions are disabled, including multi-root and partial documents (which was implemented with Expat as an ugly kludge before, so it was removed), the XML prolog is honored (the specified encoding is used and entity declarations are parsed), and stricter rules are enforced (e.g. in names).

  • In the loose mode, extensions are supported and the XML prolog is ignored (instead, we use the system locale).

The encoding issue

Although I’ve just stated how encodings will be handled, at the moment, I have not written any code to suppor that yet. Actually, it’s not a simple matter.

First of all, the XML standard mandates support of Unicode. For one thing, XML character entities (&xxxx;) are references to character codes from the Unicode tables. This makes support for Unicode pretty much mandatory.

In order to handle this, the Expat people have chosen to serve all data as UTF-8 (or UTF-16, depending on the build-time configuration), no matter what input encoding is used. This should have given you a hint: Expat has its own encoding conversion engine.

Now, even though XML documents can specify an encoding, and so it would be alright to always use UTF-8, that is not an acceptable solution in the real world: Unix users expect their programs to comply to the current locale. But Expat does not care one way or the other about, or integrate with, the locale system.

Fortunately, NetBSD has iconv(3) (though neither FreeBSD nor OpenBSD does, apparently, which will be a problem in making my programs portable; there seems to be an ongoing GSoC effort to port NetBSD libiconv to FreeBSD though), so I plan to run everything through that on input and again on output. Sounds like a waste of resources? Well, don’t blame me.

However, that’s not all: there is also the loose parser. Since this one was written by me, and I had no reason to force UTF-8 everywhere, it does no conversion and assumes all sources are in the current locale. The only problem will be for character entities (not currently implemented), but I intend to localize the Unicode-to-locale transformation to these, since it is costly.

Remember the push-style vs event-driven parser debate?

Well, it wasn’t really a debate, but maybe some of you remember that I posted some weeks ago a ticket on this blog about how I grew dissatisfied with the rigid event-driven behavior of Expat and wanted a push-style parser.

I took the occasion this time to make my wish come true (almost) and the new I/O design is mostly push-style. I say mostly because I’ve made some compromises in order not to impair performances.

At first, I thought about having the parser run on a fragment of input text and build a queue of events to be fed to the application one by one, on a on-demand basis. But then I realized I could just use the internal tree directly as my event queue, and have the application read that. Since we have support for look-ahead in the matching engine (and hence need to keep a partial internal tree in any case) and most tools will use that, this effectively moved the tree building code from the matcher to the I/O module, at the same time eliminating direct event responses (a bit less than 500 lines of code). This last point needs some clarification: sure we do use a little more memory (but honestly that just doesn’t show) since we build the tree first and only then process it, but this is limited to how many nodes can be represented in one read buffer, which means it’s mostly insignificant. But we have gained what I think is far more important: an unified implementation of the matcher (which is the most sensitive part).

Further plans

At the moment, the new parser does not support things such as entity declarations and I am still pondering whether to write code for that or not. In any case, it would be a good idea to have a xmlcat(1) utility which fully supports XML, including external entities, with the ability to fetch and include external documents (fetch(3)?) and substitute references. But let’s leave this discussion for another time.

As for the locale support, I think it will come after xmlsed is somewhat ready (i.e. as xmlgrep is right now). So for now, some more testing needs to be done on the new I/O components, and when this is done, I will resume work on xmlsed proper.

[ tag:blog.huoc.org,2009:posts/15 ]
Aucun commentaire · Commenter

<< >> Page : 0 1 2 3 4 5 6 7 8 9