Archives 09/2009

26/9/2009 Petite présentation de sys/queue.h

C

Dans vos programmes C, il arrive très fréquemment d'utiliser des listes chaînée (de toutes sortes), afin de ne pas avoir à recréer le monde à chaque fois vous pouvez utiliser les macros super pratiques de queue(3). Voici une petite introduction à l'utilisation de sys/queue.h avant d'aller se plonger dans le man pour aller plus loin.

Avec sys/queue.h , vous pouvez manipuler facilement quatres sortes de listes :

  • Listes simplement chainées (SLIST) de type pile
  • Listes doublement chainées (LIST) de type pile
  • Listes simplement chainées (STAILQ) de type file
  • Listes doublement chainées (TAILQ) de type file

Voici un exemple de SLIST :

Le header :

#ifndef HEADER_H
#define HEADER_H

#include <sys/queue.h>

typedef struct MaStruct {
    /* ici on met nos elements par exemple : */
    char *str;

    /*
     * On déclare notre liste avec SLIST_ENTRY qui est equivalente à
     * struct { struct MaStruct *sle_next; } next;
     */

    SLIST_ENTRY(MaStruct) next;
} MaStruct;

#endif /* HEADER_H */

Ensuite voyons comment manipuler cette liste :

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "header.h"

int
main(void)
{
    /* SLIST_HEAD crée une variable pour acceder à notre liste */
    SLIST_HEAD(, MaStruct) head;

    /* on crée un element MaStruct */
    MaStruct *p;

    /* On l'initialise à NULL */
    SLIST_INIT(&head);

    p = malloc(sizeof(*p));
    p->str = malloc(sizeof(char) * 10);
    strcpy(p->str, "blah");

    /* On insere p dans la SLIST */
    SLIST_INSERT_HEAD(&head, p, next);

    /* On empile un deuxième element */
    p = malloc(sizeof(*p));
    p->str = malloc(sizeof(char) * 10);
    strcpy(p->str, "blu");

    SLIST_INSERT_HEAD(&head, p, next);

    /*
     * Il est très facile de parcourir la liste
     * que ce soit pour du traitement ou de
     * la libération de mémoire
     */
    SLIST_FOREACH(p, &head, next) {
        /* ici p est l'element courant */
        printf("element : %s\n", p->str);
    }

    /* exemple de libération */
    while (!SLIST_EMPTY(&head))
    {
        p = SLIST_FIRST(&head);
        SLIST_REMOVE_HEAD(&head);
        free(p->str);
        free(p);
    }

    return 0;
}

Parmis les macros interessantes pour les SLIST il y a :

SLIST_FIRST(&head);                /* renvoie la tête de liste */
SLIST_REMOVE_HEAD(&head, next);    /* supprime la tete de liste */
SLIST_EMPTY(&head); /* renvoie vrai si la liste est vide */

Ben entendu, il y a beaucoup plus de possibilités avec LIST et TAILQ... Mais globalement vous devriez avoir compris le principe.

La lecture de sys/queue.h devrait vous éclairer pour comprendre comment marchent toutes ces macros, c'est assez facile à comprendre si vous avez (comme moi) un niveau moyen en C.

Voyez aussi ce papier d'iMil.

13/9/2009 Nouveau blog

J'ai du mal à utiliser un logiciel sans savoir exactement comment il marche. En l'occurrence j'utilisais dotclear, un moteur de blog en php, je l'utilisais de façon basique sans les nombreuses fonctionnalités à coté (dont je ne connais pas plus le sens que le nom).

Quand un jour Bender B. Rodriguez me montre un template CSS qui me plait bien, j'avais déjà l'idée de coder mon propre blog derrière la tête et c'est parti pour coder ce nouveau blog from scratch en python bien sûr avec webpy.

Maintenant quand j'ai un bug ou un problème je peux régler le problème rapidement.

Pour ceux qui veulent essayer chez eux mon blog, le code est disponible via git :

$ git clone git://git.philpep.org/pblog.git

Pblog est donc écris en python avec le framework minimaliste webpy, avec des templates générés par makotemplates, le générateur html est markdown couplé avec pygments pour la coloration syntaxique, la base de données utilisé est MySQL mais ça doit pas être trop dur de l'utiliser avec d'autres DB.

Toute contribution est bienvenue, c'est fort probable que le code comporte une maxi faille donc noble hacker si tu la trouve merci de m'en faire part avant de l'avoir exploité :-)

Si vous trouvez que les pages mettent un temps fou à se générer j'ai ma petite idée là dessus, en fait j'utilise des jails, donc nous avons :

  • lenine.philpep.org avec les sites en php et le serveur MySQL
  • marx.philpep.org avec les sites en python

Donc, les requettes sql ne se font pas en localhost et il y a des latences non négligeables (le code n'étant pas super optimisé ça amplifie le truc).

La solution que j'envisage (à moins de tout optimiser avec du cache), c'est d'utiliser une db plus adaptée à cette petite appli web toute simple : sqlite.

11/9/2009 Limiter un utilisateur avec pf

OpenBSD Packet Filter permet de filtrer les paquets suivant l'UID de provenance (et peut être même de destination mais ça nous intéresse moins.

Vous avez un amis qui se connecte en ssh chez vous pour poser un irssi dans un GNU screen. C'est super sympa de votre part, seulement si on a pas une confiance totale en cet utilisateur il pourrait (lui ou un virus) se servir de son accès pour utiliser votre IP et balancer du spam, lancer une attaque de banque ou je ne sais quoi encore. Résultat : vous êtes responsable.

L'idée est simple, nous allons filtrer le trafic sortant de cet utilisateur (de login fictif machin) en lui autorisant uniquement le port IRC 6667 :

pass out on $ext_if proto tcp to port 6667 user machin tag TAG_MACHIN
block out quick on $ext_if proto tcp all user machin ! tagged TAG_MACHIN

La première règle autorise le port 6667 sortant pour machin et tagge le paquet avec TAG_MACHIN. La deuxième bloque tout ce qui vient de machin et qui n'est pas taggé avec TAG_MACHIN. Ce qui fait exactement ce que l'on veut.

Le mot clef quick permet a la règle d'être prise en compte immédiatement peu importe les règles suivantes (ce qui protège d'une éventuelle règle qui ferait tout passer ensuite).

Pour continuer dans l'exemple, il peut être utile d'autoriser les query DNS pour cet utilisateur (si vous n'avez pas de serveur DNS en interne), ça se passe en 53/udp :

pass out on $ext_if proto tcp to port 6667 user machin tag TAG_MACHIN
pass out on $ext_if proto udp to port domain user machin tag TAG_MACHIN
block out quick on $ext_if proto tcp all user machin ! tagged TAG_MACHIN

On peut même faire des listes sur les port et/ou utilisateurs :

users = { machin, truc }
pass out on $ext_if proto tcp to port { 6667, http } user $users tag TAG_USERS
pass out on $ext_if proto udp to port domain user $users tag TAG_USERS
block out quick on $ext_if proto tcp all user $users ! tagged TAG_USERS