keyctl(2)

الاسم
keyctl - التلاعب بمرفق إدارة المفاتيح في النواة

المكتبة
مكتبة سي المعيارية (libc، -lc)

موجز
#include <linux/keyctl.h>  /* تعريف ثوابت KEY* */
#include <sys/syscall.h>   /* تعريف ثوابت SYS_* */
#include <unistd.h>

long syscall(SYS_keyctl, int op, ...);

الوصف
تسمح keyctl() لبرامج فضاء المستخدم بإجراء تلاعب بالمفاتيح.

تُحدد العملية التي تجريها keyctl() بواسطة قيمة المعامل op. تُغلف كل عملية من هذه العمليات بواسطة مكتبة libkeyutils (التي توفرها حزمة keyutils) في دوال منفردة (انظر keyctl(3)) للسماح للمصرف بالتحقق من الأنواع.

القيم المسموح بها لـ op هي:

KEYCTL_GET_KEYRING_ID(2const)
KEYCTL_JOIN_SESSION_KEYRING(2const)
KEYCTL_UPDATE(2const)
KEYCTL_REVOKE(2const)
KEYCTL_CHOWN(2const)
KEYCTL_SETPERM(2const)
KEYCTL_DESCRIBE(2const)
KEYCTL_CLEAR(2const)
KEYCTL_LINK(2const)
KEYCTL_UNLINK(2const)
KEYCTL_SEARCH(2const)
KEYCTL_READ(2const)
KEYCTL_INSTANTIATE(2const)
KEYCTL_INSTANTIATE_IOV(2const)
KEYCTL_NEGATE(2const)
KEYCTL_REJECT(2const)
KEYCTL_SET_REQKEY_KEYRING(2const)
KEYCTL_SET_TIMEOUT(2const)
KEYCTL_ASSUME_AUTHORITY(2const)
KEYCTL_GET_SECURITY(2const)
KEYCTL_SESSION_TO_PARENT(2const)
KEYCTL_INVALIDATE(2const)
KEYCTL_GET_PERSISTENT(2const)
KEYCTL_DH_COMPUTE(2const)
KEYCTL_RESTRICT_KEYRING(2const)

قيمة الإرجاع
للاستدعاء الناجح، تعتمد قيمة الإرجاع على العملية.

عند الخطأ، تُعاد القيمة -1، ويُضبط errno للإشارة إلى الخطأ.

الأخطاء

EACCES
    العملية المطلوبة لم تكن مسموحة.

EDQUOT
    حصة المفاتيح لمستخدم المستدعِي ستُتجاوز بإنشاء مفتاح أو ربطه بحلقة المفاتيح.

EINVAL
    حجم السلسلة (بما في ذلك بايت الإنهاء الصفري) المحدد في arg3 (نوع المفتاح) أو arg4 (وصف المفتاح) تجاوز الحد (32 بايت و 4096 بايت على التوالي).

EKEYEXPIRED
    وُجد أو حُدد مفتاح منتهي الصلاحية.

EKEYREJECTED
    وُجد أو حُدد مفتاح مرفوض.

EKEYREVOKED
    وُجد أو حُدد مفتاح ملغى.

ENOKEY
    لم يُعثر على مفتاح مطابق أو حُدد مفتاح غير صالح.

ENOMEM
    فشلت إحدى روتينات تخصيص ذاكرة النواة أثناء تنفيذ استدعاء النظام.

ENOTDIR
    تُوقع مفتاح من نوع حلقة مفاتيح ولكن قُدم معرف مفتاح بنوع مختلف.

الإصدارات
يُوفّر غلاف في مكتبة libkeyutils. (تُوفّر الحزمة المرفقة ملف الترويسة <keyutils.h>). ومع ذلك، بدلاً من استخدام استدعاء النظام هذا مباشرةً، ربما تود استخدام دوال المكتبة المتنوعة المذكورة في أوصاف العمليات الفردية أعلاه.

المعايير
لينكس.

التاريخ
لينكس 2.6.10.

