تجميعة (Assembly) البنية التحتية المشتركة للغات هي مكتبة برمجية من الكود المُصرّف تستخدم أثناء تطوير البرمجيات وتعيين الإصدارات وتعزيز أمان البرمجيات. يوجد نوعان من التجميعات: التجميعات العملياتية (EXE) والتجميعات المكتبية (DLL). تمثل التجميعة العملياتية عمليةً تستخدم الصفوف المعرفة ضمن بعض التجميعات المكتبية. تحتوي تجميعات سي إل آي على كود مكتوبٍ باللغة المشتركة الوسيطة، ويتم توليد هذا الكود عادةً من إحدى لغات البنية التحتية المشتركة للغات (كلغة سي# مثلاً)، يُصرّف هذا الكود إلى تعمليات لغة الآلة من قبل مصرف يعمل في الوقت المناسب (Just-in-time compiler). يشكل هذا المصرف في إطار عمل دوت نت جزءاً من وقت التنفيذ المشترك للغات.
يمكن للتجميعة أن تتضمن ملفاً واحداً أو أكثر. يُطلق على الملفات التي تحتوي الكود اسم وحدات (modules). يمكن للتجميعة أن تحتوي على عدة وحدات. بما أنه من الممكن استخدام لغات برمجية مختلفة لكتابة الوحدات يمكن نظرياً استخدام عدة لغات برمجية لإنشاء تجميعة (على سبيل المثال يمكن استخدام لغة سي++/سي إل آي لكتابة بعض الوحدات الخاصة بالعمليات غير المُدارة كالولوج إلى الذاكرة الخاصة ببطاقة الشبكة عن طريق المؤشرات في حين تكتب باقي الوحدات باستخدام لغة سي#). إلا أن فيجوال ستوديو لا يدعم استخدام عدة لغات برمجة ضمن تجميعة واحدة.
أسماء التجميعات
يتكون اسم التجميعة من أربعة أجزاء:
- اسم قصير. في نظام ويندوز يتناسب هذا الاسم مع الاسم الخاص بالملفات التنفيذية المحمولة (Portable Executable) (PE) بدون الامتداد.
- الثقافة؛ وهي معرّف يتفق مع ورقة طلب التعليقات رقم 1766 يقوم بتحديد الإعدادات المحلية (كالأرقام وصيغ التواريخ) الخاصة بالتجميعة. يجب أن تكون التجميعات المكتبية والعملياتية حيادية الإعدادات المحلية عموماً، إذ يجب تحديد الإعدادات المحلية فقط بالنسبة للتجميعات التبعية (Satellite assemblies).
- الإصدار. وهو رقم مكون من أربع أقسام مفصولة عن بعضها بنقاط: الإصدار الأعلى والإصدار الأدنى ورقم بناء البرمجية ورقم التنقيح.
- رمز المفتاح المعلن وهو هاش بطول 64 بت يتوافق مع المفتاح الخاص المستخدم لتوقيع التجميعة. عادةً ما يشار إلى التجميعات الموقّعة أنها تمتلك اسماً قوياً.
بما أن المفتاح المعلن المستخدم في تسمية التجميعة رقمٌ فريد يمكن لتجميعتين تحملان اسمين قويين أن تمتلكا اسم الملف التنفيذي المحمول (PE) ذاته وعلى الرغم من ذلك تستطيع البنية التحتية المشتركة اللغات من التمييز بينهما. بما أن أنظمة ملفات ويندوز (FAT32 وNTFS) تقوم فقط بتمييز أسماء الملفات التنفيذية المحمولة (PE) فإنه من غير الممكن أن يوجد تجميعتين تحملان اسم (PE) (إلا أنهما تختلفان عن بعضهما بالثقافة والإصدار ورمز المفتاح المعلن) ذاته ضمن نفس المجلد. لحل هذه المعضلة توفر البنية التحتية المشتركة للغات تجريداً اسمه (كاش التجميعات الشامل) (Global Assembly Cache) أو اختصاراً (GAC) حيث يتم التعامل معه وقت التنفيذ كأنه مجلد واحد على الرغم من أنه عبارة عن مجموعة من المجلدات التي تتضمن مجلدات أخرى فرعية منعاً لتضارب الأسماء الملفات التنفيذية المحمولة.
يتم توقيع التجميعة باستخدام المفتاح الخاص بهدف منع الهجمات الانتحالية التي يحاول المهاجم فيها تمرير تجميعة ما على اعتبار أنها تجميعة أخرى. يحتفظ مطور التجميعة بالمفتاح الخاص لنفسه دون مشاركته مع أحد بحيث لا يستطيع المهاجم الولوج إلى هذا المفتاح ولا يتمكن من تخمينه. وبهذا لا يستطيع المهاجم جعل تجميعته تنتحل صفات تجميعة أخرى بسبب فقدانه لإمكانية توقيعها بتفس المفتاح الخاص. يشتمل إجراء توقيع التجميعة على تكوين هاش من الأجزاء الهامة من التجميعة ومن ثم تشفير هذا الهاش باستخدام المفتاح الخاص. يُخزن الهاش داخل التجميعة مع المفتاح المعلن، يُفك تشفير الهاش باستخدام المفتاح العام. عندما يحمل وقت التنفيذ المشترك للغات التجميعات ذات الأسماء القوية يقوم بتوليد هاش من كل تجميعة ويقارنه مع الهاش الذي تم فك تشفيره. في حال التطابق يتأكد وقت التنفيذ المشترك للغات أن المفتاح المعلن الموجود داخل الملف (وبالتالي رمز المفتاح المعلن) يرتبط بالمفتاح الخاص المستخدم لتوقيع التجميعة. مما يعني أن المفتاح المعلن من ملكية ناشر التجميعة لاغياً بذلك احتمال حصول هجوم انتحالي.
التجميعات وأمن البنية التحتية المشتركة للغات
يعتمد أمن الولوج للكود الخاص بالبنية التحتية المشتركة على كل من التجميعات والدليل (Evidence). يمكن للدليل أن يكون أي شيء يمكن استنتاجه من التجميعة نفسها إلا أنه يبنى عموماً من كود التجميعة المصدري - سواءً أكانت التجميعة التجميعة محملة من الانترنت أو الانترانت أو مثبتة على الآلة المحلية (إذا تم تحميل التجميعة من آلة أخرى فإنها توضع في صندوق رملي داخل كاش التجميعات الشامل (GAC) ولا تعامَل على أنها مثبتة ضمن الآلة المحلية). تطبق السماحيات على كامل التجميعات ويمكن للتجميعة أن تصرح عن الحد الأدنى من السماحيات الذي تحتاجه من خلال سمات مخصصة لهذا الغرض. أثناء تحميل التجميعة يقوم وقت التنفيذ المشترك للغات باستخدام الدليل لخلق مجموعة من السماحيات مكونة من واحدة أو أكثر من سماحيات ولوج الكود. بعد ذلك يقوم وقت التنفيذ المشترك للغات بالتأكد من أن مجموعة السماحيات تحتوي على السماحيات الضرورية التي تحددها التجميعة.
تقوم البنية التحتية المشتركة للغات بطلب أمني خاص بصلاحية ولوج الكود. يعني ذلك أن الكود يستطيع تنفيذ نشاط حساس فقط عندما تتمتع كافة التجميعات الخاصة بالطرق الموجودة في مكدس الاستدعاءات بالسماحات المطلوبة. في حال كانت إحدى هذه التجميعات لا تتمتع بالسماحيات المطلوبة يتم إلقاء استثناء أمني.
كما يمكن للبنية التحتية المشتركة للغات أن تقدم طلباً مرتبطاً (Linked Demand) للحصول على السماحيات من مكدس الاستدعاء. في هذه الحالة يقوم وقت التنفيذ المشترك للغات بالتعامل مع طريقة واحدة، وهي تلك الموجودة في قمة مكدس الاستدعاءات بحثاً عن السماحيات المحددة. في هذه الحالة يفترض وقت التنفيذ المشترك للغات أن بقية الطرق تتمتع السماحيات المطلوبة.
التجميعات التبعية
بشكل عام يجب أن تحتوي التجميعات على موارد حيادية الثقافة. في حال أراد المطور مَركزة (Localize) التجميعة (على سبيل المثال استخدام سلاسل نصية مختلفة للغات المختلفة) يجب اعتماد التجميعات التبعية، وهي تجميعات خاصة تتضمن موارداً فقط. إن التجميعة التبعية -كما يشير الاسم- ترتبط بتجميعة أخرى تدعى التجميعة الرئيسية. يجب أن تتضمن تلك التجميعة (مثل التجميعة lib.dll) على موارد حيادية الثقافة (تشير مايكروسوفت لها بالإنكليزية العالمية إلا أنها تعني ضمناً الإنكليزية الأمريكية). تمتلك كل تجميعة تبعية اسم التجميعة التي تتبع لها ملحوقاً بـresouce. (على سبيل المثال lib.resources.dll). تعطى التجميعة اسماً غير حيادي الثقافة وبما أن أنظمة ملفات ويندوز (FAT32 وNTFS) تهمل هذه الأسماء فإن ذلك يعني وجود عدة ملفات تمتلك اسم الملف التنفيذي المحمول ذاته ضمن نفس المجلد، إلا أن هذا بالطبع غير ممكن، لذلك تخزن التجميعات التبعية في مجلدات فرعية داخل مجلد التطبيق. على سبيل المثال تمتلك تجميعة اللغة الإنكليزية للملكة المتحدة الاسم التالي ضمن البنية التحتية المشتركة للغات "lib.resources Version=0.0.0.0 Culture=en-GB PublicKeyToken=null" ويتم تخزين الملف التنفيذي المحمول (PE) ذو الاسم lib.resources.dll ضمن المجلد الفرعي en-GB.
تُحمل التجميعات التبعية عن طريق الصف System.Resources.ResourceManager
. ويزوده المطور باسم المورد ومعلومات حول التجميعة الأساسية (التي يجب أن تمتلك موارداً حيادية). يقوم الصف ResourceManager
بقراءة معلومات الثقافة الخاصة بالآلة ويستخدم هذه المعلومة بالإضافة إلى اسم التجميعة الأساسي للحصول على اسم التجميعة التبعية والمجلد الفرعي الذي يتضمنها ويقوم بعد ذلك بتحميل التجميعة للحصول على الموارد المطلوبة.
لغة التجميعة
تُبنى التجميعة باستخدام كود اللغة الوسيطة العامة، وهي -كما يشير الاسم- لغةٌ وسيطة. يقوم إطار العمل بتحويل الكود المكتوب بهذه اللغة إلى كود لغة التجميع. يوضح المثال التالي كود اللغة الوسيطة العامة الخاص ببرنامج أهلاً بالعالم:
.method private hidebysig static void Main(string[] args) cil managed { .entrypoint .custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 ) // Code size 11 (0xb) .maxstack 1 IL_0000: ldstr "Hello World" IL_0005: call void [mscorlib]System.Console::WriteLine(string) IL_000a: ret } // end of method Class1::Main
يقوم هذا الكود بتحميل السلسلة المحرفية إلى المكدس ومن ثم يستدعي الوظيفة WriteLine منهياً التنفيذ بعد ذلك.