request_key(2)

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

المكتبة
أدوات إدارة المفاتيح لينكس (libkeyutils, -lkeyutils)

موجز
#include <keyutils.h>

key_serial_t request_key(const char *type, const char *description,
                         const char *_Nullable callout_info,
                         key_serial_t dest_keyring);

الوصف
تحاول request_key() إيجاد مفتاح من النوع type المحدد مع وصف (اسم) يطابق description المحدد. إذا لم يُعثر على هذا المفتاح، يُنشأ المفتاح اختيارياً. إذا وُجد المفتاح أو أُنشئ، ترفقه request_key() بحلقة المفاتيح التي يُحدد معرفها في dest_keyring وتعيد الرقم التسلسلي للمفتاح.

تبحث request_key() أولاً بشكل متكرر عن مفتاح مطابق في جميع حلقات المفاتيح المرفقة بالعملية المستدعية. تُبحث حلقات المفاتيح بالترتيب: حلقة المفاتيح الخاصة بالخيط، حلقة المفاتيح الخاصة بالعملية، ثم حلقة المفاتيح الخاصة بالجلسة.

إذا استُدعيت request_key() من برنامج استُدعي بواسطة request_key() نيابة عن عملية أخرى لتوليد مفتاح، فسيُبحث بعد ذلك عن حلقات المفاتيح لتلك العملية الأخرى، باستخدام معرف المستخدم ومعرف المجموعة ومعرفات المجموعات الإضافية وسياق الأمان لتلك العملية الأخرى لتحديد الوصول.

البحث في شجرة حلقة المفاتيح هو بحث عرضي أولاً: تُفحص المفاتيح في كل حلقة مفاتيح بحثاً عن تطابق قبل التعمق في أي حلقات مفاتيح فرعية. فقط المفاتيح التي يملك المستدعي إذن search لها تُوجد، وحلقات المفاتيح التي يملك المستدعي إذن search لها فقط قد تُبحث.

إذا لم يُعثر على المفتاح وكان callout فارغاً (NULL)، فشلت الاستدعاء مع الخطأ ENOKEY.

إذا لم يُعثر على المفتاح وكان callout غير فارغ، تحاول النواة استدعاء برنامج في مساحة المستخدم لتحقيق المفتاح. التفاصيل مذكورة أدناه.

الرقم التسلسلي dest_keyring قد يكون لحلقة مفاتيح صالحة يملك المستدعي إذن write لها، أو قد يكون أحد معرفات حلقة المفاتيح الخاصة التالية:

KEY_SPEC_THREAD_KEYRING
    يحدد هذا حلقة المفاتيح الخاصة بالخيط للمستدعي (انظر thread-keyring(7)).

KEY_SPEC_PROCESS_KEYRING
    يحدد هذا حلقة المفاتيح الخاصة بالعملية للمستدعي (انظر process-keyring(7)).

KEY_SPEC_SESSION_KEYRING
    يحدد هذا حلقة المفاتيح الخاصة بالجلسة للمستدعي (انظر session-keyring(7)).

KEY_SPEC_USER_KEYRING
    يحدد هذا حلقة المفاتيح الخاصة بمعرف المستخدم للمستدعي (انظر user-keyring(7)).

KEY_SPEC_USER_SESSION_KEYRING
    يحدد هذا حلقة مفاتيح جلسة معرف المستخدم للمستدعي (انظر user-session-keyring(7)).

عندما يُحدد dest_keyring بالصفر 0 ولم يُجرَ بناء مفتاح، فلا يُجرى أي ربط إضافي.

وإلا، إذا كان dest_keyring صفراً 0 وبُني مفتاح جديد، سيُربط المفتاح الجديد بحلقة المفاتيح "المبدئية". بتعبير أدق، عندما تحاول النواة تحديد أي حلقة مفاتيح يجب ربط المفتاح المبني حديثاً بها، تجرب حلقات المفاتيح التالية، مبتدئة بحلقة المفاتيح المُعينة عبر عملية keyctl(2) KEYCTL_SET_REQKEY_KEYRING ومستمرة بالترتيب الموضح أدناه حتى تجد أول حلقة مفاتيح موجودة:

