我正在维护一个github项目,该项目旨在自动化干净的macOS安装,macOS定制(完整的系统首选项和更多设置)以及对应用程序和系统的更新。
https://github.com/tiiiecherle/osx_install_config
脚本之一在系统首选项-安全-隐私下设置了首选项。
https://github.com/tiiiecherle/osx_install_config/blob/master/11_system_and_app_preferences/11a_system_preferences_privacy_sqlite_mojave.sh
每个macOS应用程序都有一个csreq,这似乎是每个应用程序的指纹/校验和。在macOS Mojave之前,不需要显式设置该值,并且正在用“?”替换csreq。例如,允许访问终端:
DATABASE_SYSTEM="/Library/Application Support/com.apple.TCC/TCC.db"
INPUT_SERVICE=kTCCServiceAccessibility
APP_ID=com.apple.Terminal
PERMISSION_GRANTED=1
APP_CSREQ=X'FADE0C000000003000000001000000060000000200000012636F6D2E6170706C652E5465726D696E616C000000000003'
### working, but no csreq
sudo sqlite3 "$DATABASE_SYSTEM" "REPLACE INTO access VALUES('"$INPUT_SERVICE"','"$APP_ID"',0,$PERMISSION_GRANTED,1,NULL,NULL,NULL,?,NULL,0,?);"
### working with csreq
sqlite3 "$DATABASE_USER" "REPLACE INTO access VALUES('"$INPUT_SERVICE"','"$APP_ID"',0,$PERMISSION_GRANTED,1,$APP_CSREQ,NULL,NULL,?,NULL,NULL,?);"
这仍然有效,但是macOS Mojave引入了更多安全性设置,并且为了通过命令行正确设置自动化,需要两个应用程序的csreqs(自动和自动应用程序),例如,允许终端自动执行系统设置:
DATABASE_USER="/Users/"$USER"/Library/Application Support/com.apple.TCC/TCC.db"
SOURCE_APP_ID=com.apple.Terminal
SOURCE_APP_CSREQ=X'FADE0C000000003000000001000000060000000200000012636F6D2E6170706C652E5465726D696E616C000000000003'
PERMISSION_GRANTED=1
AUTOMATED_APP_ID=com.apple.systemevents
AUTOMATED_APP_CSREQ=X'FADE0C000000003400000001000000060000000200000016636F6D2E6170706C652E73797374656D6576656E7473000000000003'
sqlite3 "$DATABASE_USER" "REPLACE INTO access VALUES('kTCCServiceAppleEvents','"$SOURCE_APP_ID"',0,$PERMISSION_GRANTED,1,$SOURCE_APP_CSREQ,NULL,0,'"$AUTOMATED_APP_ID"',$AUTOMATED_APP_CSREQ,NULL,?);"
如果将csreq替换为问号“?”,则该条目有效,但根本不显示在系统偏好设置的GUI中。
当您在请求许可时单击允许时,系统会生成csreq,然后可以从数据库中读取该csreq。为了通过命令行进行正确的输入,我想从命令行上的应用程序读取/生成正确的csreq,而无需从tcc.db中读取它,因为它似乎随应用程序的每个版本而变化。
感谢您的任何帮助
编辑
非常感谢Keith Johnson的出色解释,并在很大程度上解决了该问题。
按照他的回答,我能够在新的脚本配置文件中实现csreq。
https://github.com/tiiiecherle/osx_install_config/blob/master/_config_file/shellscriptsrc.sh
在函数
env_set_apps_security_permissions
和env_set_apps_automation_permissions
中。我还无法解决的问题是,使用脚本编辑器或自动器为未签名的小程序或小滴获取csreq。
PATH_TO_APP="/Applications/brew_casks_update.app"
codesign --detached "$PATH_TO_APP".sig -s - "$PATH_TO_APP"
SOURCE_APP_CSREQ_STRING=$(codesign -d -r- --detached "$PATH_TO_APP".sig "$PATH_TO_APP")
echo "$SOURCE_APP_CSREQ_STRING" | csreq -r- -b /tmp/csreq.bin
Executable=/Applications/brew_casks_update.app/Contents/MacOS/applet error: invalid or corrupted code requirement(s) Requirement syntax error(s): line 2:1: unexpected end of file
如果我手动添加它并从数据库中读取字符串,则它具有有效的csreq。如果也可以解决这个问题,将得到完全解决。那真是太好了。
谢谢
最佳答案
背景
csreq blob本身的格式看起来并不复杂,如果您想花哨的话,可以在Security.Framework中找到源代码来帮助解释其含义。[1]它基本上是一个魔术头(0xFADE0C00),后跟32位长度(blob的大小),然后是一些不同的“操作”。
值得庆幸的是,已经有一些实用程序可以用来处理csreq blob,因此我们无需对此进行深入研究。
解码csreq blob,并找出其来源
让我以上面的Terminal.app
为例。苹果提供了一个名为csreq
的工具,可用于将需求从其二进制表示形式转换为文本表示形式(然后再次转换)。
# Convert the hex string into a binary blob
$ BLOB="FADE0C000000003000000001000000060000000200000012636F6D2E6170706C652E5465726D696E616C000000000003"
$ echo "$BLOB" | xxd -r -p > terminal-csreq.bin
# Ask csreq to tell us what it means
$ csreq -r -t < terminal-csreq.bin
identifier "com.apple.Terminal" and anchor apple
因此,csreq blob只是说它想将标识符为“com.apple.Terminal”的应用程序与 anchor 定苹果匹配。我们可以检查Terminal.app并找到相同的需求字符串(在“指定”下)
$ codesign -d -r- /Applications/Utilities/Terminal.app
Executable=/Applications/Utilities/Terminal.app/Contents/MacOS/Terminal
designated => identifier "com.apple.Terminal" and anchor apple
让我们来看另一个示例,这次是从存储库中为virtualbox进行的[2]:
# Convert the hex string into a binary blob
BLOB="FADE0C00000000AC0000000100000006000000020000001D6F72672E7669727475616C626F782E6170702E5669727475616C426F78000000000000060000000F000000060000000E000000010000000A2A864886F76364060206000000000000000000060000000E000000000000000A2A864886F7636406010D0000000000000000000B000000000000000A7375626A6563742E4F550000000000010000000A564235453254563936330000"
$ echo "$BLOB" | xxd -r -p > vbox-csreq.bin
# Ask csreq to tell us what it means
$ csreq -r -t < vbox-csreq.bin
identifier "org.virtualbox.app.VirtualBox" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = VB5E2TV963
# ask codesign what the requirement text from the application itself is
$ codesign -d -r- /Applications/VirtualBox.app
Executable=/Applications/VirtualBox.app/Contents/MacOS/VirtualBox
designated => identifier "org.virtualbox.app.VirtualBox" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = VB5E2TV963
再一次,我们可以看到
designated
字段codesign返回的值与csreq blob包含的内容相同。如果您对需求字符串的实际含义感到好奇,apple可以提供一些文档[3]。
建立一个新的csreq blob
现在我们知道了csreq blob所包含的内容以及在何处查找等效信息,我们需要将其转换为tcc数据库所需的二进制格式。上面我们用来解码二进制Blob的
csreq
工具还能够将文本表示形式转换为二进制。# Get the requirement string from codesign
$ REQ_STR=$(codesign -d -r- /Applications/Utilities/Terminal.app/ 2>&1 | awk -F ' => ' '/designated/{print $2}')
# Convert the requirements string into it's binary representation(sadly it seems csreq requires the output to be a file; so we just throw it in /tmp)
$ echo "$REQ_STR" | csreq -r- -b /tmp/csreq.bin
# Convert the binary form to hex, and print it nicely for use in sqlite
$ REQ_HEX=$(xxd -p /tmp/csreq.bin | tr -d '\n')
$ echo "X'$REQ_HEX'"
X'fade0c000000003000000001000000060000000200000012636f6d2e6170706c652e5465726d696e616c000000000003'
此十六进制字符串与上面从tcc数据库获得的十六进制字符串相同。
奖励:未签名的二进制文件
如果要信任未签名的脚本/二进制文件并尝试使用上述方法,则会遇到一些问题:
$ codesign -d -r- ./hello.sh
./hello.sh: code object is not signed at all
阅读有关代码签名要求语言的文档
[3],在
Code Directory Hash
(强调我的名字)下有一个小字条因此,对于未签名的程序,将生成临时签名,并将其用于标识TCC(以及其他)之类的东西。
codesign
工具可用于创建临时签名,我们可以从中获取需求字符串。$ cat hello.sh
#!/bin/bash
echo "Hello World"
# Create a detached signature(so as not to modify the original binary)
$ codesign --detached ./hello.sh.sig -s - ./hello.sh
# Display the designated identifier from the detached signature
$ codesign -d -r- --detached ./hello.sh.sig ./hello.sh
Executable=/Users/keith/hello.sh
host => identifier "com.apple.bash" and anchor apple
# designated => cdhash H"70212a41efea9849e7a88afa946afa3e1b559cbe" or cdhash H"9044184bcced89d2f4bf1d75ec61a7537871eee7"
从这里我们可以继续上面给出的相同过程。
[1] https://github.com/toriningen/apple-security-framework/blob/eb36592b951817622c07a7cff65854f477054b0b/OSX/libsecurity_codesigning/lib/requirement.h#L54
[2] https://github.com/tiiiecherle/osx_install_config/blob/master/11_system_and_app_preferences/11a_app_profiles/VirtualBox.txt
[3] https://developer.apple.com/library/archive/documentation/Security/Conceptual/CodeSigningGuide/RequirementLang/RequirementLang.html
关于bash - 如何在命令行上获取macOS应用程序的csreq?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52706542/