أمثلة
يوفر البرنامج أدناه مجموعة فرعية من وظائف برنامج request-key(8) الذي توفره حزمة keyutils. لأغراض إعلامية، يسجل البرنامج معلومات متنوعة في ملف سجل.

كما هو موضح في request_key(2)، يُستدعى برنامج request-key(8) بمعاملات سطر الأوامر التي تصف مفتاحاً سيُنشأ. يجلب برنامج المثال هذه المعاملات ويسجلها. يفترض البرنامج سلطة إنشاء المفتاح المطلوب، ثم ينشئ ذلك المفتاح.

توضح جلسة الصدفة التالية استخدام هذا البرنامج. في الجلسة، نصرف البرنامج ثم نستخدمه لاستبدال برنامج request-key(8) المعياري مؤقتاً. (لاحظ أن تعطيل برنامج request-key(8) المعياري مؤقتاً قد لا يكون آمناً في بعض الأنظمة). بينما يكون برنامج المثال الخاص بنا مثبتاً، نستخدم برنامج المثال الموضح في request_key(2) لطلب مفتاح.

    $ 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;
    Key ID is 20d035bf
    $ sudo mv /sbin/request-key.backup /sbin/request-key;

بالنظر إلى ملف السجل الذي أنشأه هذا البرنامج، يمكننا رؤية معاملات سطر الأوامر المقدمة لبرنامج المثال الخاص بنا:

    $ 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

    Key description:      user;1000;1000;3f010000;mykey
    Auth key payload:     somepayloaddata
    Destination keyring:  256e6a6
    Auth key description: .request_key_auth;1000;1000;0b010000;20d035bf

تظهر الأسطر القليلة الأخيرة من المخرجات أعلاه أن برنامج المثال كان قادراً على جلب:

•   وصف المفتاح المُراد إنشاؤه، والذي يتضمن اسم المفتاح (mykey)؛

•   حمولة مفتاح الاستيثاق، والتي تتكون من البيانات (somepayloaddata) الممرة إلى request_key(2)؛

•   حلقة مفاتيح الوجهة التي حُددت في استدعاء request_key(2)؛ و

•   وصف مفتاح الاستيثاق، حيث يمكننا رؤية أن اسم مفتاح الاستيثاق يطابق معرف المفتاح المُراد إنشاؤه (20d035bf).