•   حلقة مفاتيح الطالب (KEY_REQKEY_DEFL_REQUESTOR_KEYRING، منذ لينكس 2.6.29).

•   حلقة المفاتيح الخاصة بالخيط (KEY_REQKEY_DEFL_THREAD_KEYRING؛ انظر thread-keyring(7)).

•   حلقة المفاتيح الخاصة بالعملية (KEY_REQKEY_DEFL_PROCESS_KEYRING؛ انظر process-keyring(7)).

•   حلقة المفاتيح الخاصة بالجلسة (KEY_REQKEY_DEFL_SESSION_KEYRING؛ انظر session-keyring(7)).

•   حلقة مفاتيح الجلسة لمعرف مستخدم العملية (KEY_REQKEY_DEFL_USER_SESSION_KEYRING؛ انظر user-session-keyring(7)). يُتوقع أن توجد حلقة المفاتيح هذه دائماً.

•   حلقة المفاتيح الخاصة بمعرف المستخدم (KEY_REQKEY_DEFL_USER_KEYRING؛ انظر user-keyring(7)). يُتوقع أيضًا أن توجد حلقة المفاتيح هذه دائماً.

إذا حددت عملية keyctl(2) KEYCTL_SET_REQKEY_KEYRING القيمة KEY_REQKEY_DEFL_DEFAULT (أو لم تُجرَ أي عملية KEYCTL_SET_REQKEY_KEYRING)، فتبحث النواة عن حلقة مفاتيح مبتدئة من بداية القائمة.

  طلب تحقيق مفتاح في مساحة المستخدم
إذا لم تستطع النواة إيجاد مفتاح يطابق type و description، وكان callout غير فارغ، فتحاول النواة استدعاء برنامج في مساحة المستخدم لتحقيق مفتاح بالنوع type والوصف description المحددين. في هذه الحالة، تُجرى الخطوات التالية:

(1) تنشئ النواة مفتاحاً غير محقق، U، بالنوع type والوصف description المطلوبين.

(2) تنشئ النواة مفتاح تفويض، V، يشير إلى المفتاح U ويسجل الحقائق بأن مستدعي request_key() هو:

    (2.1)
        السياق الذي يجب فيه إنشاء المفتاح U وتأمينه، و

    (2.2)
        السياق الذي يمكن من خلاله تلبية طلبات المفاتيح المرتبطة.

    يُبنى مفتاح التفويض على النحو التالي:

    •   نوع المفتاح هو ".request_key_auth".

    •   UID وGID للمفتاح هما نفس معرفات نظام الملفات المقابلة للعملية الطالبة.

    •   يمنح المفتاح صلاحيات view وread وsearch لحائز المفتاح بالإضافة إلى صلاحية view لمستخدم المفتاح.

    •   الوصف (الاسم) للمفتاح هو السلسلة السداسية العشرية التي تمثل معرف المفتاح الذي سيتم إنشاؤه في البرنامج الطالب.

    •   يؤخذ حمولة المفتاح من البيانات المحددة في callout_info.

    •   داخليًا، يسجل النواة أيضًا PID العملية التي استدعت request_key().

