close
  • chevron_right

    Adrien Dorsaz – 7 days ago - 07:08

    Bravo ! Let's Encrypt a validé sa version définitive de son standard de génération automatique de certificats ! CLAPPING HANDS SIGN

  • The ACME Protocol is an IETF Standard

    It has long been a dream of ours for there to be a standardized protocol for certificate issuance and management. That dream has become a reality now that the IETF has standardized the ACME protocol as RFC 8555. I’d like to thank everyone involved in that effort, including Let’s Encrypt staff and other IETF contributors. Having a standardized protocol for certificate issuance and management is important for two reasons. First, it improves the quality of the software ecosystem because developers can focus on developing great software for a single protocol, instead of having many pieces of less well maintained software for bespoke APIs.

  • chevron_right

    Adrien Dorsaz – 7 days ago - 06:35

    Internet est vraiment devenu nécessaire : on prive les gens de services, car ils sont disponibles sur Internet !

  • link

    Sans TNT, plus de TV

    La Fédération romande des consommateurs est une association de défense des consommateurs basée en Suisse romande et fondée en 1959.

  • chevron_right

    Utilisation de GtkTreeModel, GtkTreeView et consorts

    Adrien Dorsaz – Thursday, 7 February - 14:31

Introduction

J'ai eu de la peine à trouver dans la documentation de GTK une vision globale de tout ce qui est possible de faire avec l'affichage d'une GtkTreeView.

La documentation de GTK est disponible via l'interface graphique Devhelp (si vous avez des problèmes de rendu, vous avez peut-être une base MIME en mauvais état). Elle a bien une description globale de l'utilisation de GtkTreeModel et GtkTreeView, mais elle est un peu trop généraliste.

J'écris donc cet article pour permettre à d'autres personnes (sûrement moi-même dans 6 mois :D) de mieux comprendre comment tous ces objets se goupillent pour faire un affichage propre des arbres (ou listes) de données avec le widget GtkTreeView sous forme de tableau.

Vision d

GtkTreeView contient uniquement les informations relatives à l'affichage des données: quelles données doivent être affichées, dans quelles colonnes, est-ce que les lignes doivent être pliées ou dépliées…

Les données sont toutes contenues dans l'objet GtkTreeModel qui est implémenté par GtkTreeStore et GtkListStore (le premier permet d'avoir une hiérarchie entre les lignes de données, le second permet d'avoir une liste plate de donnée).

Au travers de mes tests pour HomeBank, j'ai découvert également qu'il existe GtkTreeModelFilter et GtkTreeModelSort qui implémentent aussi GtkTreeModel. Le premier est utilisé pour appliquer un filtre sur les données qui doivent être affichées. Ceci vous permet donc d'inclure des lignes techniques dans vos modèles qui ne seront pas systématiquement affichées à l'utilisateur. Le second est utilisé pour appliquer un tri sur vos données qui ne sera pas dépendant de l'ordre d'insertion de vos données dans le modèle.

Notez que ces deux derniers modèles sont construits au dessus d'un modèle qui contient les données réelles. Ainsi quand vous les utilisez, vous ne pourrez pas modifier directement les itérateurs reçus par les événements utilisateurs, mais vous allez devoir les traduire comme itérateur du modèle original. Heureusement pour moi, l'objet GtkTreeStore implémente GtkTreeModel et l'interface GtkTreeSortable ce qui rend de fait inutile d'utiliser la couche supplémentaire de GtkTreeModelSort pour appliquer mon tri.

Création du modèle et ajout des données

GtkTreeModel peut être vue comme une table dans une base de donnée: son objectif est d'enregistrer toutes les informations qui définissent la nature de la ligne de donnée sans toutefois que les colonnes de la table correspondent aux colonnes affichées dans la vue.

