keyctl(2) System Calls Manual keyctl(2)

keyctl - Manipuler la gestion des clés du noyau

Bibliothèque C standard (libc-lc)

#include <linux/keyctl.h>  /* Définition des constantes KEY* */
#include <sys/syscall.h>   /* Définition des constantes SYS_* */
#include <unistd.h>
long syscall(SYS_keyctl, int op, ...);

keyctl() permet aux programmes de l'espace utilisateur de manipuler des clés.

L'opération qu'effectue keyctl() dépend de la valeur du paramètre op. Chacune de ces opérations fait partie de l'enveloppe de la bibliothèque libkeyutils (fournie par le paquet keyutils) en tant que fonctions individuelles (voir keyctl(3)) pour permettre au compilateur de vérifier les types.

Les valeurs autorisées pour op sont :

Pour qu'un appel réussisse, le code de retour dépend de l'opération.

En cas d'erreur, la valeur de retour est -1 et errno est définie pour préciser l'erreur.

L'opération demandée n'était pas autorisée.
Le quota de clés de l'utilisateur appelant serait dépassé si la clé était créée ou ajoutée au trousseau.
la taille de la chaîne (y compris l'octet NULL final) indiquée dans arg3 (le type de clé) ou dans arg4 (la description de la clé) dépassait les limites (respectivement 32 et 4096 octets).
Une clé expirée a été trouvée ou spécifiée.
Une clé rejetée a été trouvée ou spécifiée.
Une clé révoquée a été trouvée ou spécifiée.
Aucune clé correspondante n'a été trouvée, ou une clé non valable a été spécifiée.
Une des routines de l'allocation mémoire du noyau a échoué lors de l'exécution de l'appel système.
Une clé de type trousseau était attendue mais l'identifiant d'une clé de type différent a été fourni.

Une enveloppe est fournie dans la bibliothèque libkeyutils. (Le paquet accompagnant fournit le fichier d'en-tête <keyutils.h>.) Cependant, plutôt que d'utiliser cet appel système directement, vous voudrez probablement utiliser les fonctions de la bibliothèque mentionnées dans les descriptions des opérations individuelles ci-dessus.

Linux.

Linux 2.6.10.

Le programme ci-dessous fournit un sous-ensemble de fonctions du programme request-key(8) fourni par le paquet keyutils. Pour information, le programme enregistre diverses informations dans un fichier journal.

Comme indiqué dans request_key(2), le programme request-key(8) est appelé avec les paramètres de la ligne de commande qui décrivent une clé à instancier. Le programme exemple récupère et enregistre ces arguments. Le programme endosse l'autorité d'instancier la clé demandée, puis il instancie cette clé.

La session d'interpréteur suivante montre l'utilisation de ce programme. Dans la session, nous compilons le programme, puis nous l'utilisons pour remplacer temporairement le programme request-key(8) standard (remarquez que la désactivation temporaire du programme standard request-key(8) peut ne pas être sure sur certains systèmes). Tant que notre programme exemple est installé, nous utilisons le programme exemple présent dans request_key(2) pour demander une clé.


$ cc -o key_instantiate key_instantiate.c -lkeyutils
$ sudo mv /sbin/request-key /sbin/request-key.backup
$ sudo cp key_instantiate /sbin/request-key
$ ./t_request_key user mykey somepayloaddata
L'identifiant de clé est 20d035bf
$ sudo mv /sbin/request-key.backup /sbin/request-key

En regardant le fichier journal créé par ce programme, on peut voir les paramètres de la ligne de commande fournis à notre programme exemple :


$ cat /tmp/key_instantiate.log
Time: Mon Nov  7 13:06:47 2016
Command line arguments:
  argv[0]:            /sbin/request-key
  operation:          create
  key_to_instantiate: 20d035bf
  UID:                1000
  GID:                1000
  thread_keyring:     0
  process_keyring:    0
  session_keyring:    256e6a6

Les dernières lignes de la sortie ci-dessus montrent que le programme exemple a pu récupérer :

  • la description de la clé à instanciée, qui incluait le nom de la clé (mykey) ;
  • la charge utile de la clé d'autorisation, qui consistait dans des données (somepayloaddata) passées à request_key(2) ;
  • le trousseau de destination indiqué dans l'appel à request_key(2) ;
  • la description de la clé d'autorisation où on peut voir que le nom de la clé correspond à l'identifiant de celle à instancier (20d035bf).

Le programme exemple dans request_key(2) indiquait le trousseau de destination en tant que KEY_SPEC_SESSION_KEYRING. En examinant le contenu de /proc/keys, on peut voir que cela a été transcrit dans l'identifiant du trousseau de destination (0256e6a6) affiché dans le fichier journal ci-dessus ; on peut aussi voir la clé nouvellement créée dont le nom est mykey et l'identifiant est 20d035bf.


$ cat /proc/keys | egrep 'mykey|256e6a6'
0256e6a6 I--Q---  194 perm 3f030000  1000  1000 keyring  _ses: 3
20d035bf I--Q---    1 perm 3f010000  1000  1000 user     mykey: 16

/* key_instantiate.c */
#include <errno.h>
#include <keyutils.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
#ifndef KEY_SPEC_REQUESTOR_KEYRING
#define KEY_SPEC_REQUESTOR_KEYRING      (-8)
#endif
int
main(int argc, char *argv[])
{
    int           akp_size;       /* Taille de auth_key_payload */
    int           auth_key;
    char          dbuf[256];
    char          auth_key_payload[256];
    char          *operation;
    FILE          *fp;
    gid_t         gid;
    uid_t         uid;
    time_t        t;
    key_serial_t  key_to_instantiate, dest_keyring;
    key_serial_t  thread_keyring, process_keyring, session_keyring;
    if (argc != 8) {
        fprintf(stderr, "Usage : %s op key uid gid thread_keyring "
                        "process_keyring session_keyring\n", argv[0]);
        exit(EXIT_FAILURE);
    }
    fp = fopen("/tmp/key_instantiate.log", "w");
    if (fp == NULL)
        exit(EXIT_FAILURE);
    setbuf(fp, NULL);
    t = time(NULL);
    fprintf(fp, "Time: %s\n", ctime(&t));
    /*
     * Le noyau passe un ensemble fixe de paramètres au programme
     * qu'il exécute ; les récupérer.
     */
    operation = argv[1];
    key_to_instantiate = atoi(argv[2]);
    uid = atoi(argv[3]);
    gid = atoi(argv[4]);
    thread_keyring = atoi(argv[5]);
    process_keyring = atoi(argv[6]);
    session_keyring = atoi(argv[7]);
    fprintf(fp, "Paramètres de la ligne de commande :\n");
    fprintf(fp, "  argv[0]:            %s\n", argv[0]);
    fprintf(fp, "  operation:          %s\n", operation);
    fprintf(fp, "  key_to_instantiate: %jx\n",
            (uintmax_t) key_to_instantiate);
    fprintf(fp, "  UID:                %jd\n", (intmax_t) uid);
    fprintf(fp, "  GID:                %jd\n", (intmax_t) gid);
    fprintf(fp, "  thread_keyring:     %jx\n",
            (uintmax_t) thread_keyring);
    fprintf(fp, "  process_keyring:    %jx\n",
            (uintmax_t) process_keyring);
    fprintf(fp, "  session_keyring:    %jx\n",
            (uintmax_t) session_keyring);
    fprintf(fp, "\n");
    /*
     * Assumer l'autorité pour instancier la clé nommée dans argv[2].
     */
    if (keyctl(KEYCTL_ASSUME_AUTHORITY, key_to_instantiate) == -1) {
        fprintf(fp, "KEYCTL_ASSUME_AUTHORITY a échoué : %s\n",
                strerror(errno));
        exit(EXIT_FAILURE);
    }
    /*
     * Récupérer la description de la clé à instancier.
     */
    if (keyctl(KEYCTL_DESCRIBE, key_to_instantiate,
               dbuf, sizeof(dbuf)) == -1) {
        fprintf(fp, "KEYCTL_DESCRIBE a échoué : %s\n", strerror(errno));
        exit(EXIT_FAILURE);
    }
    fprintf(fp, "Description de clé :      %s\n", dbuf);
    /*
     * Récupérer la charge utile de la clé d'autorisation, qui est en fait
     * les données d'appel (callout) données à request_key().
     */
    akp_size = keyctl(KEYCTL_READ, KEY_SPEC_REQKEY_AUTH_KEY,
                      auth_key_payload, sizeof(auth_key_payload));
    if (akp_size == -1) {
        fprintf(fp, "KEYCTL_READ a échoué : %s\n", strerror(errno));
        exit(EXIT_FAILURE);
    }
    auth_key_payload[akp_size] = '\0';
    fprintf(fp, "Charge utile de la clé d'auth :     %s\n", auth_key_payload);
    /*
     * Par intérêt, récupérer l'identifiant de la clé d'autorisation et
     * l'afficher.
     */
    auth_key = keyctl(KEYCTL_GET_KEYRING_ID,
                      KEY_SPEC_REQKEY_AUTH_KEY);
    if (auth_key == -1) {
        fprintf(fp, "KEYCTL_GET_KEYRING_ID a échoué : %s\n",
                strerror(errno));
        exit(EXIT_FAILURE);
    }
    fprintf(fp, "Identifiant de la clé d'auth :          %jx\n", (uintmax_t) auth_key);
    /*
     * Récupérer l'identifiant de clé pour le trousseau de destination
     * request_key(2).
     */
    dest_keyring = keyctl(KEYCTL_GET_KEYRING_ID,
                          KEY_SPEC_REQUESTOR_KEYRING);
    if (dest_keyring == -1) {
        fprintf(fp, "KEYCTL_GET_KEYRING_ID a échoué : %s\n",
                strerror(errno));
        exit(EXIT_FAILURE);
    }
    fprintf(fp, "Trousseau de destination :  %jx\n", (uintmax_t) dest_keyring);
    /*
     * Récupérer la description de la clé d'autorisation. Cela nous permet
     * de voir le type de clé, l'identifiant utilisateur et de groupe, les
     * droits et la description (nom) de la clé. Entre autres choses,
     * on verra que le nom de la clé est une chaîne hexadécimale représentant
     * l'identifiant de la clé à instancier.
     */
    if (keyctl(KEYCTL_DESCRIBE, KEY_SPEC_REQKEY_AUTH_KEY,
               dbuf, sizeof(dbuf)) == -1)
    {
        fprintf(fp, "KEYCTL_DESCRIBE a échoué : %s\n", strerror(errno));
        exit(EXIT_FAILURE);
    }
    fprintf(fp, "Description de la clé d'auth : %s\n", dbuf);
    /*
     * Instancier la clé en utilisant les données de l'appel (callout)
     * fournies dans la charge utile de la clé d'autorisation.
     */
    if (keyctl(KEYCTL_INSTANTIATE, key_to_instantiate,
               auth_key_payload, akp_size + 1, dest_keyring) == -1)
    {
        fprintf(fp, "KEYCTL_INSTANTIATE a échoué : %s\n",
                strerror(errno));
        exit(EXIT_FAILURE);
    }
    exit(EXIT_SUCCESS);
}

keyctl(1), add_key(2), request_key(2), keyctl(3), recursive_key_scan(3), recursive_session_key_scan(3), capabilities(7), credentials(7), keyrings(7), keyutils(7), persistent-keyring(7), process-keyring(7), session-keyring(7), thread-keyring(7), user-keyring(7), user_namespaces(7), user-session-keyring(7), request-key(8)

Les fichiers sources du noyau Documentation/security/keys/ (ou avant Linux 4.13, dans le fichier Documentation/security/keys.txt).

La traduction française de cette page de manuel a été créée par Christophe Blaess https://www.blaess.fr/christophe/, Stéphan Rafin <stephan.rafin@laposte.net>, Thierry Vignaud <tvignaud@mandriva.com>, François Micaux, Alain Portal <aportal@univ-montp2.fr>, Jean-Philippe Guérard <fevrier@tigreraye.org>, Jean-Luc Coulon (f5ibh) <jean-luc.coulon@wanadoo.fr>, Julien Cristau <jcristau@debian.org>, Thomas Huriaux <thomas.huriaux@gmail.com>, Nicolas François <nicolas.francois@centraliens.net>, Florentin Duneau <fduneau@gmail.com>, Simon Paillard <simon.paillard@resel.enst-bretagne.fr>, Denis Barbier <barbier@debian.org>, David Prévot <david@tilapin.org> et Jean-Philippe MENGUAL <jpmengual@debian.org>

Cette traduction est une documentation libre ; veuillez vous reporter à la GNU General Public License version 3 concernant les conditions de copie et de distribution. Il n'y a aucune RESPONSABILITÉ LÉGALE.

Si vous découvrez un bogue dans la traduction de cette page de manuel, veuillez envoyer un message à debian-l10n-french@lists.debian.org.

21 août 2024 Pages du manuel de Linux 6.12