(3) تنشئ النواة عملية تنفذ خدمة في مساحة المستخدم مثل request-key(8) مع حلقة مفاتيح جلسة جديدة تحتوي على رابط لمفتاح التفويض V.

    يُزود هذا البرنامج بوسائط سطر الأوامر التالية:

    [0] السلسلة "/sbin/request-key".

    [1] السلسلة "create" (تشير إلى أنه سيتم إنشاء مفتاح).

    [2] معرف المفتاح الذي سيتم إنشاؤه.

    [3] UID نظام الملفات لمستدعي request_key().

    [4] GID نظام الملفات لمستدعي request_key().

    [5] معرف حلقة مفاتيح الخيط لمستدعي request_key(). قد يكون صفرًا إذا لم يتم إنشاء حلقة المفاتيح تلك.

    [6] معرف حلقة مفاتيح العملية لمستدعي request_key(). قد يكون صفرًا إذا لم يتم إنشاء حلقة المفاتيح تلك.

    [7] معرف حلقة مفاتيح الجلسة لمستدعي request_key().

    ملاحظة: كل وسيطة من وسائط سطر الأوامر التي تمثل معرف مفتاح تُرمّز بـ عشري (على عكس معرفات المفاتيح المعروضة في /proc/keys، والتي تُعرض كقيم سداسية عشرية).

(4) البرنامج المنشأ في الخطوة السابقة:

    •   يفترض السلطة لإنشاء المفتاح U باستخدام عملية keyctl(2) KEYCTL_ASSUME_AUTHORITY (عادةً عبر الدالة keyctl_assume_authority(3)).

    •   يحصل على بيانات الاستدعاء من حمولة مفتاح التفويض V (باستخدام عملية keyctl(2) KEYCTL_READ (أو بشكل أكثر شيوعًا، الدالة keyctl_read(3)) مع قيمة معرف مفتاح KEY_SPEC_REQKEY_AUTH_KEY).

    •   ينشئ المفتاح (أو ينفذ برنامجًا آخر يؤدي تلك المهمة)، مع تحديد الحمولة وحلقة المفاتيح الوجهة. (يمكن الوصول إلى حلقة المفاتيح الوجهة التي حددها الطالب عند استدعاء request_key() باستخدام معرف المفتاح الخاص KEY_SPEC_REQUESTOR_KEYRING.) يتم الإنشاء باستخدام عملية keyctl(2) KEYCTL_INSTANTIATE (أو بشكل أكثر شيوعًا، الدالة keyctl_instantiate(3)). عند هذه النقطة، يكتمل استدعاء request_key()، ويمكن للبرنامج الطالب متابعة التنفيذ.

إذا لم تنجح هذه الخطوات، فسيتم إرجاع خطأ ENOKEY إلى مستدعي request_key() وسيتم تثبيت مفتاح مؤقت منشأ بشكل سلبي في حلقة المفاتيح المحددة بواسطة dest_keyring. سينتهي صلاحية هذا المفتاح بعد بضع ثوانٍ، ولكنه سيتسبب في فشل الاستدعاءات اللاحقة لـ request_key() حتى ذلك الحين. الغرض من هذا المفتاح المنشأ بشكل سلبي هو منع العمليات (ربما المختلفة) من تقديم طلبات متكررة (تتطلب استدعاءات علوية مكلفة لـ request-key(8)) لمفتاح لا يمكن (في الوقت الحالي) إنشاؤه بشكل إيجابي.

بمجرد إنشاء المفتاح، يتم إلغاء مفتاح التفويض (KEY_SPEC_REQKEY_AUTH_KEY)، ولم يعد من الممكن الوصول إلى حلقة المفاتيح الوجهة (KEY_SPEC_REQUESTOR_KEYRING) من برنامج request-key(8).

إذا تم إنشاء مفتاح، فبغض النظر عما إذا كان مفتاحًا صالحًا أم مفتاحًا منشأ بشكل سلبي، فسيحل محل أي مفتاح آخر من نفس النوع والوصف من حلقة المفاتيح المحددة في dest_keyring.

قيمة الإرجاع
عند النجاح، تُرجع request_key() الرقم التسلسلي للمفتاح الذي وجدته أو تسببت في إنشائه. عند الخطأ، تُرجع -1 ويتم تعيين errno للإشارة إلى الخطأ.

الأخطاء

EACCES
    لم تكن حلقة المفاتيح متاحة للتعديل من قبل المستخدم.

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

EFAULT
    يشير أحد type أو description أو callout_info إلى خارج مساحة العنوان القابلة للوصول للعملية.