Dans le cas de HomeBank par exemple, j'avais besoin de stocker les informations sur la catégorie budgétaire (nom et ID de la catégorie, son type, ses montants budgétés par mois…) et les informations externes qui m'aident à définir l'affichage des données (si la ligne correspond juste à un séparateur, si elle est une des 3 racines de l'arbre que j'ai crée, si la ligne est un total calculé automatiquement, si c'est une ligne technique d'en-tête…).

Dans mon, cas, le modèle est donc définit ainsi:

// Create Tree Store
budget = GTK_tree_store_new (
    ADVBUD_NUMCOLS, // Nombre de donnée dans le modèle
    // Les propriétés des catégories de HomeBank
    G_TYPE_UINT, // ADVBUD_CATEGORY_KEY
    G_TYPE_STRING, // ADVBUD_CATEGORY_NAME
    G_TYPE_STRING, // ADVBUD_CATEGORY_FULLNAME
    G_TYPE_INT, // ADVBUD_CATEGORY_TYPE
    G_TYPE_BOOLEAN, // ADVBUD_ISDISPLAYFORCED
    G_TYPE_BOOLEAN, // ADVBUD_ISSAMEAMOUNT
    // Montants (le premier est un montant fixe par mois)
    G_TYPE_DOUBLE, // ADVBUD_SAMEAMOUNT
    G_TYPE_DOUBLE, // ADVBUD_JANUARY
    G_TYPE_DOUBLE, // ADVBUD_FEBRUARY
    G_TYPE_DOUBLE, // ADVBUD_MARCH
    G_TYPE_DOUBLE, // ADVBUD_APRIL
    G_TYPE_DOUBLE, // ADVBUD_MAY
    G_TYPE_DOUBLE, // ADVBUD_JUNE
    G_TYPE_DOUBLE, // ADVBUD_JULY
    G_TYPE_DOUBLE, // ADVBUD_AUGUST
    G_TYPE_DOUBLE, // ADVBUD_SEPTEMBER
    G_TYPE_DOUBLE, // ADVBUD_OCTOBER
    G_TYPE_DOUBLE, // ADVBUD_NOVEMBER
    G_TYPE_DOUBLE,  // ADVBUD_DECEMBER
    // Les données techniques liées à l'utilisation dans les widgets GTK
    G_TYPE_BOOLEAN, // ADVBUD_ISROOT
    G_TYPE_BOOLEAN, // ADVBUD_ISTOTAL
    G_TYPE_BOOLEAN, // ADVBUD_ISCHILDHEADER
    G_TYPE_BOOLEAN // ADVBUD_ISSEPARATOR
);

Dans le code source réel, je n'ai pas tout à fait organisé comme ça les données, mais là, ça vous permet de bien voir les différentes données que j'ai enregistrées.

Notez que les 2 dernières données sont inutiles pour le widget d'affichage GtkTreeView dans ma fenêtre principale. Elles sont là, car j'utilise exactement le même modèle pour créer un GtkComboBox qui contient la liste des catégories actuelles.

Comme vous pouvez le constater, dans ce modèle je n'enregistre pas de donnée relative au montant total de la catégorie sur l'année. Cette colonne est inutile dans le modèle, car il peut être calculé directement lors de l'affichage de la vue. Ça permet de pouvoir mettre à jour les montants mensuels dans le modèle simplement sans avoir à se soucier de mettre à jour cette colonne de totale.

Le code source qui insert les catégories d'HomeBank dans le modèle, le fait en 2 temps (il y a une fonction pour le faire directement, mais j'avais une condition à faire appliquer avant):

gtk_tree_store_insert (
    budget, // Le modèle
    &child, // La nouvelle ligne à insérer dans le modèle
    parent, // La ligne parente à la nouvelle ligne
    -1);

DB(g_print("insert new category %s (key: %d, type: %d)\n",
    bdg_category->name, bdg_category->key, category_type_get (bdg_category)));

