Язык требования подписывания кода

Когда Вы используете codesign команда для подписания блока кода можно указать внутренние требования; т.е. критерии, которые Вы рекомендуете, должны использоваться для оценки подписи кода. Это до верификатора, чтобы решить, применить ли внутренние требования или некоторый другой набор требований при решении, как обработать код со знаком. Вы используете язык требования кода, описанный в этой главе при указании требований к codesign или csreq команда (см. страницы руководства для codesign(1) и csreq(1)).

В этой главе описываются исходный код языка требования. Можно скомпилировать ряд требований и сохранить их в двоичной форме с помощью csreq команда. Можно обеспечить требования для codesign команда или как исходный код или как двоичный файл. Оба codesign и csreq команды могут преобразовать двоичный набор требования в текст. Несмотря на то, что существует некоторая гибкость в синтаксисе исходного кода (например, кавычки могут всегда использоваться вокруг строковых констант, но не всегда требуются), преобразование от двоичного файла до текста всегда использует ту же форму:

Синтаксис языка

Некоторые основные характеристики синтаксиса языка:

Оценка требований

Требование составляет выражение без побочных эффектов. Каждое требование может иметь любое число подвыражений, каждое из которых оценено с булевской переменной (следовать-сбой) результат. Нет никакого определенного порядка оценки. Подвыражения объединены с помощью логических операторов в выражении для получения полного булева результата для выражения. Даже если некоторые подвыражения перестали работать, В зависимости от используемых операторов может успешно выполниться выражение. Например, выражение

anchor apple or anchor = "/var/db/yourcorporateanchor.cert"

успешно выполняется, если любое подвыражение успешно выполняется — т.е. если код был подписан или Apple или Вашей компанией — даже при том, что одно из подвыражений, несомненно, перестанет работать.

Если ошибка происходит во время оценки, с другой стороны, оценка сразу останавливается и codesign или csreq команда возвращается с кодом результата, указывающим причину отказа.

Константы

В этом разделе описываются использование строки, целого числа, значения хэш-функции и двоичных констант на языке требования подписывания кода.

Строковые константы

Строковые константы должны быть включены двойными кавычками (" ") если строка не содержит только буквы, цифры, и периоды (.), когда кавычки являются дополнительными. Абсолютные пути к файлам, запускающиеся с наклонной черты, не требуют кавычек, если они не содержат пробелы. Например:

com.apple.mail                       //no quotes are required
"com.apple.mail"                     //quotes are optional
"My Company's signing identity"      //requires quotes for spaces and apostrophe
/Volumes/myCA/root.crt               //no quotes are required
"/Volumes/my CA/root.crt"            //space requires quotes
"/Volumes/my_CA/root.crt"            //underscore requires quotes

Никогда не неправильно включить строку в кавычки — если в сомнении, используйте кавычки.

Используйте наклонную черту влево, чтобы «выйти» из любого символа. Например:

"one \" embedded quote"              //one " embedded quote
"one \\ embedded backslash"          //one \ embedded backslash