حدد برنامج المثال في request_key(2) حلقة مفاتيح الوجهة بـ KEY_SPEC_SESSION_KEYRING. بفحص محتويات /proc/keys، يمكننا رؤية أن هذا قد تُرجم إلى معرف حلقة مفاتيح الوجهة (0256e6a6) الموضح في مخرجات السجل أعلاه؛ يمكننا أيضًا رؤية المفتاح المُنشأ حديثاً باسم mykey والمعرف 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;       /* حجم حمولة مفتاح الاستيثاق */
        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, "الاستخدام: %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, "الوقت: %s\n", ctime(&t));

        /*
         * تُمرّر النواة مجموعة ثابتة من المعاملات إلى البرنامج
         * الذي تنفذه؛ اجلبها.
         */
        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 = argv[7];

        fprintf(fp, "معاملات سطر الأوامر:\n");
        fprintf(fp, "  argv[0]:            %s\n", argv[0]);
        fprintf(fp, "  العملية:          %s\n", operation);
        fprintf(fp, "  المفتاح المُراد إنشاؤه: %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, "  حلقة مفاتيح الخيط:     %jx\n",
                (uintmax_t) thread_keyring);
        fprintf(fp, "  حلقة مفاتيح العملية:    %jx\n",
                (uintmax_t) process_keyring);
        fprintf(fp, "  حلقة مفاتيح الجلسة:    %jx\n",
                (uintmax_t) session_keyring);
        fprintf(fp, "\n");

        /*
         * افتراض سلطة إنشاء المفتاح المسمى في argv[2].
         */
        if (keyctl(KEYCTL_ASSUME_AUTHORITY, key_to_instantiate) == -1) {
            fprintf(fp, "فشل KEYCTL_ASSUME_AUTHORITY: %s\n",
                    strerror(errno));
            exit(EXIT_FAILURE);
        }

        /*
         * جلب وصف المفتاح المُراد إنشاؤه.
         */
        if (keyctl(KEYCTL_DESCRIBE, key_to_instantiate,
                   dbuf, sizeof(dbuf)) == -1) {
            fprintf(fp, "فشل KEYCTL_DESCRIBE: %s\n", strerror(errno));
            exit(EXIT_FAILURE);
        }

        fprintf(fp, "وصف المفتاح:      %s\n", dbuf);

        /*
         * جلب حمولة مفتاح الاستيثاق، وهي في الواقع
         * بيانات النداء المقدمة إلى 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: %s\n", strerror(errno));
            exit(EXIT_FAILURE);
        }

        auth_key_payload[akp_size] = '\0';
        fprintf(fp, "حمولة مفتاح الاستيثاق:     %s\n", auth_key_payload);

        /*
         * من باب الفضول، جلب معرف مفتاح الاستيثاق
         * وعرضه.
         */
        auth_key = keyctl(KEYCTL_GET_KEYRING_ID,
                          KEY_SPEC_REQKEY_AUTH_KEY);
        if (auth_key == -1) {
            fprintf(fp, "فشل KEYCTL_GET_KEYRING_ID: %s\n",
                    strerror(errno));
            exit(EXIT_FAILURE);
        }

        fprintf(fp, "معرف مفتاح الاستيثاق:          %jx\n", (uintmax_t) auth_key);

        /*
         * جلب معرف المفتاح لحلقة مفاتيح وجهة request_key(2).
         */
        dest_keyring = keyctl(KEYCTL_GET_KEYRING_ID,
                              KEY_SPEC_REQUESTOR_KEYRING);
        if (dest_keyring == -1) {
            fprintf(fp, "فشل KEYCTL_GET_KEYRING_ID: %s\n",
                    strerror(errno));
            exit(EXIT_FAILURE);
        }

        fprintf(fp, "حلقة مفاتيح الوجهة:  %jx\n", (uintmax_t) dest_keyring);

        /*
         * جلب وصف مفتاح الاستيثاق. يسمح لنا هذا
         * برؤية نوع المفتاح، ومعرف المستخدم، ومعرف المجموعة، والأذونات،
         * ووصف (اسم) المفتاح. من بين أشياء أخرى،
         * سنرى أن اسم المفتاح هو سلسلة ست عشرية
         * تمثل معرف المفتاح المُراد إنشاؤه.
         */
        if (keyctl(KEYCTL_DESCRIBE, KEY_SPEC_REQKEY_AUTH_KEY,
                   dbuf, sizeof(dbuf)) == -1)
        {
            fprintf(fp, "فشل KEYCTL_DESCRIBE: %s\n", strerror(errno));
            exit(EXIT_FAILURE);
        }

        fprintf(fp, "وصف مفتاح الاستيثاق: %s\n", dbuf);

        /*
         * إنشاء المفتاح باستخدام بيانات النداء التي قدمت
         * في حمولة مفتاح الاستيثاق.
         */
        if (keyctl(KEYCTL_INSTANTIATE, key_to_instantiate,
                   auth_key_payload, akp_size + 1, dest_keyring) == -1)
        {
            fprintf(fp, "فشل KEYCTL_INSTANTIATE: %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)

ملفات مصدر النواة تحت Documentation/security/keys/.

ترجمة
تُرجمت هذه الصفحة من الدليل بواسطة زايد السعيدي <zayed.alsaidi@gmail.com>

هذه الترجمة هي وثيقة مجانية؛ راجع رخصة جنو العامة الإصدار 3 (https://www.gnu.org/licenses/gpl-3.0.html) أو ما بعده للاطلاع على شروط حقوق النشر. لا توجد أي ضمانات.

إذا وجدت أي أخطاء في ترجمة صفحة الدليل هذه، يرجى إرسال بريد إلكتروني إلى قائمة بريد المترجمين: kde-l10n-ar@kde.org.