gtk_tree_store_set(
    budget,
    &child,
    ADVBUD_CATEGORY_KEY, bdg_category->key,
    ADVBUD_CATEGORY_NAME, bdg_category->name,
    ADVBUD_CATEGORY_FULLNAME, bdg_category->fullname,
    ADVBUD_CATEGORY_TYPE, category_type_get (bdg_category),
    ADVBUD_ISDISPLAYFORCED, (bdg_category->flags & GF_FORCED),
    ADVBUD_ISROOT, FALSE,
    ADVBUD_ISSAMEAMOUNT, cat_is_sameamount,
    ADVBUD_ISTOTAL, FALSE,
    ADVBUD_SAMEAMOUNT, bdg_category->budget[0],
    ADVBUD_JANUARY, bdg_category->budget[1],
    ADVBUD_FEBRUARY, bdg_category->budget[2],
    ADVBUD_MARCH, bdg_category->budget[3],
    ADVBUD_APRIL, bdg_category->budget[4],
    ADVBUD_MAY, bdg_category->budget[5],
    ADVBUD_JUNE, bdg_category->budget[6],
    ADVBUD_JULY, bdg_category->budget[7],
    ADVBUD_AUGUST, bdg_category->budget[8],
    ADVBUD_SEPTEMBER, bdg_category->budget[9],
    ADVBUD_OCTOBER, bdg_category->budget[10],
    ADVBUD_NOVEMBER, bdg_category->budget[11],
    ADVBUD_DECEMBER, bdg_category->budget[12],
    -1);

La structure bdg_category correspond à la modélisation des catégories budgétaires par HomeBank. Je n'utilise quasiment que les informations de HomeBank quand j'ajoute une ligne de catégorie dans mon modèle (la ligne s'appelle child et le modèle budget dans le code).

Dans le code source, pour chaque nouvelle catégorie crée, j'ajoute systématiquement 2 nouveaux enfants à cette ligne:

  1. Un premier enfant qui correspond à la catégorie du père (même identifiant et même nom, je l'appelle dans le code "childhead" pour l'"en-tête des enfants").
  2. Un second enfant qui sera juste utilisé comme séparateur.

Ceci permettra de faire des GtkComboBox qui pourront sélectionner les catégories intermédiaires dans la hiérarchie. Vous verrez dans le chapitre des filtres comment ces lignes sont cachées.

Dialogue d

Dialogue de fusion des catégories avec un GtkComboBox

Ajout d'un tri sur le modèle

Quand j'ajoute les lignes dans le modèle, je ne fais pas du tout attention à l'ordre de création des lignes. Je parcours simplement les catégories de HomeBank une à une et je les ajoute dans le modèle. En réalité, le seul point que je fais attention c'est d'ajouter la catégorie parente d'abord afin de conserver la même hiérarchie que HomeBank.

Au début, j'affichais ces lignes directement et l'affichage n'avait donc aucun sens pour l'utilisateur, car le tri des catégories sœurs correspondait à l'ordre de création des catégories par l'utilisateur.

Comme GtkTreeStore (de même que GtkListStore) implémente l'interface GtkTreeSortable, il est très simple de lui ajouter un tri:

/* Sort categories on same node level */
gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE(budget), // budget est un pointeur de GtkTreeStore, ici nous utilisons les macros de Gtk dans C pour expliciter au compilateur que l'interface GtkTreeSortable est disponible depuis ce pointeur également
    ADVBUD_CATEGORY_NAME, ui_adv_bud_model_row_sort, // Nom de la fonction qui implémente l'algorithme de tri
    NULL, NULL);
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (budget),
    ADVBUD_CATEGORY_NAME, GTK_SORT_ASCENDING); // Le tri est croissant

Par exemple, dans HombeBank, l'implémentation de la fonction affiche d'abord la catégorie « en-tête des enfants », puis la catégorie « séparateur », puis dans l'ordre alphabétique les autres catégories.

Comme vous pouvez le voir, je ne fais le tri que sur une seule colonne et comme c'est le seul tri qui est logique pour cette vue, je n'ai pas cherché à proposer des tris différents pour les différentes colonnes.