Нет ничего специального о символе одинарной кавычки (').

Целочисленные константы

Целочисленные константы записаны, как десятичные константы находятся в C. Язык не позволяет префиксы основания (такой как 0x) или продвижение плюс или минус (+ или -) знаки.

Константы хеша

Значения хэш-функции записаны любой как шестнадцатеричное число в кавычках, которым предшествуют H, или как путь к файлу, содержащему двоичный сертификат. При использовании первой формы число должно включать точное число цифр в значении хэш-функции. Хеш SHA 1 (единственный вид, в настоящее время поддерживаемый), требует точно 40 цифр; например:

H"0123456789ABCDEFFEDCBA98765432100A2BC5DA"

Можно использовать или прописные или строчные буквы (A..F или a..f) в шестнадцатеричных числах.

При указании пути к файлу компилятор читает двоичный сертификат и вычисляет хеш для Вас. Скомпилированная версия кода требования включает только хеш; файл сертификата и путь не сохраняются. При преобразовании требования назад в текст Вы получаете шестнадцатеричный постоянный хеш. Путь к файлу должен указать на файл, содержащий закодированный сертификат DER X.509. Никакие контейнерные формы (PKCS7, PKCS12) не позволяются, и при этом форма OpenSSL «PEM» не поддерживается.

Переменные

На языке требования в настоящее время нет никаких переменных.

Логические операторы

Язык требования включает следующие логические операторы, в порядке уменьшающегося приоритета:

Эти операторы могут использоваться для объединения подвыражений в более сложные выражения. Оператор отрицания (!) унарный префиксный оператор. Другие - инфиксные операторы. Круглые скобки могут использоваться для переопределения приоритета операторов.

Поскольку язык свободен от побочных эффектов, порядок оценки подвыражений является неуказанным.

Операции сравнения

Язык требования включает следующие операторы сравнения:

Настоящее значения (exists) оператор является унарным суффиксным оператором. Другие - инфиксные операторы.

Нет никаких операторов для несоответствий (не равны, не больше, чем, и т.д.). Используйте оператора отрицания (!) вместе с операторами сравнения, чтобы сделать сравнения несоответствия.

Равенство

Все операции равенства сравнивают некоторое значение с константой. Значение и постоянный должно иметь тот же тип: строка соответствует строковую константу, значение данных соответствует шестнадцатеричную константу. Работа равенства оценивает к true если значение существует и равно константе. Сопоставление строк использует те же правила соответствия как CFString (см. ссылку CFString).

В выражениях соответствия (см. Информацию, Часть Сертификата и Право), подстроки строковых констант могут быть соответствующими при помощи * подстановочный символ:

  • value = *constant* true если значение существует, и любая подстрока значения соответствует константу; например:

    • thunderbolt = *under*

    • thunderbolt = *thunder*

    • thunderbolt = *bolt*

  • value = constant* true если значение существует и начинается с константы; например:

    • thunderbolt = thunder*

    • thunderbolt = thun*

  • value = *constant true если значение существует и заканчивается константой; например:

    • thunderbolt = *bolt

    • thunderbolt = *underbolt

Если константа записана с кавычками, звездочки должны быть вне кавычек. Звездочка в кавычках взята буквально. Например:

  • "ten thunderbolts" = "ten thunder"* true

  • "ten thunder*bolts" = "ten thunder*"* true

  • "ten thunderbolts" = "ten thunder*" false

Неравенство

Операции неравенства сравнивают некоторое значение с константой. Значение и постоянный должно иметь тот же тип: строка соответствует строковую константу, значение данных соответствует шестнадцатеричную константу. Сравнения строк используют те же правила соответствия как CFString с kCFCompareNumerically флаг опции; например, "17.4" больше, чем "7.4".

Существование

Оператор существования тестирует, существует ли значение. Это оценивает к false только если значение не существует вообще или является точно булевым значением false. Пустая строка и число 0 как полагают, существуют.

Ограничения

Несколько ключевых слов на языке требования используются, чтобы потребовать что определенные сертификаты присутствовать или другие условия быть встреченными.

Идентификатор

Выражение

identifier = постоянный

если строка уникального идентификатора, встроенная в подпись кода, точно равна константе, успешно выполняется. Знак «равно» является дополнительным в выражениях идентификатора. Подписание идентификаторов может быть протестировано только на точное равенство; подстановочный символ (*) не может использоваться с ограничением идентификатора, и при этом идентификаторы не могут быть протестированы на неравенство.

Информация

Выражение

info [ключ]выражение соответствия

если значение, связанное с верхним уровнем, вводит код, успешно выполняется info.plist файл соответствует выражение соответствия, где выражение соответствия может включать любого из операторов, перечисленных в Операциях Сравнения и Логических операторах. Например:

info [CFBundleShortVersionString] < "17.4"

или

info [MySpecialMarker] exists

Необходимо указать ключ как строковую константу.

Если значение указанного ключа является строкой, соответствие применяется к нему непосредственно. Если значение является массивом, это должен быть массив строк, и соответствие сделано каждому, в свою очередь, следованием, если соответствует какой-либо из них. Подстроки строковых констант могут быть соответствующими при помощи любого выражения соответствия (см. Операции Сравнения).

Если код имеет нет info.plist файл, или info.plist не содержит указанный ключ, это выражение оценивает к false не возвращая ошибку.

Сертификат

Ограничения сертификата обращаются к сертификатам в цепочке сертификата, используемой для проверки подписи. Большая часть использования certificate ключевое слово принимает целое число, указывающее позицию сертификата в цепочке: положительные целые числа рассчитывают от листа (0) к привязке. Отрицательные целые числа рассчитывают назад от привязки (-1). Например, certificate 1 промежуточный сертификат, использовавшийся для подписания листа (т.е. сертификат подписания), и certificate -2 указывает сертификат, непосредственно подписанный привязкой. Обратите внимание на то, что это соглашение совпадает с, который использовал для индексации массива в языках программирования Ruby и Perl:

Привязка

Первое промежуточное звено

Второе промежуточное звено

Лист

certificate 3

certificate 2

certificate 1

certificate 0

certificate -1

certificate -2

certificate -3

certificate -4

Другие ключевые слова включают:

  • certificate root— сертификат привязки; то же как сертификат 0

  • anchor— то же как certificate root

  • certificate leaf— сертификат подписания; то же как certificate -1

Если нет никакого сертификата в указанной позиции, ограничение оценивает к false не возвращая ошибку.

Если код был подписан с помощью оперативной подписи, нет никаких сертификатов вообще, и все ограничения сертификата оценивают к false. (Оперативная подпись создается путем подписания с псевдоидентификационными данными - (тире). Оперативная подпись не использует или записывает криптографические идентификационные данные, и таким образом идентифицирует точно и только одна подписываемая программа.)

Если код был подписан самоподписанным сертификатом, то лист и корень обращаются к тому же единственному сертификату.

Целый сертификат

Чтобы потребовать, чтобы определенный сертификат присутствовал в цепочке сертификата, используйте форму

certificate позиция = хеш

или одна из эквивалентных форм, обсужденных выше, такой как anchor = хеш. Константы хеша описаны в Константах Хеша.

Для собственного кода Apple, подписанного Apple, можно использовать краткую форму

anchor apple

Для кода, подписанного Apple, включая код использование со знаком сертификата подписания, выпущенного Apple другим разработчикам, используют форму

anchor apple generic

Часть сертификата

Для соответствия четко определенного элемента сертификата используйте форму

certificate позиция[элемент]выражение соответствия

где выражение соответствия может включать * подстановочный символ и любой из операторов, перечисленных в Логических операторах и Операциях Сравнения. В настоящее время поддерживаемые элементы следующие:

Имя элемента

Значение

Комментарии

subject.CN

Подчиненное общее название

Показанный в утилите Keychain Access

subject.C

Подчиненное название страны

subject.D

Подчиненное описание

subject.L

Подчиненная местность

subject.O

Подчиненная организация

Обычно компания или организация

subject.OU

Подчиненная организационная единица

subject.STREET

Подчиненный адрес расположения

Поле Certificate OID

Для проверки на существование любого поля сертификата, идентифицированного его идентификатором объекта X.509 (OID), используйте форму

certificate позиция [field.OID] exists

Идентификатор объекта должен быть записан в числовой форме (x.y.z...), и может быть OID расширения сертификата или стандартного элемента сертификата, как определено стандартом CSSM (см. Главу 31 в Коллективной безопасности: CDSA и CSSM, версия 2 (с исправлениями) Open Group (http://www .opengroup.org/security/cdsa.htm)).

Доверяемый

Выражение

certificate позиция trusted

если сертификат, указанный позицией, отмечен доверяемый для политики сертификата для подписывания кода в базе данных Trust Settings системы, успешно выполняется. Параметром позиции является целое число или ключевое слово, указывающее позицию сертификата в цепочке; посмотрите обсуждение в соответствии с Сертификатом.

Выражение

anchor trusted

успешно выполняется, если какой-либо сертификат в цепочке сертификата подписи отмечен доверяемый для политики сертификата для подписывания кода в базе данных Trust Settings системы, при условии, что никакой сертификат ближе листовому сертификату не явно недоверяем.

Таким образом, использование trusted ключевое слово с позицией сертификата проверяет только указанный сертификат при использовании его с anchor ключевое слово проверяет все сертификаты, давая приоритет установке доверия, найденной самой близкой к листу.

Сертификаты могут иметь доверительные настройки в расчете на пользователя и в масштабе всей системы доверять настройкам и положить, что настройки применяются к определенным политикам. trusted ключевое слово на языке требования подписывания кода заставляет доверие быть проверенным на указанный сертификат или сертификаты для пользователя, выполняющего проверку. Если нет никаких настроек для того пользователя, то параметры настройки системы используются. Во всех случаях только проверяются доверительные настройки для политики подписывания кода. Политики и доверие обсуждены в Сертификате, Ключе и Руководстве по программированию Trust Services.

Право

Выражение

entitlement [ключ] выражение соответствия

успешно выполняется, если значение связалось с указанным ключом во встроенном дающем право выражении соответствия соответствий словаря подписи, где выражение соответствия может включать * подстановочный символ и любой из операторов, перечисленных в Логических операторах и Операциях Сравнения. Необходимо указать ключ как строковую константу. Дающий право словарь включен в подписи для определенных платформ.

Хеш каталога кода

Выражение

cdhash постоянный хешем

если значение этого хеша точно равняется указанному постоянному хешу, вычисляет хеш SHA 1 ресурса CodeDirectory программы и успешно выполняется.

Ресурс CodeDirectory является основным каталогом содержания программы. Это состоит из имеющего версию заголовка, сопровождаемого массивом хешей. Этот массив состоит из ряда дополнительных специальных хешей для других ресурсов плюс вектор хешей для страниц основной исполнимой программы. Ресурсы CodeSignature и CodeDirectory вместе составляют подпись кода.

Можно использовать утилиту элемента кода с (по крайней мере) тремя уровнями многословия для получения хеша, постоянного из ресурса CodeDirectory программы:

    $ codesign -dvvv /bin/ls
    ...
    CodeDirectory v=20001 size=257 flags=0x0(none) hashes=8+2 location=embedded
    CDHash=4bccbc576205de37914a3023cae7e737a0b6a802
    ...

Поскольку каталог кода изменяется каждый раз, когда изменения программы нетривиальным способом, этот тест может использоваться для однозначной идентификации одной определенной версии программы. Когда операционная система подписывает иначе программу без знака (так, чтобы цепочка для ключей или Родительский контроль могли распознать программу, например), это использует это требование.

Наборы требования

Набор требования является набором отличных требований, каждый индексированный (теговый) с кодом типа. Выражение

тег => требование

применяет требование к типу кода, обозначенного тегом, где возможные теги

Основное использование наборов требования должно представлять внутренние требования кода со знаком. Например:

    codesign -r='host => anchor apple and identifier com.apple.perl designated => anchor /my/root and identifier com.bar.foo'

устанавливает внутренние требования некоторого кода, имея требование узла anchor apple and identifier com.apple.perl (“Я - сценарий Perl, и я хочу быть выполненным интерпретатором Perl Apple”), и явное определяемое требование anchor /my/root and identifier com.bar.foo. Обратите внимание на то, что это наборы команд никакой гость или требования библиотеки.

Можно также поместить набор требования в файл и указать на файл:

    codesign -r myrequirements.rqset

где файл myrequirements.rqset мог бы содержать:

    //internal requirements
      host => anchor apple and identifier com.apple.perl //require Apple's Perl interpreter
      designated => anchor /my/root and identifier com.bar.foo