EINTR
    تمت مقاطعة الطلب بواسطة إشارة؛ انظر signal(7).

EINVAL
    حجم السلسلة (بما في ذلك بايت null النهائي) المحدد في type أو description تجاوز الحد (32 بايت و 4096 بايت على التوالي).

EINVAL
    تجاوز حجم السلسلة (بما في ذلك البايت الفارغ الختامي) المحدد في callout_info حجم صفحة النظام.

EKEYEXPIRED
    تم العثور على مفتاح منتهي الصلاحية، لكن لا يمكن الحصول على بديل.

EKEYREJECTED
    تم رفض محاولة إنشاء مفتاح جديد.

EKEYREVOKED
    تم العثور على مفتاح ملغي، لكن لا يمكن الحصول على بديل.

ENOKEY
    لم يتم العثور على مفتاح مطابق.

ENOMEM
    الذاكرة غير كافية لإنشاء مفتاح.

EPERM
    بدأت وسيطة type بنقطة ('.').

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

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

أُضيفت القدرة على إنشاء المفاتيح عند الطلب في Linux 2.6.13.

أمثلة
يُوضح البرنامج أدناه استخدام request_key(). تُؤخذ وسيطات type و description و callout_info لاستدعاء النظام من القيم المقدمة في وسيطات سطر الأوامر. يُحدد الاستدعاء حلقة المفاتيح الجلسة كحلقة مفاتيح هدف.

لتوضيح هذا البرنامج، ننشئ أولاً إدخالاً مناسباً في الملف /etc/request-key.conf.

    $ sudo sh;
    # echo 'create user mtk:* *   /bin/keyctl instantiate %k %c %S' \
              > /etc/request-key.conf;
    # exit;

يُحدد هذا الإدخال أنه عندما يجب إنشاء مفتاح "user" جديد بالبادئة "mtk:"، يجب تنفيذ هذه المهمة عبر عملية instantiate لأمر keyctl(1). الوسيطات المقدمة لعملية instantiate هي: معرف المفتاح غير المنشأ (%k)؛ بيانات الاستدعاء المقدمة لاستدعاء request_key() (%c)؛ وحلقة المفاتيح الجلسة (%S) للطالب (أي مستدعي request_key()). انظر request-key.conf(5) لتفاصيل هذه المحددات %.

ثم نشغل البرنامج ونتحقق من محتويات /proc/keys للتحقق من إنشاء المفتاح المطلوب:

    $ ./t_request_key user mtk:key1 "Payload data";
    $ grep '2dddaf50' /proc/keys;
    2dddaf50 I--Q---  1 perm 3f010000  1000  1000 user  mtk:key1: 12

لمثال آخر على استخدام هذا البرنامج، انظر keyctl(2).

  مصدر البرنامج
    /* t_request_key.c */

    #include <keyutils.h>
    #include <stdint.h>
    #include <stdio.h>
    #include <stdlib.h>

    int
    main(int argc, char *argv[])
    {
        key_serial_t key;

        if (argc != 4) {
            fprintf(stderr, "Usage: %s type description callout-data\n",
                    argv[0]);
            exit(EXIT_FAILURE);
        }

        key = request_key(argv[1], argv[2], argv[3],
                          KEY_SPEC_SESSION_KEYRING);
        if (key == -1) {
            perror("request_key");
            exit(EXIT_FAILURE);
        }

        printf("Key ID is %jx\n", (uintmax_t) key);

        exit(EXIT_SUCCESS);
    }

انظر أيضًا
keyctl(1), add_key(2), keyctl(2), keyctl(3), capabilities(7), keyrings(7), keyutils(7), persistent-keyring(7), process-keyring(7), session-keyring(7), thread-keyring(7), user-keyring(7), user-session-keyring(7), request-key(8)

ملفات مصدر النواة Documentation/security/keys/core.rst و Documentation/keys/request-key.rst.

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

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

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