Comme nous utilisons directement le même objet modèle, aucune complexité n'est ajoutée pour le traitement des lignes reçues par les actions utilisateurs (les itérateurs reçus sont donc toujours directement liés au modèle qui contient les données réelles).

Ajout d'un filtre sur le modèle

Dans le cas de HomeBank, j'avais besoin de pouvoir appliquer différents filtres sur les lignes des modèles: d'abord, j'avais besoin de cacher mes lignes techniques (« en-tête d'enfants » et « séparateur ») quand je n'en avais pas besoin, ensuite j'avais aussi besoin de filtrer les lignes selon la vue demandée par l'utilisateur (soit une vue de toutes les catégories, soit une vue uniquement des crédits, soit une vue des dépenses).

Il m'a donc fallu trouver une solution pour facilement afficher ces différentes vues. Dans ma première implémentation, je n'avais pas trouvé dans la documentation de GTK les objets GtkTreeModelFilter. En plus, comme dans mon premier essai la vue était très simple, j'ai simplement décidé de détruire et reconstruire le modèle à chaque fois que l'utilisateur appuyait sur un bouton. J'en conviens ce n'était pas le plus performant, mais ça marchait et je n'avais pas vu la solution plus élégante, mais plus complexe à mettre en œuvre des GtkModelFilter.

// tree model to map HomeBank categories to the tree view
model = ui_adv_bud_model_new(); // Création du modèle sous forme de GtkTreeStore

filter = gtk_tree_model_filter_new(model, NULL); // Création du modèle "filtre" à partir du modèle réel
gtk_tree_model_filter_set_visible_func(GTK_TREE_MODEL_FILTER(filter), ui_adv_bud_model_row_filter, data, NULL); // Définition de la fonction à utiliser pour filtrer

gtk_tree_view_set_model(GTK_TREE_VIEW(treeview), filter); // Liaison de GtkTreeView (voir plus bas) avec le modèle "filtre" et non pas le vrai modèle "budget"

g_object_unref(model); // Remove model with filter
g_object_unref(filter); // Remove filter with view

Bon, là vous allez me dire que ce n'est pas plus compliqué que pour le tri vu plus haut.

C'est en effet, très simple, surtout que dans HomeBank, la fonction de tri ui_adv_bud_model_row_filter est identique quel que soit l'interaction de l'utilisateur: cette fonction lit quel bouton est activé par l'utilisateur et ajuste son tri. Il fallait juste faire attention à appeler gtk_tree_model_filter_refilter quand l'utilisateur cliquait sur un bouton pour vérifier à nouveau quelles lignes doivent être affichées dans le nouveau contexte.

Ce qui est rendu plus compliqué en réalité est la lecture des lignes du modèle durant les interactions utilisateurs, car le filtre ajoute un modèle englobant le modèle réel. Dans ce cas, ça veut dire que pour pouvoir appliquer des modifications sur le modèle réel, il faut bien faire attention à sélectionner la ligne du modèle réel et non pas la ligne retournée par l'interface utilisateur qui est liée au modèle « filtre ».

Par exemple, pour retrouver la ligne courante quand l'utilisateur demande de supprimer une catégorie, je dois passer par ces étapes:

DB( g_print("[ui_adv_bud] open sub-dialog to delete a category\n") );

view = data->TV_budget; // data est un pointeur sur une structure qui conserve les adresses des différents widgets de la vue, view est un GtkTreeView

filter = gtk_tree_view_get_model (GTK_TREE_VIEW(view)); // Le modèle lié au GtkTreeView est bien un filtre

budget = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(filter)); // Depuis le filtre, je peux retrouver le modèle réel

selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); // selection est un objet GtkTreeSelection lié à la vue et donc au modèle filtre

// filter_iter est l'itérateur du modèle lié à la sélection courrante quand le retour de la fonction est TRUE
if (gtk_tree_selection_get_selected(selection, &filter, &filter_iter))
{
Category* category;
guint32 item_key;

    // Traduction de l'itérateur du filtre vers un itérateur du modèle réel
    gtk_tree_model_filter_convert_iter_to_child_iter(GTK_TREE_MODEL_FILTER(filter),
        &iter,
        &filter_iter);

    // Enfin, je peux retrouver l'identifiant de la catégorie sélectionnée
    gtk_tree_model_get (budget, &iter,
        ADVBUD_CATEGORY_KEY, &item_key,
        -1);

C'est un peu plus complexe, mais ça reste gérable tant qu'il n'y a pas trop de couches de modèle: avant que je remarque l'interface GtkTreeSortable, j'avais utilisé une couche supplémentaire pour le tri et, là, ça commençait à faire beaucoup de modèles et de traductions d'itérateur à appliquer correctement.

Affichage des données du modèle dans la vue

Enfin, maintenant que nos données sont enregistrées dans le modèle, qu'elles sont filtrées selon le contexte de l'interface et qu'elles sont triées selon un tri naturelle, il reste à les afficher à l'utilisateur.

Lors de la création de la vue avec GtkTreeView, il faut définir chaque colonne à afficher (GtkTreeViewColumn). Pour chaque colonne, il faut indiquer comment va être fait le rendu des cellules de la colonne (GtkCellRenderer). Chaque colonne peut contenir plusieurs éléments de rendu, comme c'est le cas pour la colonne "Monthly" qui affiche une case à cocher pour activer le montant mensuel et une entrée de texte pour y entrer le montant.

Les rendus peuvent être soit directement liés à la valeur du modèle, soit avec une fonction qui s'occupera du rendu.

view = gtk_tree_view_new(); // Création de la vue

/* --- Colonne "Catégorie" --- */
col = gtk_tree_view_column_new();
data->TVC_category = col;

gtk_tree_view_column_set_title(col, _("Category"));
gtk_tree_view_append_column(GTK_TREE_VIEW(view), col); // Lisaison de la colonne à la vue

// Category Name
cat_name_renderer = gtk_cell_renderer_text_new(); // rendu de type entrée de texte
gtk_tree_view_column_pack_start (col, cat_name_renderer, TRUE); // ajout du rendu dans la colonne
gtk_tree_view_column_add_attribute(col, cat_name_renderer, "text", ADVBUD_CATEGORY_NAME); // ce rendu est directement lié à une colonne du modèle

// Le nome de la catégorie peut être édité directement depuis la vue
g_object_set(cat_name_renderer, "editable", TRUE, NULL);
g_signal_connect(cat_name_renderer, "edited", G_CALLBACK(ui_adv_bud_cell_update_category), (gpointer) data);

/* --- Colonne "Monthly" --- */
col = gtk_tree_view_column_new();
gtk_tree_view_column_set_title(col, _("Monthly"));
gtk_tree_view_append_column(GTK_TREE_VIEW(view), col);

// Monthly toggler
renderer = gtk_cell_renderer_toggle_new(); // rendu de type case à cocher
gtk_tree_view_column_pack_start(col, renderer, TRUE); // ajout du premier rendu à la colonne "Monthly"

// Ici, le rendu utilise une fonction, car le rendu ne doit rien afficher pour les lignes de racine de l'arbre et les lignes de total
gtk_tree_view_column_set_cell_data_func(col, renderer, ui_adv_bud_view_display_issameamount, NULL, NULL);

g_signal_connect (renderer, "toggled", G_CALLBACK(ui_adv_bud_cell_update_issameamount), (gpointer) data);

// Monthly amount
renderer = gtk_cell_renderer_spin_new(); // rendu de type numérique avec les boutons + et - pour l'édition
gtk_tree_view_column_pack_start(col, renderer, TRUE); // ajout du second rendu à la colonne "Monthly"

// Utilisation d'une fonction de rendu pour la même raison et aussi pour ajuster la couleur du texte affiché selon le montant
// Le numéro de la colonne est donné en plus pour pouvoir afficher le montant du bon mois (en l'occurence du mois "sameamount")
// Ca me permet d'utiliser la même fonction pour les 13 colonnes de montant
gtk_tree_view_column_set_cell_data_func(col, renderer, ui_adv_bud_view_display_amount, GINT_TO_POINTER(ADVBUD_SAMEAMOUNT), NULL);

g_object_set_data(G_OBJECT(renderer), "ui_adv_bud_column_id", GINT_TO_POINTER(ADVBUD_SAMEAMOUNT));
g_signal_connect(renderer, "edited", G_CALLBACK(ui_adv_bud_cell_update_amount), (gpointer) data);

Conclusion

L'outil GtkTreeView est assez complexe et demande du temps pour s'y habituer, mais j'ai vraiment été surpris en bien du fait que la complexité est assez bien réfléchie pour pouvoir répondre aux différents besoins des utilisateurs (tris, filtres, recherche…) tout en étant relativement saine à utiliser dans des codes d'interfaces.

Pour avoir un exemple de code réel utilisant ces informations, vous pouvez voir ma proposition de fusion pour HomeBank de cette vue d'affichage de budget.

  • chevron_right

    Configure OpenLDAP to use Kerberos as password backend

    Adrien Dorsaz – Friday, 1 February - 11:11

C'était assez compliqué à mettre en place, mais voilà, j'ai enfin réussi :)


  • chevron-right

    Configure OpenLDAP to use Kerberos as password backend

    This text reports what I've done to use Kerberos as password backend for my OpenLDAP installation. It was tried on a Debian Stretch 9. Kerberos Install apt install krb5-kdc krb5-admin-server apt will ask you the name of your default kerberos realm. I've decided to use example.org (in lowercase), because, even if it's not the usual case as explained by apt, I know I'll forgot to use the uppercase notation. Furthermore, I have a specific domain which is only used by LDAP and Kerberos, so I think I'll have no confusion. Configure Kerberos I've just followed my Kerberos Installation resource (linked at the end of the article). So I notice here just what I've done, I can't fully explain every steps. First, we need to configure the Kerberos server by modifying /etc/krb5.conf to add our realm: [libdefaults] default_realm = example.org ... [realms] example.org = { kdc = kdc.example.org admin_server = kdc.example.org default_domain = example.org } ... [domain_realm] .example.com = example.org example.com = example.org ... To define the kdc and admin_server, you can also simply use the localhost domain. If you do as me, you'll need to create DNS resources for kdc.example.org. Then, you need to check the realm has been well installed in /etc/krb5conf/kdc.conf. For me, apt has put: [kdcdefaults] kdc_ports = 750,88 [realms] example.org = { database_name = /var/lib/krb5kdc/principal admin_keytab = FILE:/etc/krb5kdc/kadm5.keytab acl_file = /etc/krb5kdc/kadm5.acl key_stash_file = /etc/krb5kdc/stash kdc_ports = 750,88 max_life = 10h 0m 0s max_renewable_life = 7d 0h 0m 0s master_key_type = des3-hmac-sha1 #supported_enctypes = aes256-cts:normal aes128-cts:normal default_principal_flags = +preauth } Now, the kerberos is well configured, we can create the realm: kdb5_util create -s Then, we use the kadmin.local shell to list principals and create first users: kadmin.local: listprincs K/M@example.org kadmin/admin@example.org kadmin/changepw@example.org kadmin/localhost@example.org kiprop/localhost@example.org krbtgt/example.org@example.org kadmin.local: ank adrien/admin@example.org WARNING: no policy specified for adrien/admin@example.org; defaulting to no policy Enter password for principal "adrien/admin@example.org": Re-enter password for principal "adrien/admin@example.org": Principal "adrien/admin@example.org" created. kadmin.local: ank adrien@example.org WARNING: no policy specified for adrien@example.org; defaulting to no policy Enter password for principal "adrien@example.org": Re-enter password for principal "adrien@example.org": Principal "adrien@example.org" created. Create the kadmin keytab as explained in the MIT documentation: kadmin.local: ktadd -k /etc/krb5kdc/kadm5.keytab kadmin/admin kadmin/changepw Entry for principal kadmin/admin with kvno 2, encryption type aes256-cts-hmac-sha1-96 added to keytab WRFILE:/etc/krb5kdc/kadm5.keytab. Entry for principal kadmin/admin with kvno 2, encryption type aes128-cts-hmac-sha1-96 added to keytab WRFILE:/etc/krb5kdc/kadm5.keytab. Entry for principal kadmin/changepw with kvno 2, encryption type aes256-cts-hmac-sha1-96 added to keytab WRFILE:/etc/krb5kdc/kadm5.keytab. Entry for principal kadmin/changepw with kvno 2, encryption type aes128-cts-hmac-sha1-96 added to keytab WRFILE:/etc/krb5kdc/kadm5.keytab. Finally, edit the file /etc/krb5kdc/kadm5.acl to set up users with admin rights: */admin@example.org * Restart kerberos services: systemctl restart krb5-kdc krb5-admin-server Check with a client On another computer, try to get a kerberos ticket with the client. First, install the client: apt install krb5-user Then, try to authenticate: kinit adrien@example.org On success, you can list current tickets with klist: # klist Ticket cache: FILE:/tmp/krb5cc_1000 Default principal: adrien@example.org Valid starting Expires Service principal 01. 02. 19 11:30:25 01. 02. 19 21:30:25 krbtgt/example.org@example.org renew until 02. 02. 19 11:30:03 To clean the ticket from the client, use: kdestroy. Cyrus SASL Install apt install sasl2-bin libsasl2-modules-gssapi-mit Configure Cryus SASL Edit the service environment variables in /etc/default/saslauthd with: START=yes MECHANISMS="kerberos5" KRB5_KTNAME="/etc/localhost.keytab" export KRB5_KTNAME According to the value of KRB5_KTNAME above, we'll create a new user and its keytab file with kadmin.local: kadmin.local: addprinc -randkey host/localhost WARNING: no policy specified for host/localhost@example.org; defaulting to no policy Principal "host/localhost@example.org" created. kadmin.local: ktadd -k /etc/localhost.keytab host/localhost Entry for principal host/localhost with kvno 2, encryption type aes256-cts-hmac-sha1-96 added to keytab WRFILE:/etc/localhost.keytab. Entry for principal host/localhost with kvno 2, encryption type aes128-cts-hmac-sha1-96 added to keytab WRFILE:/etc/localhost.keytab. Finally, restart the saslauthd service: systemctl restart saslauthd Check saslauthd configuration There's a little command to check if you can connect with your user through Cyrus SASL: # testsaslauthd -u adrien@example.org -p 'your password in clear text' 0: OK "Success." On authentication error, the output will be 0: NO "authentication failed". If you see other errors, like one with connect() fail, check the daemon saslauthd use the right keytab file and it has access to it. OpenLDAP Endly, we are in the final part of the documentation. We just need now to say to OpenLDAP that it can use saslauthd as external authentication mechanism and configure our first user to use it. Enable Cyrus SASL backend We need to create a /etc/ldap/sasl2/slapd.conf with these values: # PLAIN is used by saslauthd # EXTERNAL is required for local root auth mech_list: PLAIN EXTERNAL pwcheck_method: saslauthd saslauthd_path: /var/run/saslauthd/mux Note that OpenLDAP will need access to /var/run/saslauthd/mux. On my installation, the access to the content of /var/run/saslauthd/ is allowed only to users inside the sasl group, so we add openldap to this group: adduser openldap sasl Finally, restart the slapd service: systemctl restart slapd Modify user to use the SASL backend Now, we need to modify the adrien@example.org user to authenticate through SASL. That's simply done by setting the prefix {SASL} followed by the kerberos user name (with realm) inside the userPassword attribute. For example, I've made this ldif file: # adrien, people, example.org dn: uid=adrien,ou=people,dc=example,dc=org changetype: modify replace: userPassword userPassword: {SASL}adrien@example.org Note that to apply this ldif you need to use a user with modification rights on userPassword attribute (the user itself or an administrator). ldapmodify -f 01_adrien_password.ldif -D "uid=adrien,ou=people,dc=example,dc=org" -w 'your old LDAP password in clear text' Finally, to check the new password is well set, you can simply try to do a search inside your LDAP directory: # ldapsearch -D "uid=adrien,ou=people,dc=example,dc=org" -w 'your new password in clear text' -b '' -s base # extended LDIF # # LDAPv3 # base with scope baseObject # filter: (objectclass=*) # requesting: ALL # # dn: objectClass: top objectClass: OpenLDAProotDSE # search result search: 2 result: 0 Success # numResponses: 2 # numEntries: 1 Well done, that was a big job to retrieve every steps to do, thanks a lot of people who documented their steps ! I hope this document will help someone in the future :) Sources Kerberos installation OpenLDAP with external password backend through sasl2authd OpenLDAP documentation for Pass-Through authentication OpenLDAP Authentication With Kerberos Backend Using SASL

    group_work debian-stretch 1 February

  • chevron_right

    Micro: édition zéro d'un futur journalisme indépendant

    Adrien Dorsaz – Tuesday, 29 January - 12:55

Nous avons 30 jours pour décider si nous souhaitons voir, pour environ 4 mois, un nouveau journal indépendant qui souhaite fédérer à nouveau la suisse romande.

L'édition « 0 » (très bon choix pour titiller les informaticiens 😁) est à disposition sur le site de Micro pour vous faire une idée si oui ou non il faudrait leur faire un don pour financer les 90'000 CHF qu'ils pensent avoir besoin pour 4 mois d'édition.

Personnellement, j'apprécie beaucoup leur démarche qui souhaite se séparer de la sur-information: ils ont choisi de ne pas être publié quotidiennement et, en plus, ils disent s'imposer la création de reportages (en opposition donc au simple rapport de faits).

Je pense en effet que les informations H 24 comme nous pouvons le voir sur certaines chaînes TV ou site web ne fait que de noyer les lecteurs sous des faits sans pousser à la réflexion. En plus, ça fait perdre sens au travail de journalisme, au point, où certains journaux font croire à leur lecteur qu'ils peuvent être journalistes juste en tirant une photo ou une vidéo avec leur smartphone.

Leur premier numéro montre bien leur démarche: les deux principaux sujets sont, comme expliqué plus haut, originaux et bien développés. Je me rend bien compte que ces informations ne peuvent pas venir de 5 minutes de recherche sur Internet: je trouve que le fond traite bien de problématiques locales (à la suisse romande) et que la forme montre l'implication du journaliste dans ses recherches (les textes ont de la personnalité et présentent bien la situation).

Je m'emballe sûrement, mais je me réjouis de voir ce que peut donner ces 4 mois d'édition et de collaboration avec les bistrots et restaurants romands.

Maintenant, c'est à vous de choisir et vous faire votre opinion !

  • OnePage

    journal, romand, lematin, matin, microjournal, journal papier

  • image
  • chevron_right

    Adrien Dorsaz – Tuesday, 8 January - 06:22

    C'est un point de vue très intéressant sur la manière d'enseigner et pourquoi elle devra évoluer silea programmation doit être incluse dans des programmes scolaires.

  • chevron_right

    devhelp peut ne pas fonctionner à cause de votre base de donnée MIME (et entre autre à cause de WINE)

    Adrien Dorsaz – Sunday, 6 January - 19:32 edit

devhelp est un outil sympa pour lire les documentations des différents projets (surtout autour de GNOME et GTK). Mais, parfois, certaines documentations sont impossible à ouvrir. Merci à l'utilisateur de Debian qui a découvert que devhelp est très sensible à la base de donnée MIME installée sur nos PCs (perso, un petit coup de mv ./local/share/mime{,.backup} et ça s'est réglé).