appwrite-cli 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (413) hide show
  1. package/.github/workflows/npm-publish.yml +41 -0
  2. package/Formula/appwrite.rb +19 -0
  3. package/LICENSE.md +12 -0
  4. package/README.md +102 -0
  5. package/docs/examples/account/create-anonymous-session.md +1 -0
  6. package/docs/examples/account/create-j-w-t.md +1 -0
  7. package/docs/examples/account/create-magic-u-r-l-session.md +4 -0
  8. package/docs/examples/account/create-o-auth2session.md +5 -0
  9. package/docs/examples/account/create-recovery.md +3 -0
  10. package/docs/examples/account/create-session.md +3 -0
  11. package/docs/examples/account/create-verification.md +2 -0
  12. package/docs/examples/account/create.md +5 -0
  13. package/docs/examples/account/delete-session.md +2 -0
  14. package/docs/examples/account/delete-sessions.md +1 -0
  15. package/docs/examples/account/delete.md +1 -0
  16. package/docs/examples/account/get-logs.md +3 -0
  17. package/docs/examples/account/get-prefs.md +1 -0
  18. package/docs/examples/account/get-session.md +2 -0
  19. package/docs/examples/account/get-sessions.md +1 -0
  20. package/docs/examples/account/get.md +1 -0
  21. package/docs/examples/account/update-email.md +3 -0
  22. package/docs/examples/account/update-magic-u-r-l-session.md +3 -0
  23. package/docs/examples/account/update-name.md +2 -0
  24. package/docs/examples/account/update-password.md +3 -0
  25. package/docs/examples/account/update-prefs.md +2 -0
  26. package/docs/examples/account/update-recovery.md +5 -0
  27. package/docs/examples/account/update-session.md +2 -0
  28. package/docs/examples/account/update-verification.md +3 -0
  29. package/docs/examples/avatars/get-browser.md +5 -0
  30. package/docs/examples/avatars/get-credit-card.md +5 -0
  31. package/docs/examples/avatars/get-favicon.md +2 -0
  32. package/docs/examples/avatars/get-flag.md +5 -0
  33. package/docs/examples/avatars/get-image.md +4 -0
  34. package/docs/examples/avatars/get-initials.md +6 -0
  35. package/docs/examples/avatars/get-q-r.md +5 -0
  36. package/docs/examples/database/create-boolean-attribute.md +6 -0
  37. package/docs/examples/database/create-collection.md +6 -0
  38. package/docs/examples/database/create-document.md +6 -0
  39. package/docs/examples/database/create-email-attribute.md +6 -0
  40. package/docs/examples/database/create-enum-attribute.md +7 -0
  41. package/docs/examples/database/create-float-attribute.md +8 -0
  42. package/docs/examples/database/create-index.md +6 -0
  43. package/docs/examples/database/create-integer-attribute.md +8 -0
  44. package/docs/examples/database/create-ip-attribute.md +6 -0
  45. package/docs/examples/database/create-string-attribute.md +7 -0
  46. package/docs/examples/database/create-url-attribute.md +6 -0
  47. package/docs/examples/database/delete-attribute.md +3 -0
  48. package/docs/examples/database/delete-collection.md +2 -0
  49. package/docs/examples/database/delete-document.md +3 -0
  50. package/docs/examples/database/delete-index.md +3 -0
  51. package/docs/examples/database/get-attribute.md +3 -0
  52. package/docs/examples/database/get-collection-usage.md +3 -0
  53. package/docs/examples/database/get-collection.md +2 -0
  54. package/docs/examples/database/get-document.md +3 -0
  55. package/docs/examples/database/get-index.md +3 -0
  56. package/docs/examples/database/get-usage.md +2 -0
  57. package/docs/examples/database/list-attributes.md +2 -0
  58. package/docs/examples/database/list-collection-logs.md +4 -0
  59. package/docs/examples/database/list-collections.md +7 -0
  60. package/docs/examples/database/list-document-logs.md +5 -0
  61. package/docs/examples/database/list-documents.md +9 -0
  62. package/docs/examples/database/list-indexes.md +2 -0
  63. package/docs/examples/database/update-collection.md +7 -0
  64. package/docs/examples/database/update-document.md +6 -0
  65. package/docs/examples/functions/create-deployment.md +5 -0
  66. package/docs/examples/functions/create-execution.md +4 -0
  67. package/docs/examples/functions/create.md +9 -0
  68. package/docs/examples/functions/delete-deployment.md +3 -0
  69. package/docs/examples/functions/delete.md +2 -0
  70. package/docs/examples/functions/get-deployment.md +3 -0
  71. package/docs/examples/functions/get-execution.md +3 -0
  72. package/docs/examples/functions/get-usage.md +3 -0
  73. package/docs/examples/functions/get.md +2 -0
  74. package/docs/examples/functions/list-deployments.md +8 -0
  75. package/docs/examples/functions/list-executions.md +7 -0
  76. package/docs/examples/functions/list-runtimes.md +1 -0
  77. package/docs/examples/functions/list.md +7 -0
  78. package/docs/examples/functions/retry-build.md +4 -0
  79. package/docs/examples/functions/update-deployment.md +3 -0
  80. package/docs/examples/functions/update.md +8 -0
  81. package/docs/examples/health/get-antivirus.md +1 -0
  82. package/docs/examples/health/get-cache.md +1 -0
  83. package/docs/examples/health/get-d-b.md +1 -0
  84. package/docs/examples/health/get-queue-certificates.md +1 -0
  85. package/docs/examples/health/get-queue-functions.md +1 -0
  86. package/docs/examples/health/get-queue-logs.md +1 -0
  87. package/docs/examples/health/get-queue-usage.md +1 -0
  88. package/docs/examples/health/get-queue-webhooks.md +1 -0
  89. package/docs/examples/health/get-storage-local.md +1 -0
  90. package/docs/examples/health/get-time.md +1 -0
  91. package/docs/examples/health/get.md +1 -0
  92. package/docs/examples/locale/get-continents.md +1 -0
  93. package/docs/examples/locale/get-countries-e-u.md +1 -0
  94. package/docs/examples/locale/get-countries-phones.md +1 -0
  95. package/docs/examples/locale/get-countries.md +1 -0
  96. package/docs/examples/locale/get-currencies.md +1 -0
  97. package/docs/examples/locale/get-languages.md +1 -0
  98. package/docs/examples/locale/get.md +1 -0
  99. package/docs/examples/projects/create-domain.md +3 -0
  100. package/docs/examples/projects/create-key.md +4 -0
  101. package/docs/examples/projects/create-platform.md +7 -0
  102. package/docs/examples/projects/create-webhook.md +8 -0
  103. package/docs/examples/projects/create.md +13 -0
  104. package/docs/examples/projects/delete-domain.md +3 -0
  105. package/docs/examples/projects/delete-key.md +3 -0
  106. package/docs/examples/projects/delete-platform.md +3 -0
  107. package/docs/examples/projects/delete-webhook.md +3 -0
  108. package/docs/examples/projects/delete.md +3 -0
  109. package/docs/examples/projects/get-domain.md +3 -0
  110. package/docs/examples/projects/get-key.md +3 -0
  111. package/docs/examples/projects/get-platform.md +3 -0
  112. package/docs/examples/projects/get-usage.md +3 -0
  113. package/docs/examples/projects/get-webhook.md +3 -0
  114. package/docs/examples/projects/get.md +2 -0
  115. package/docs/examples/projects/list-domains.md +2 -0
  116. package/docs/examples/projects/list-keys.md +2 -0
  117. package/docs/examples/projects/list-platforms.md +2 -0
  118. package/docs/examples/projects/list-webhooks.md +2 -0
  119. package/docs/examples/projects/list.md +7 -0
  120. package/docs/examples/projects/update-auth-limit.md +3 -0
  121. package/docs/examples/projects/update-auth-status.md +4 -0
  122. package/docs/examples/projects/update-domain-verification.md +3 -0
  123. package/docs/examples/projects/update-key.md +5 -0
  124. package/docs/examples/projects/update-o-auth2.md +5 -0
  125. package/docs/examples/projects/update-platform.md +7 -0
  126. package/docs/examples/projects/update-service-status.md +4 -0
  127. package/docs/examples/projects/update-webhook.md +9 -0
  128. package/docs/examples/projects/update.md +12 -0
  129. package/docs/examples/storage/create-bucket.md +11 -0
  130. package/docs/examples/storage/create-file.md +6 -0
  131. package/docs/examples/storage/delete-bucket.md +2 -0
  132. package/docs/examples/storage/delete-file.md +3 -0
  133. package/docs/examples/storage/get-bucket-usage.md +3 -0
  134. package/docs/examples/storage/get-bucket.md +2 -0
  135. package/docs/examples/storage/get-file-download.md +3 -0
  136. package/docs/examples/storage/get-file-preview.md +14 -0
  137. package/docs/examples/storage/get-file-view.md +3 -0
  138. package/docs/examples/storage/get-file.md +3 -0
  139. package/docs/examples/storage/get-usage.md +2 -0
  140. package/docs/examples/storage/list-buckets.md +7 -0
  141. package/docs/examples/storage/list-files.md +8 -0
  142. package/docs/examples/storage/update-bucket.md +11 -0
  143. package/docs/examples/storage/update-file.md +5 -0
  144. package/docs/examples/teams/create-membership.md +6 -0
  145. package/docs/examples/teams/create.md +4 -0
  146. package/docs/examples/teams/delete-membership.md +3 -0
  147. package/docs/examples/teams/delete.md +2 -0
  148. package/docs/examples/teams/get-membership.md +3 -0
  149. package/docs/examples/teams/get-memberships.md +8 -0
  150. package/docs/examples/teams/get.md +2 -0
  151. package/docs/examples/teams/list.md +7 -0
  152. package/docs/examples/teams/update-membership-roles.md +4 -0
  153. package/docs/examples/teams/update-membership-status.md +5 -0
  154. package/docs/examples/teams/update.md +3 -0
  155. package/docs/examples/users/create.md +5 -0
  156. package/docs/examples/users/delete-session.md +3 -0
  157. package/docs/examples/users/delete-sessions.md +2 -0
  158. package/docs/examples/users/delete.md +2 -0
  159. package/docs/examples/users/get-logs.md +4 -0
  160. package/docs/examples/users/get-prefs.md +2 -0
  161. package/docs/examples/users/get-sessions.md +2 -0
  162. package/docs/examples/users/get-usage.md +3 -0
  163. package/docs/examples/users/get.md +2 -0
  164. package/docs/examples/users/list.md +7 -0
  165. package/docs/examples/users/update-email.md +3 -0
  166. package/docs/examples/users/update-name.md +3 -0
  167. package/docs/examples/users/update-password.md +3 -0
  168. package/docs/examples/users/update-prefs.md +3 -0
  169. package/docs/examples/users/update-status.md +3 -0
  170. package/docs/examples/users/update-verification.md +3 -0
  171. package/index.js +49 -0
  172. package/install.sh +165 -0
  173. package/ldid/COPYING +661 -0
  174. package/ldid/Makefile +51 -0
  175. package/ldid/control +12 -0
  176. package/ldid/control.sh +5 -0
  177. package/ldid/deb.sh +10 -0
  178. package/ldid/ios.sh +2 -0
  179. package/ldid/ldid.cpp +3253 -0
  180. package/ldid/ldid.hpp +164 -0
  181. package/ldid/libplist/.github/workflows/build.yml +62 -0
  182. package/ldid/libplist/.github/workflows/codeql-analysis.yml +71 -0
  183. package/ldid/libplist/AUTHORS +28 -0
  184. package/ldid/libplist/COPYING +340 -0
  185. package/ldid/libplist/COPYING.LESSER +502 -0
  186. package/ldid/libplist/Makefile.am +20 -0
  187. package/ldid/libplist/NEWS +252 -0
  188. package/ldid/libplist/README.md +114 -0
  189. package/ldid/libplist/aclocal.m4 +1729 -0
  190. package/ldid/libplist/autogen.sh +26 -0
  191. package/ldid/libplist/configure.ac +292 -0
  192. package/ldid/libplist/cython/Makefile.am +53 -0
  193. package/ldid/libplist/cython/plist.pxd +78 -0
  194. package/ldid/libplist/cython/plist.pyx +947 -0
  195. package/ldid/libplist/cython/plist_util.c +40 -0
  196. package/ldid/libplist/cython/plist_util.h +5 -0
  197. package/ldid/libplist/docs/Makefile.am +3 -0
  198. package/ldid/libplist/docs/plistutil.1 +62 -0
  199. package/ldid/libplist/fuzz/Makefile.am +43 -0
  200. package/ldid/libplist/fuzz/bplist-crashes/clusterfuzz-testcase-4766291097288704 +0 -0
  201. package/ldid/libplist/fuzz/bplist-crashes/clusterfuzz-testcase-4930725262393344 +0 -0
  202. package/ldid/libplist/fuzz/bplist-crashes/clusterfuzz-testcase-5421965105954816 +0 -0
  203. package/ldid/libplist/fuzz/bplist-crashes/clusterfuzz-testcase-5556177727389696 +0 -0
  204. package/ldid/libplist/fuzz/bplist-crashes/clusterfuzz-testcase-6557963011489792 +0 -0
  205. package/ldid/libplist/fuzz/bplist-crashes/clusterfuzz-testcase-6605859144597504 +0 -0
  206. package/ldid/libplist/fuzz/bplist-crashes/crash-0ce4dd483b645bc05ec45a97d285dcf1933ee840 +0 -0
  207. package/ldid/libplist/fuzz/bplist-crashes/crash-0d59cdcb5c3416c2790612b78a631ce9f5622800 +0 -0
  208. package/ldid/libplist/fuzz/bplist-crashes/crash-17d635ab460fef74df1ac7561f1253533a6359c5 +0 -0
  209. package/ldid/libplist/fuzz/bplist-crashes/crash-33a67313fa7864cd627ef92d12017a127d342f28 +0 -0
  210. package/ldid/libplist/fuzz/bplist-crashes/crash-39f1347115f8fe9ac25cdc9332e3fc5cd32c7f7b +0 -0
  211. package/ldid/libplist/fuzz/bplist-crashes/crash-4bd78175fe01d07c5ee90104fbc68d95dd092210 +0 -0
  212. package/ldid/libplist/fuzz/bplist-crashes/crash-4c5404453bb7425aef9b953a5f6f3f0afcc48392 +0 -0
  213. package/ldid/libplist/fuzz/bplist-crashes/crash-52775e25f6af20af351cd616834e602fc988a032 +0 -0
  214. package/ldid/libplist/fuzz/bplist-crashes/crash-6d1399685b745d3d49fadc91072fabcdde8d16fa +0 -0
  215. package/ldid/libplist/fuzz/bplist-crashes/crash-94b3725900d63c6258448fd757559c81002de9c9 +0 -0
  216. package/ldid/libplist/fuzz/bplist-crashes/crash-a47195acbabc3f5b2cda9c6ebda42f2afc1cc5af +0 -0
  217. package/ldid/libplist/fuzz/bplist-crashes/crash-ce852bae6aeeffc4698a93660236f1b995ce966e +0 -0
  218. package/ldid/libplist/fuzz/bplist-crashes/crash-daddb6e82e3d1ed76e20e4131462f5247a6fb131 +0 -0
  219. package/ldid/libplist/fuzz/bplist-crashes/crash-f21be4ebce7f9c337bf96b93cec7e252f5c75a21 +0 -0
  220. package/ldid/libplist/fuzz/bplist-crashes/crash-f779dafccc0164684d1a264976e56037188b40e2 +0 -0
  221. package/ldid/libplist/fuzz/bplist-leaks/leak-96fb453b3ba18d31e164831795a708183b5a0dac +0 -0
  222. package/ldid/libplist/fuzz/bplist-leaks/leak-acb3c00a83d7635638a476a4e70fc1f1caa1a5b1 +0 -0
  223. package/ldid/libplist/fuzz/bplist-leaks/leak-fe2cd4b1f67e0c9b21e6225a4fb4ca19eab80074 +0 -0
  224. package/ldid/libplist/fuzz/bplist.dict +1 -0
  225. package/ldid/libplist/fuzz/bplist_fuzzer.cc +32 -0
  226. package/ldid/libplist/fuzz/bplist_fuzzer.options +3 -0
  227. package/ldid/libplist/fuzz/fuzzers.test +8 -0
  228. package/ldid/libplist/fuzz/init-fuzzers.sh +23 -0
  229. package/ldid/libplist/fuzz/test-fuzzers.sh +33 -0
  230. package/ldid/libplist/fuzz/xplist-crashes/clusterfuzz-testcase-4516959125241856 +0 -0
  231. package/ldid/libplist/fuzz/xplist-crashes/clusterfuzz-testcase-4663876528373760 +5 -0
  232. package/ldid/libplist/fuzz/xplist-crashes/clusterfuzz-testcase-5799076113154048 +45 -0
  233. package/ldid/libplist/fuzz/xplist-crashes/clusterfuzz-testcase-5922404220010496 +0 -0
  234. package/ldid/libplist/fuzz/xplist-crashes/clusterfuzz-testcase-6015098361479168 +0 -0
  235. package/ldid/libplist/fuzz/xplist-crashes/clusterfuzz-testcase-6043836860071936 +0 -0
  236. package/ldid/libplist/fuzz/xplist-crashes/clusterfuzz-testcase-6047509906456576 +10050 -0
  237. package/ldid/libplist/fuzz/xplist-crashes/clusterfuzz-testcase-6482601374121984 +0 -0
  238. package/ldid/libplist/fuzz/xplist-crashes/crash-09788d7acb46b4b177422f9c4ee54556a3ad1f17 +53 -0
  239. package/ldid/libplist/fuzz/xplist-crashes/crash-155c60d5c4b2778110fb4a633caa7d64eb9b99c1 +9 -0
  240. package/ldid/libplist/fuzz/xplist-crashes/crash-348c909a0b3532977185f551eb5d2ed04e694883 +11 -0
  241. package/ldid/libplist/fuzz/xplist-crashes/crash-7bc172e27a2b1d4fcaf031f59d1f08fb83081e4a +8 -0
  242. package/ldid/libplist/fuzz/xplist-crashes/crash-80c28b0e2a446665e68927dd4441c10c9a68e64e +0 -0
  243. package/ldid/libplist/fuzz/xplist-crashes/crash-8acf177da60ecf13c36d0da1b8e25de891980ea6 +5 -0
  244. package/ldid/libplist/fuzz/xplist-crashes/crash-94276cf69a50e78dd6cdf079c208cb80f357cd33 +0 -0
  245. package/ldid/libplist/fuzz/xplist-crashes/crash-9ddb891a0ec42401eb4629e6b99e01aef7909eb9 +0 -0
  246. package/ldid/libplist/fuzz/xplist-crashes/crash-a8b44e1f5be4f75f00a937016ec5405bce77a0f9 +0 -0
  247. package/ldid/libplist/fuzz/xplist-crashes/crash-da39a3ee5e6b4b0d3255bfef95601890afd80709 +0 -0
  248. package/ldid/libplist/fuzz/xplist-crashes/crash-f03c680ee1c4d84c28e731752df77a61e213a24d +72 -0
  249. package/ldid/libplist/fuzz/xplist-leaks/clusterfuzz-testcase-4634751103139840 +187 -0
  250. package/ldid/libplist/fuzz/xplist-leaks/clusterfuzz-testcase-6056412121661440 +12 -0
  251. package/ldid/libplist/fuzz/xplist-leaks/leak-47b0a9f21d3affab6cfc898e5140bb53265ada07 +0 -0
  252. package/ldid/libplist/fuzz/xplist-leaks/leak-4c81aae70b20d9b9408b78d40999a54205bdcfb7 +0 -0
  253. package/ldid/libplist/fuzz/xplist-leaks/leak-53bc466851eda790bd891733da5db0a7482886bf +6 -0
  254. package/ldid/libplist/fuzz/xplist.dict +51 -0
  255. package/ldid/libplist/fuzz/xplist_fuzzer.cc +32 -0
  256. package/ldid/libplist/fuzz/xplist_fuzzer.options +3 -0
  257. package/ldid/libplist/include/Makefile.am +15 -0
  258. package/ldid/libplist/include/plist/Array.h +55 -0
  259. package/ldid/libplist/include/plist/Boolean.h +48 -0
  260. package/ldid/libplist/include/plist/Data.h +49 -0
  261. package/ldid/libplist/include/plist/Date.h +50 -0
  262. package/ldid/libplist/include/plist/Dictionary.h +68 -0
  263. package/ldid/libplist/include/plist/Integer.h +48 -0
  264. package/ldid/libplist/include/plist/Key.h +49 -0
  265. package/ldid/libplist/include/plist/Node.h +57 -0
  266. package/ldid/libplist/include/plist/Real.h +48 -0
  267. package/ldid/libplist/include/plist/String.h +49 -0
  268. package/ldid/libplist/include/plist/Structure.h +59 -0
  269. package/ldid/libplist/include/plist/Uid.h +48 -0
  270. package/ldid/libplist/include/plist/plist++.h +39 -0
  271. package/ldid/libplist/include/plist/plist.h +953 -0
  272. package/ldid/libplist/libcnary/COPYING +502 -0
  273. package/ldid/libplist/libcnary/Makefile.am +15 -0
  274. package/ldid/libplist/libcnary/README +5 -0
  275. package/ldid/libplist/libcnary/cnary.c +46 -0
  276. package/ldid/libplist/libcnary/include/node.h +65 -0
  277. package/ldid/libplist/libcnary/include/node_list.h +47 -0
  278. package/ldid/libplist/libcnary/include/object.h +41 -0
  279. package/ldid/libplist/libcnary/node.c +216 -0
  280. package/ldid/libplist/libcnary/node_list.c +157 -0
  281. package/ldid/libplist/m4/ac_pkg_cython.m4 +67 -0
  282. package/ldid/libplist/m4/as-compiler-flag.m4 +62 -0
  283. package/ldid/libplist/m4/ax_pthread.m4 +485 -0
  284. package/ldid/libplist/m4/ax_python_devel.m4 +327 -0
  285. package/ldid/libplist/m4/cython_python.m4 +7 -0
  286. package/ldid/libplist/src/Array.cpp +148 -0
  287. package/ldid/libplist/src/Boolean.cpp +73 -0
  288. package/ldid/libplist/src/Data.cpp +79 -0
  289. package/ldid/libplist/src/Date.cpp +76 -0
  290. package/ldid/libplist/src/Dictionary.cpp +182 -0
  291. package/ldid/libplist/src/Integer.cpp +73 -0
  292. package/ldid/libplist/src/Key.cpp +80 -0
  293. package/ldid/libplist/src/Makefile.am +63 -0
  294. package/ldid/libplist/src/Node.cpp +166 -0
  295. package/ldid/libplist/src/Real.cpp +73 -0
  296. package/ldid/libplist/src/String.cpp +80 -0
  297. package/ldid/libplist/src/Structure.cpp +123 -0
  298. package/ldid/libplist/src/Uid.cpp +73 -0
  299. package/ldid/libplist/src/base64.c +119 -0
  300. package/ldid/libplist/src/base64.h +28 -0
  301. package/ldid/libplist/src/bplist.c +1381 -0
  302. package/ldid/libplist/src/bytearray.c +61 -0
  303. package/ldid/libplist/src/bytearray.h +36 -0
  304. package/ldid/libplist/src/hashtable.c +140 -0
  305. package/ldid/libplist/src/hashtable.h +50 -0
  306. package/ldid/libplist/src/plist.c +1356 -0
  307. package/ldid/libplist/src/plist.h +74 -0
  308. package/ldid/libplist/src/ptrarray.c +96 -0
  309. package/ldid/libplist/src/ptrarray.h +40 -0
  310. package/ldid/libplist/src/strbuf.h +34 -0
  311. package/ldid/libplist/src/time64.c +814 -0
  312. package/ldid/libplist/src/time64.h +81 -0
  313. package/ldid/libplist/src/time64_limits.h +97 -0
  314. package/ldid/libplist/src/xplist.c +1435 -0
  315. package/ldid/libplist/test/Makefile.am +93 -0
  316. package/ldid/libplist/test/amp.test +14 -0
  317. package/ldid/libplist/test/bigarray.test +15 -0
  318. package/ldid/libplist/test/cdata.test +12 -0
  319. package/ldid/libplist/test/data/1.plist +35 -0
  320. package/ldid/libplist/test/data/2.plist +100 -0
  321. package/ldid/libplist/test/data/3.plist +420 -0
  322. package/ldid/libplist/test/data/4.plist +5037 -0
  323. package/ldid/libplist/test/data/5.plist +55053 -0
  324. package/ldid/libplist/test/data/6.plist +4006 -0
  325. package/ldid/libplist/test/data/7.plist +14 -0
  326. package/ldid/libplist/test/data/amp.plist +6 -0
  327. package/ldid/libplist/test/data/cdata.plist +6 -0
  328. package/ldid/libplist/test/data/dictref1byte.bplist +0 -0
  329. package/ldid/libplist/test/data/dictref2bytes.bplist +0 -0
  330. package/ldid/libplist/test/data/dictref3bytes.bplist +0 -0
  331. package/ldid/libplist/test/data/dictref4bytes.bplist +0 -0
  332. package/ldid/libplist/test/data/dictref5bytes.bplist +0 -0
  333. package/ldid/libplist/test/data/dictref6bytes.bplist +0 -0
  334. package/ldid/libplist/test/data/dictref7bytes.bplist +0 -0
  335. package/ldid/libplist/test/data/dictref8bytes.bplist +0 -0
  336. package/ldid/libplist/test/data/empty_keys.plist +8 -0
  337. package/ldid/libplist/test/data/entities.plist +57 -0
  338. package/ldid/libplist/test/data/hex.plist +5 -0
  339. package/ldid/libplist/test/data/invalid_tag.plist +6 -0
  340. package/ldid/libplist/test/data/malformed_dict.bplist +0 -0
  341. package/ldid/libplist/test/data/off1byte.bplist +0 -0
  342. package/ldid/libplist/test/data/off2bytes.bplist +0 -0
  343. package/ldid/libplist/test/data/off3bytes.bplist +0 -0
  344. package/ldid/libplist/test/data/off4bytes.bplist +0 -0
  345. package/ldid/libplist/test/data/off5bytes.bplist +0 -0
  346. package/ldid/libplist/test/data/off6bytes.bplist +0 -0
  347. package/ldid/libplist/test/data/off7bytes.bplist +0 -0
  348. package/ldid/libplist/test/data/off8bytes.bplist +0 -0
  349. package/ldid/libplist/test/data/offxml.plist +8 -0
  350. package/ldid/libplist/test/data/order.bplist +0 -0
  351. package/ldid/libplist/test/data/order.plist +27 -0
  352. package/ldid/libplist/test/data/recursion.bplist +0 -0
  353. package/ldid/libplist/test/data/signed.bplist +0 -0
  354. package/ldid/libplist/test/data/signed.plist +5 -0
  355. package/ldid/libplist/test/data/signedunsigned.bplist +0 -0
  356. package/ldid/libplist/test/data/signedunsigned.plist +11 -0
  357. package/ldid/libplist/test/data/unsigned.bplist +0 -0
  358. package/ldid/libplist/test/data/unsigned.plist +5 -0
  359. package/ldid/libplist/test/dates.test +15 -0
  360. package/ldid/libplist/test/empty.test +15 -0
  361. package/ldid/libplist/test/empty_keys.test +12 -0
  362. package/ldid/libplist/test/entities.test +12 -0
  363. package/ldid/libplist/test/hex.test +12 -0
  364. package/ldid/libplist/test/huge.test +15 -0
  365. package/ldid/libplist/test/invalid_tag.test +14 -0
  366. package/ldid/libplist/test/large.test +15 -0
  367. package/ldid/libplist/test/malformed_dict.test +11 -0
  368. package/ldid/libplist/test/medium.test +15 -0
  369. package/ldid/libplist/test/offsetsize.test +12 -0
  370. package/ldid/libplist/test/order.test +13 -0
  371. package/ldid/libplist/test/plist_cmp.c +158 -0
  372. package/ldid/libplist/test/plist_test.c +135 -0
  373. package/ldid/libplist/test/recursion.test +11 -0
  374. package/ldid/libplist/test/refsize.test +12 -0
  375. package/ldid/libplist/test/signedunsigned1.test +23 -0
  376. package/ldid/libplist/test/signedunsigned2.test +23 -0
  377. package/ldid/libplist/test/signedunsigned3.test +23 -0
  378. package/ldid/libplist/test/small.test +15 -0
  379. package/ldid/libplist/test/timezone1.test +17 -0
  380. package/ldid/libplist/test/timezone2.test +21 -0
  381. package/ldid/libplist/tools/Makefile.am +10 -0
  382. package/ldid/libplist/tools/plistutil.c +299 -0
  383. package/ldid/lookup2.c +416 -0
  384. package/ldid/make.sh +90 -0
  385. package/ldid/minimal/hexdump.h +76 -0
  386. package/ldid/minimal/mapping.h +72 -0
  387. package/ldid/minimal/sqlite3.h +71 -0
  388. package/ldid/minimal/stdlib.h +129 -0
  389. package/ldid/minimal/string.h +51 -0
  390. package/ldid/plist.sh +2 -0
  391. package/ldid/sha1.h +64 -0
  392. package/ldid/sysroot.sh +31 -0
  393. package/ldid/version.sh +2 -0
  394. package/lib/client.js +243 -0
  395. package/lib/commands/account.js +785 -0
  396. package/lib/commands/avatars.js +349 -0
  397. package/lib/commands/database.js +1238 -0
  398. package/lib/commands/deploy.js +477 -0
  399. package/lib/commands/functions.js +689 -0
  400. package/lib/commands/generic.js +106 -0
  401. package/lib/commands/health.js +269 -0
  402. package/lib/commands/init.js +148 -0
  403. package/lib/commands/locale.js +177 -0
  404. package/lib/commands/projects.js +1191 -0
  405. package/lib/commands/storage.js +743 -0
  406. package/lib/commands/teams.js +435 -0
  407. package/lib/commands/users.js +542 -0
  408. package/lib/config.js +264 -0
  409. package/lib/exception.js +9 -0
  410. package/lib/parser.js +179 -0
  411. package/lib/questions.js +223 -0
  412. package/lib/sdks.js +82 -0
  413. package/package.json +41 -0
package/ldid/ldid.cpp ADDED
@@ -0,0 +1,3253 @@
1
+ /* ldid - (Mach-O) Link-Loader Identity Editor
2
+ * Copyright (C) 2007-2015 Jay Freeman (saurik)
3
+ */
4
+
5
+ /* GNU Affero General Public License, Version 3 {{{ */
6
+ /*
7
+ * This program is free software: you can redistribute it and/or modify
8
+ * it under the terms of the GNU Affero General Public License as published by
9
+ * the Free Software Foundation, either version 3 of the License, or
10
+ * (at your option) any later version.
11
+
12
+ * This program is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ * GNU Affero General Public License for more details.
16
+
17
+ * You should have received a copy of the GNU Affero General Public License
18
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
19
+ **/
20
+ /* }}} */
21
+
22
+ #include <cstdio>
23
+ #include <cstdlib>
24
+ #include <cstring>
25
+ #include <fstream>
26
+ #include <iostream>
27
+ #include <memory>
28
+ #include <set>
29
+ #include <sstream>
30
+ #include <string>
31
+ #include <vector>
32
+
33
+ #include <dirent.h>
34
+ #include <errno.h>
35
+ #include <fcntl.h>
36
+ #include <regex.h>
37
+ #include <stdbool.h>
38
+ #include <stdint.h>
39
+ #include <unistd.h>
40
+
41
+ #include <sys/mman.h>
42
+ #include <sys/stat.h>
43
+ #include <sys/types.h>
44
+
45
+ #ifndef LDID_NOSMIME
46
+ #include <openssl/err.h>
47
+ #include <openssl/pem.h>
48
+ #include <openssl/pkcs7.h>
49
+ #include <openssl/pkcs12.h>
50
+ #endif
51
+
52
+ #ifdef __APPLE__
53
+ #include <CommonCrypto/CommonDigest.h>
54
+
55
+ #define LDID_SHA1_DIGEST_LENGTH CC_SHA1_DIGEST_LENGTH
56
+ #define LDID_SHA1 CC_SHA1
57
+ #define LDID_SHA1_CTX CC_SHA1_CTX
58
+ #define LDID_SHA1_Init CC_SHA1_Init
59
+ #define LDID_SHA1_Update CC_SHA1_Update
60
+ #define LDID_SHA1_Final CC_SHA1_Final
61
+
62
+ #define LDID_SHA256_DIGEST_LENGTH CC_SHA256_DIGEST_LENGTH
63
+ #define LDID_SHA256 CC_SHA256
64
+ #define LDID_SHA256_CTX CC_SHA256_CTX
65
+ #define LDID_SHA256_Init CC_SHA256_Init
66
+ #define LDID_SHA256_Update CC_SHA256_Update
67
+ #define LDID_SHA256_Final CC_SHA256_Final
68
+ #else
69
+ #include <openssl/sha.h>
70
+
71
+ #define LDID_SHA1_DIGEST_LENGTH SHA_DIGEST_LENGTH
72
+ #define LDID_SHA1 SHA1
73
+ #define LDID_SHA1_CTX SHA_CTX
74
+ #define LDID_SHA1_Init SHA1_Init
75
+ #define LDID_SHA1_Update SHA1_Update
76
+ #define LDID_SHA1_Final SHA1_Final
77
+
78
+ #define LDID_SHA256_DIGEST_LENGTH SHA256_DIGEST_LENGTH
79
+ #define LDID_SHA256 SHA256
80
+ #define LDID_SHA256_CTX SHA256_CTX
81
+ #define LDID_SHA256_Init SHA256_Init
82
+ #define LDID_SHA256_Update SHA256_Update
83
+ #define LDID_SHA256_Final SHA256_Final
84
+ #endif
85
+
86
+ #ifndef LDID_NOPLIST
87
+ #include <plist/plist.h>
88
+ #elif __APPLE__
89
+ #include <CoreFoundation/CoreFoundation.h>
90
+ #endif
91
+
92
+ #include "ldid.hpp"
93
+
94
+ #define _assert___(line) \
95
+ #line
96
+ #define _assert__(line) \
97
+ _assert___(line)
98
+
99
+ #ifndef $
100
+ #define $(value) value
101
+ #endif
102
+
103
+ #ifdef __EXCEPTIONS
104
+ #define _assert_(expr, format, ...) \
105
+ do if (!(expr)) { \
106
+ fprintf(stderr, $("%s(%u): _assert(): " format "\n"), __FILE__, __LINE__, ## __VA_ARGS__); \
107
+ throw $(__FILE__ "(" _assert__(__LINE__) "): _assert(" #expr ")"); \
108
+ } while (false)
109
+ #else
110
+ // XXX: this is not acceptable
111
+ #define _assert_(expr, format, ...) \
112
+ do if (!(expr)) { \
113
+ fprintf(stderr, $("%s(%u): _assert(): " format "\n"), __FILE__, __LINE__, ## __VA_ARGS__); \
114
+ exit(-1); \
115
+ } while (false)
116
+ #endif
117
+
118
+ #define _assert(expr) \
119
+ _assert_(expr, "%s", $(#expr))
120
+
121
+ #define _syscall(expr, ...) [&] { for (;;) { \
122
+ auto _value(expr); \
123
+ if ((long) _value != -1) \
124
+ return _value; \
125
+ int error(errno); \
126
+ if (error == EINTR) \
127
+ continue; \
128
+ /* XXX: EINTR is included in this list to fix g++ */ \
129
+ for (auto success : (long[]) {EINTR, __VA_ARGS__}) \
130
+ if (error == success) \
131
+ return (decltype(expr)) -success; \
132
+ _assert_(false, "errno=%u", error); \
133
+ } }()
134
+
135
+ #define _trace() \
136
+ fprintf(stderr, $("_trace(%s:%u): %s\n"), __FILE__, __LINE__, $(__FUNCTION__))
137
+
138
+ #define _not(type) \
139
+ ((type) ~ (type) 0)
140
+
141
+ #define _packed \
142
+ __attribute__((packed))
143
+
144
+ template <typename Type_>
145
+ struct Iterator_ {
146
+ typedef typename Type_::const_iterator Result;
147
+ };
148
+
149
+ #define _foreach(item, list) \
150
+ for (bool _stop(true); _stop; ) \
151
+ for (const __typeof__(list) &_list = (list); _stop; _stop = false) \
152
+ for (Iterator_<__typeof__(list)>::Result _item = _list.begin(); _item != _list.end(); ++_item) \
153
+ for (bool _suck(true); _suck; _suck = false) \
154
+ for (const __typeof__(*_item) &item = *_item; _suck; _suck = false)
155
+
156
+ class _Scope {
157
+ };
158
+
159
+ template <typename Function_>
160
+ class Scope :
161
+ public _Scope
162
+ {
163
+ private:
164
+ Function_ function_;
165
+
166
+ public:
167
+ Scope(const Function_ &function) :
168
+ function_(function)
169
+ {
170
+ }
171
+
172
+ ~Scope() {
173
+ function_();
174
+ }
175
+ };
176
+
177
+ template <typename Function_>
178
+ Scope<Function_> _scope(const Function_ &function) {
179
+ return Scope<Function_>(function);
180
+ }
181
+
182
+ #define _scope__(counter, function) \
183
+ __attribute__((__unused__)) \
184
+ const _Scope &_scope ## counter(_scope([&]function))
185
+ #define _scope_(counter, function) \
186
+ _scope__(counter, function)
187
+ #define _scope(function) \
188
+ _scope_(__COUNTER__, function)
189
+
190
+ #define CPU_ARCH_MASK uint32_t(0xff000000)
191
+ #define CPU_ARCH_ABI64 uint32_t(0x01000000)
192
+
193
+ #define CPU_TYPE_ANY uint32_t(-1)
194
+ #define CPU_TYPE_VAX uint32_t( 1)
195
+ #define CPU_TYPE_MC680x0 uint32_t( 6)
196
+ #define CPU_TYPE_X86 uint32_t( 7)
197
+ #define CPU_TYPE_MC98000 uint32_t(10)
198
+ #define CPU_TYPE_HPPA uint32_t(11)
199
+ #define CPU_TYPE_ARM uint32_t(12)
200
+ #define CPU_TYPE_MC88000 uint32_t(13)
201
+ #define CPU_TYPE_SPARC uint32_t(14)
202
+ #define CPU_TYPE_I860 uint32_t(15)
203
+ #define CPU_TYPE_POWERPC uint32_t(18)
204
+
205
+ #define CPU_TYPE_I386 CPU_TYPE_X86
206
+
207
+ #define CPU_TYPE_ARM64 (CPU_ARCH_ABI64 | CPU_TYPE_ARM)
208
+ #define CPU_TYPE_POWERPC64 (CPU_ARCH_ABI64 | CPU_TYPE_POWERPC)
209
+ #define CPU_TYPE_X86_64 (CPU_ARCH_ABI64 | CPU_TYPE_X86)
210
+
211
+ struct fat_header {
212
+ uint32_t magic;
213
+ uint32_t nfat_arch;
214
+ } _packed;
215
+
216
+ #define FAT_MAGIC 0xcafebabe
217
+ #define FAT_CIGAM 0xbebafeca
218
+
219
+ struct fat_arch {
220
+ uint32_t cputype;
221
+ uint32_t cpusubtype;
222
+ uint32_t offset;
223
+ uint32_t size;
224
+ uint32_t align;
225
+ } _packed;
226
+
227
+ struct mach_header {
228
+ uint32_t magic;
229
+ uint32_t cputype;
230
+ uint32_t cpusubtype;
231
+ uint32_t filetype;
232
+ uint32_t ncmds;
233
+ uint32_t sizeofcmds;
234
+ uint32_t flags;
235
+ } _packed;
236
+
237
+ #define MH_MAGIC 0xfeedface
238
+ #define MH_CIGAM 0xcefaedfe
239
+
240
+ #define MH_MAGIC_64 0xfeedfacf
241
+ #define MH_CIGAM_64 0xcffaedfe
242
+
243
+ #define MH_DYLDLINK 0x4
244
+
245
+ #define MH_OBJECT 0x1
246
+ #define MH_EXECUTE 0x2
247
+ #define MH_DYLIB 0x6
248
+ #define MH_DYLINKER 0x7
249
+ #define MH_BUNDLE 0x8
250
+ #define MH_DYLIB_STUB 0x9
251
+
252
+ struct load_command {
253
+ uint32_t cmd;
254
+ uint32_t cmdsize;
255
+ } _packed;
256
+
257
+ #define LC_REQ_DYLD uint32_t(0x80000000)
258
+
259
+ #define LC_SEGMENT uint32_t(0x01)
260
+ #define LC_SYMTAB uint32_t(0x02)
261
+ #define LC_DYSYMTAB uint32_t(0x0b)
262
+ #define LC_LOAD_DYLIB uint32_t(0x0c)
263
+ #define LC_ID_DYLIB uint32_t(0x0d)
264
+ #define LC_SEGMENT_64 uint32_t(0x19)
265
+ #define LC_UUID uint32_t(0x1b)
266
+ #define LC_CODE_SIGNATURE uint32_t(0x1d)
267
+ #define LC_SEGMENT_SPLIT_INFO uint32_t(0x1e)
268
+ #define LC_REEXPORT_DYLIB uint32_t(0x1f | LC_REQ_DYLD)
269
+ #define LC_ENCRYPTION_INFO uint32_t(0x21)
270
+ #define LC_DYLD_INFO uint32_t(0x22)
271
+ #define LC_DYLD_INFO_ONLY uint32_t(0x22 | LC_REQ_DYLD)
272
+ #define LC_ENCRYPTION_INFO_64 uint32_t(0x2c)
273
+
274
+ union Version {
275
+ struct {
276
+ uint8_t patch;
277
+ uint8_t minor;
278
+ uint16_t major;
279
+ } _packed;
280
+
281
+ uint32_t value;
282
+ };
283
+
284
+ struct dylib {
285
+ uint32_t name;
286
+ uint32_t timestamp;
287
+ uint32_t current_version;
288
+ uint32_t compatibility_version;
289
+ } _packed;
290
+
291
+ struct dylib_command {
292
+ uint32_t cmd;
293
+ uint32_t cmdsize;
294
+ struct dylib dylib;
295
+ } _packed;
296
+
297
+ struct uuid_command {
298
+ uint32_t cmd;
299
+ uint32_t cmdsize;
300
+ uint8_t uuid[16];
301
+ } _packed;
302
+
303
+ struct symtab_command {
304
+ uint32_t cmd;
305
+ uint32_t cmdsize;
306
+ uint32_t symoff;
307
+ uint32_t nsyms;
308
+ uint32_t stroff;
309
+ uint32_t strsize;
310
+ } _packed;
311
+
312
+ struct dyld_info_command {
313
+ uint32_t cmd;
314
+ uint32_t cmdsize;
315
+ uint32_t rebase_off;
316
+ uint32_t rebase_size;
317
+ uint32_t bind_off;
318
+ uint32_t bind_size;
319
+ uint32_t weak_bind_off;
320
+ uint32_t weak_bind_size;
321
+ uint32_t lazy_bind_off;
322
+ uint32_t lazy_bind_size;
323
+ uint32_t export_off;
324
+ uint32_t export_size;
325
+ } _packed;
326
+
327
+ struct dysymtab_command {
328
+ uint32_t cmd;
329
+ uint32_t cmdsize;
330
+ uint32_t ilocalsym;
331
+ uint32_t nlocalsym;
332
+ uint32_t iextdefsym;
333
+ uint32_t nextdefsym;
334
+ uint32_t iundefsym;
335
+ uint32_t nundefsym;
336
+ uint32_t tocoff;
337
+ uint32_t ntoc;
338
+ uint32_t modtaboff;
339
+ uint32_t nmodtab;
340
+ uint32_t extrefsymoff;
341
+ uint32_t nextrefsyms;
342
+ uint32_t indirectsymoff;
343
+ uint32_t nindirectsyms;
344
+ uint32_t extreloff;
345
+ uint32_t nextrel;
346
+ uint32_t locreloff;
347
+ uint32_t nlocrel;
348
+ } _packed;
349
+
350
+ struct dylib_table_of_contents {
351
+ uint32_t symbol_index;
352
+ uint32_t module_index;
353
+ } _packed;
354
+
355
+ struct dylib_module {
356
+ uint32_t module_name;
357
+ uint32_t iextdefsym;
358
+ uint32_t nextdefsym;
359
+ uint32_t irefsym;
360
+ uint32_t nrefsym;
361
+ uint32_t ilocalsym;
362
+ uint32_t nlocalsym;
363
+ uint32_t iextrel;
364
+ uint32_t nextrel;
365
+ uint32_t iinit_iterm;
366
+ uint32_t ninit_nterm;
367
+ uint32_t objc_module_info_addr;
368
+ uint32_t objc_module_info_size;
369
+ } _packed;
370
+
371
+ struct dylib_reference {
372
+ uint32_t isym:24;
373
+ uint32_t flags:8;
374
+ } _packed;
375
+
376
+ struct relocation_info {
377
+ int32_t r_address;
378
+ uint32_t r_symbolnum:24;
379
+ uint32_t r_pcrel:1;
380
+ uint32_t r_length:2;
381
+ uint32_t r_extern:1;
382
+ uint32_t r_type:4;
383
+ } _packed;
384
+
385
+ struct nlist {
386
+ union {
387
+ char *n_name;
388
+ int32_t n_strx;
389
+ } n_un;
390
+
391
+ uint8_t n_type;
392
+ uint8_t n_sect;
393
+ uint8_t n_desc;
394
+ uint32_t n_value;
395
+ } _packed;
396
+
397
+ struct segment_command {
398
+ uint32_t cmd;
399
+ uint32_t cmdsize;
400
+ char segname[16];
401
+ uint32_t vmaddr;
402
+ uint32_t vmsize;
403
+ uint32_t fileoff;
404
+ uint32_t filesize;
405
+ uint32_t maxprot;
406
+ uint32_t initprot;
407
+ uint32_t nsects;
408
+ uint32_t flags;
409
+ } _packed;
410
+
411
+ struct segment_command_64 {
412
+ uint32_t cmd;
413
+ uint32_t cmdsize;
414
+ char segname[16];
415
+ uint64_t vmaddr;
416
+ uint64_t vmsize;
417
+ uint64_t fileoff;
418
+ uint64_t filesize;
419
+ uint32_t maxprot;
420
+ uint32_t initprot;
421
+ uint32_t nsects;
422
+ uint32_t flags;
423
+ } _packed;
424
+
425
+ struct section {
426
+ char sectname[16];
427
+ char segname[16];
428
+ uint32_t addr;
429
+ uint32_t size;
430
+ uint32_t offset;
431
+ uint32_t align;
432
+ uint32_t reloff;
433
+ uint32_t nreloc;
434
+ uint32_t flags;
435
+ uint32_t reserved1;
436
+ uint32_t reserved2;
437
+ } _packed;
438
+
439
+ struct section_64 {
440
+ char sectname[16];
441
+ char segname[16];
442
+ uint64_t addr;
443
+ uint64_t size;
444
+ uint32_t offset;
445
+ uint32_t align;
446
+ uint32_t reloff;
447
+ uint32_t nreloc;
448
+ uint32_t flags;
449
+ uint32_t reserved1;
450
+ uint32_t reserved2;
451
+ uint32_t reserved3;
452
+ } _packed;
453
+
454
+ struct linkedit_data_command {
455
+ uint32_t cmd;
456
+ uint32_t cmdsize;
457
+ uint32_t dataoff;
458
+ uint32_t datasize;
459
+ } _packed;
460
+
461
+ struct encryption_info_command {
462
+ uint32_t cmd;
463
+ uint32_t cmdsize;
464
+ uint32_t cryptoff;
465
+ uint32_t cryptsize;
466
+ uint32_t cryptid;
467
+ } _packed;
468
+
469
+ #define BIND_OPCODE_MASK 0xf0
470
+ #define BIND_IMMEDIATE_MASK 0x0f
471
+ #define BIND_OPCODE_DONE 0x00
472
+ #define BIND_OPCODE_SET_DYLIB_ORDINAL_IMM 0x10
473
+ #define BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB 0x20
474
+ #define BIND_OPCODE_SET_DYLIB_SPECIAL_IMM 0x30
475
+ #define BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM 0x40
476
+ #define BIND_OPCODE_SET_TYPE_IMM 0x50
477
+ #define BIND_OPCODE_SET_ADDEND_SLEB 0x60
478
+ #define BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB 0x70
479
+ #define BIND_OPCODE_ADD_ADDR_ULEB 0x80
480
+ #define BIND_OPCODE_DO_BIND 0x90
481
+ #define BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB 0xa0
482
+ #define BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED 0xb0
483
+ #define BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB 0xc0
484
+
485
+ struct : ldid::Progress {
486
+ virtual void operator()(const std::string &value) const {
487
+ }
488
+
489
+ virtual void operator()(double value) const {
490
+ }
491
+ } dummy_;
492
+
493
+ struct Progression : ldid::Progress {
494
+ const ldid::Progress &progress_;
495
+ std::string name_;
496
+
497
+ Progression(const ldid::Progress &progress, const std::string &name) :
498
+ progress_(progress),
499
+ name_(name)
500
+ {
501
+ }
502
+
503
+ virtual void operator()(const std::string &value) const {
504
+ return progress_(name_ + " (" + value + ")");
505
+ }
506
+
507
+ virtual void operator()(double value) const {
508
+ return progress_(value);
509
+ }
510
+ };
511
+
512
+ static std::streamsize read(std::streambuf &stream, void *data, size_t size) {
513
+ auto writ(stream.sgetn(static_cast<char *>(data), size));
514
+ _assert(writ >= 0);
515
+ return writ;
516
+ }
517
+
518
+ static inline void get(std::streambuf &stream, void *data, size_t size) {
519
+ _assert(read(stream, data, size) == size);
520
+ }
521
+
522
+ static inline void put(std::streambuf &stream, const void *data, size_t size) {
523
+ _assert(stream.sputn(static_cast<const char *>(data), size) == size);
524
+ }
525
+
526
+ static inline void put(std::streambuf &stream, const void *data, size_t size, const ldid::Progress &progress) {
527
+ progress(0);
528
+ for (size_t total(0); total != size;) {
529
+ auto writ(std::min(size - total, size_t(4096 * 4)));
530
+ _assert(stream.sputn(static_cast<const char *>(data) + total, writ) == writ);
531
+ total += writ;
532
+ progress(double(total) / size);
533
+ }
534
+ }
535
+
536
+ static size_t most(std::streambuf &stream, void *data, size_t size) {
537
+ size_t total(size);
538
+ while (size > 0)
539
+ if (auto writ = read(stream, data, size))
540
+ size -= writ;
541
+ else break;
542
+ return total - size;
543
+ }
544
+
545
+ static inline void pad(std::streambuf &stream, size_t size) {
546
+ char padding[size];
547
+ memset(padding, 0, size);
548
+ put(stream, padding, size);
549
+ }
550
+
551
+ template <typename Type_>
552
+ Type_ Align(Type_ value, size_t align) {
553
+ value += align - 1;
554
+ value /= align;
555
+ value *= align;
556
+ return value;
557
+ }
558
+
559
+ static const uint8_t PageShift_(0x0c);
560
+ static const uint32_t PageSize_(1 << PageShift_);
561
+
562
+ static inline uint16_t Swap_(uint16_t value) {
563
+ return
564
+ ((value >> 8) & 0x00ff) |
565
+ ((value << 8) & 0xff00);
566
+ }
567
+
568
+ static inline uint32_t Swap_(uint32_t value) {
569
+ value = ((value >> 8) & 0x00ff00ff) |
570
+ ((value << 8) & 0xff00ff00);
571
+ value = ((value >> 16) & 0x0000ffff) |
572
+ ((value << 16) & 0xffff0000);
573
+ return value;
574
+ }
575
+
576
+ static inline uint64_t Swap_(uint64_t value) {
577
+ value = (value & 0x00000000ffffffff) << 32 | (value & 0xffffffff00000000) >> 32;
578
+ value = (value & 0x0000ffff0000ffff) << 16 | (value & 0xffff0000ffff0000) >> 16;
579
+ value = (value & 0x00ff00ff00ff00ff) << 8 | (value & 0xff00ff00ff00ff00) >> 8;
580
+ return value;
581
+ }
582
+
583
+ static inline int16_t Swap_(int16_t value) {
584
+ return Swap_(static_cast<uint16_t>(value));
585
+ }
586
+
587
+ static inline int32_t Swap_(int32_t value) {
588
+ return Swap_(static_cast<uint32_t>(value));
589
+ }
590
+
591
+ static inline int64_t Swap_(int64_t value) {
592
+ return Swap_(static_cast<uint64_t>(value));
593
+ }
594
+
595
+ static bool little_(true);
596
+
597
+ static inline uint16_t Swap(uint16_t value) {
598
+ return little_ ? Swap_(value) : value;
599
+ }
600
+
601
+ static inline uint32_t Swap(uint32_t value) {
602
+ return little_ ? Swap_(value) : value;
603
+ }
604
+
605
+ static inline uint64_t Swap(uint64_t value) {
606
+ return little_ ? Swap_(value) : value;
607
+ }
608
+
609
+ static inline int16_t Swap(int16_t value) {
610
+ return Swap(static_cast<uint16_t>(value));
611
+ }
612
+
613
+ static inline int32_t Swap(int32_t value) {
614
+ return Swap(static_cast<uint32_t>(value));
615
+ }
616
+
617
+ static inline int64_t Swap(int64_t value) {
618
+ return Swap(static_cast<uint64_t>(value));
619
+ }
620
+
621
+ class Swapped {
622
+ protected:
623
+ bool swapped_;
624
+
625
+ Swapped() :
626
+ swapped_(false)
627
+ {
628
+ }
629
+
630
+ public:
631
+ Swapped(bool swapped) :
632
+ swapped_(swapped)
633
+ {
634
+ }
635
+
636
+ template <typename Type_>
637
+ Type_ Swap(Type_ value) const {
638
+ return swapped_ ? Swap_(value) : value;
639
+ }
640
+ };
641
+
642
+ class Data :
643
+ public Swapped
644
+ {
645
+ private:
646
+ void *base_;
647
+ size_t size_;
648
+
649
+ public:
650
+ Data(void *base, size_t size) :
651
+ base_(base),
652
+ size_(size)
653
+ {
654
+ }
655
+
656
+ void *GetBase() const {
657
+ return base_;
658
+ }
659
+
660
+ size_t GetSize() const {
661
+ return size_;
662
+ }
663
+ };
664
+
665
+ class MachHeader :
666
+ public Data
667
+ {
668
+ private:
669
+ bool bits64_;
670
+
671
+ struct mach_header *mach_header_;
672
+ struct load_command *load_command_;
673
+
674
+ public:
675
+ MachHeader(void *base, size_t size) :
676
+ Data(base, size)
677
+ {
678
+ mach_header_ = (mach_header *) base;
679
+
680
+ switch (Swap(mach_header_->magic)) {
681
+ case MH_CIGAM:
682
+ swapped_ = !swapped_;
683
+ case MH_MAGIC:
684
+ bits64_ = false;
685
+ break;
686
+
687
+ case MH_CIGAM_64:
688
+ swapped_ = !swapped_;
689
+ case MH_MAGIC_64:
690
+ bits64_ = true;
691
+ break;
692
+
693
+ default:
694
+ _assert(false);
695
+ }
696
+
697
+ void *post = mach_header_ + 1;
698
+ if (bits64_)
699
+ post = (uint32_t *) post + 1;
700
+ load_command_ = (struct load_command *) post;
701
+
702
+ _assert(
703
+ Swap(mach_header_->filetype) == MH_EXECUTE ||
704
+ Swap(mach_header_->filetype) == MH_DYLIB ||
705
+ Swap(mach_header_->filetype) == MH_DYLINKER ||
706
+ Swap(mach_header_->filetype) == MH_BUNDLE
707
+ );
708
+ }
709
+
710
+ bool Bits64() const {
711
+ return bits64_;
712
+ }
713
+
714
+ struct mach_header *operator ->() const {
715
+ return mach_header_;
716
+ }
717
+
718
+ operator struct mach_header *() const {
719
+ return mach_header_;
720
+ }
721
+
722
+ uint32_t GetCPUType() const {
723
+ return Swap(mach_header_->cputype);
724
+ }
725
+
726
+ uint32_t GetCPUSubtype() const {
727
+ return Swap(mach_header_->cpusubtype) & 0xff;
728
+ }
729
+
730
+ struct load_command *GetLoadCommand() const {
731
+ return load_command_;
732
+ }
733
+
734
+ std::vector<struct load_command *> GetLoadCommands() const {
735
+ std::vector<struct load_command *> load_commands;
736
+
737
+ struct load_command *load_command = load_command_;
738
+ for (uint32_t cmd = 0; cmd != Swap(mach_header_->ncmds); ++cmd) {
739
+ load_commands.push_back(load_command);
740
+ load_command = (struct load_command *) ((uint8_t *) load_command + Swap(load_command->cmdsize));
741
+ }
742
+
743
+ return load_commands;
744
+ }
745
+
746
+ void ForSection(const ldid::Functor<void (const char *, const char *, void *, size_t)> &code) const {
747
+ _foreach (load_command, GetLoadCommands())
748
+ switch (Swap(load_command->cmd)) {
749
+ case LC_SEGMENT: {
750
+ auto segment(reinterpret_cast<struct segment_command *>(load_command));
751
+ code(segment->segname, NULL, GetOffset<void>(segment->fileoff), segment->filesize);
752
+ auto section(reinterpret_cast<struct section *>(segment + 1));
753
+ for (uint32_t i(0), e(Swap(segment->nsects)); i != e; ++i, ++section)
754
+ code(segment->segname, section->sectname, GetOffset<void>(segment->fileoff + section->offset), section->size);
755
+ } break;
756
+
757
+ case LC_SEGMENT_64: {
758
+ auto segment(reinterpret_cast<struct segment_command_64 *>(load_command));
759
+ code(segment->segname, NULL, GetOffset<void>(segment->fileoff), segment->filesize);
760
+ auto section(reinterpret_cast<struct section_64 *>(segment + 1));
761
+ for (uint32_t i(0), e(Swap(segment->nsects)); i != e; ++i, ++section)
762
+ code(segment->segname, section->sectname, GetOffset<void>(segment->fileoff + section->offset), section->size);
763
+ } break;
764
+ }
765
+ }
766
+
767
+ template <typename Target_>
768
+ Target_ *GetOffset(uint32_t offset) const {
769
+ return reinterpret_cast<Target_ *>(offset + (uint8_t *) mach_header_);
770
+ }
771
+ };
772
+
773
+ class FatMachHeader :
774
+ public MachHeader
775
+ {
776
+ private:
777
+ fat_arch *fat_arch_;
778
+
779
+ public:
780
+ FatMachHeader(void *base, size_t size, fat_arch *fat_arch) :
781
+ MachHeader(base, size),
782
+ fat_arch_(fat_arch)
783
+ {
784
+ }
785
+
786
+ fat_arch *GetFatArch() const {
787
+ return fat_arch_;
788
+ }
789
+ };
790
+
791
+ class FatHeader :
792
+ public Data
793
+ {
794
+ private:
795
+ fat_header *fat_header_;
796
+ std::vector<FatMachHeader> mach_headers_;
797
+
798
+ public:
799
+ FatHeader(void *base, size_t size) :
800
+ Data(base, size)
801
+ {
802
+ fat_header_ = reinterpret_cast<struct fat_header *>(base);
803
+
804
+ if (Swap(fat_header_->magic) == FAT_CIGAM) {
805
+ swapped_ = !swapped_;
806
+ goto fat;
807
+ } else if (Swap(fat_header_->magic) != FAT_MAGIC) {
808
+ fat_header_ = NULL;
809
+ mach_headers_.push_back(FatMachHeader(base, size, NULL));
810
+ } else fat: {
811
+ size_t fat_narch = Swap(fat_header_->nfat_arch);
812
+ fat_arch *fat_arch = reinterpret_cast<struct fat_arch *>(fat_header_ + 1);
813
+ size_t arch;
814
+ for (arch = 0; arch != fat_narch; ++arch) {
815
+ uint32_t arch_offset = Swap(fat_arch->offset);
816
+ uint32_t arch_size = Swap(fat_arch->size);
817
+ mach_headers_.push_back(FatMachHeader((uint8_t *) base + arch_offset, arch_size, fat_arch));
818
+ ++fat_arch;
819
+ }
820
+ }
821
+ }
822
+
823
+ std::vector<FatMachHeader> &GetMachHeaders() {
824
+ return mach_headers_;
825
+ }
826
+
827
+ bool IsFat() const {
828
+ return fat_header_ != NULL;
829
+ }
830
+
831
+ struct fat_header *operator ->() const {
832
+ return fat_header_;
833
+ }
834
+
835
+ operator struct fat_header *() const {
836
+ return fat_header_;
837
+ }
838
+ };
839
+
840
+ #define CSMAGIC_REQUIREMENT uint32_t(0xfade0c00)
841
+ #define CSMAGIC_REQUIREMENTS uint32_t(0xfade0c01)
842
+ #define CSMAGIC_CODEDIRECTORY uint32_t(0xfade0c02)
843
+ #define CSMAGIC_EMBEDDED_SIGNATURE uint32_t(0xfade0cc0)
844
+ #define CSMAGIC_EMBEDDED_SIGNATURE_OLD uint32_t(0xfade0b02)
845
+ #define CSMAGIC_EMBEDDED_ENTITLEMENTS uint32_t(0xfade7171)
846
+ #define CSMAGIC_DETACHED_SIGNATURE uint32_t(0xfade0cc1)
847
+ #define CSMAGIC_BLOBWRAPPER uint32_t(0xfade0b01)
848
+
849
+ #define CSSLOT_CODEDIRECTORY uint32_t(0x00000)
850
+ #define CSSLOT_INFOSLOT uint32_t(0x00001)
851
+ #define CSSLOT_REQUIREMENTS uint32_t(0x00002)
852
+ #define CSSLOT_RESOURCEDIR uint32_t(0x00003)
853
+ #define CSSLOT_APPLICATION uint32_t(0x00004)
854
+ #define CSSLOT_ENTITLEMENTS uint32_t(0x00005)
855
+ #define CSSLOT_ALTERNATE uint32_t(0x01000)
856
+
857
+ #define CSSLOT_SIGNATURESLOT uint32_t(0x10000)
858
+
859
+ #define CS_HASHTYPE_SHA160_160 1
860
+ #define CS_HASHTYPE_SHA256_256 2
861
+ #define CS_HASHTYPE_SHA256_160 3
862
+ #define CS_HASHTYPE_SHA386_386 4
863
+
864
+ struct BlobIndex {
865
+ uint32_t type;
866
+ uint32_t offset;
867
+ } _packed;
868
+
869
+ struct Blob {
870
+ uint32_t magic;
871
+ uint32_t length;
872
+ } _packed;
873
+
874
+ struct SuperBlob {
875
+ struct Blob blob;
876
+ uint32_t count;
877
+ struct BlobIndex index[];
878
+ } _packed;
879
+
880
+ struct CodeDirectory {
881
+ uint32_t version;
882
+ uint32_t flags;
883
+ uint32_t hashOffset;
884
+ uint32_t identOffset;
885
+ uint32_t nSpecialSlots;
886
+ uint32_t nCodeSlots;
887
+ uint32_t codeLimit;
888
+ uint8_t hashSize;
889
+ uint8_t hashType;
890
+ uint8_t platform;
891
+ uint8_t pageSize;
892
+ uint32_t spare2;
893
+ uint32_t scatterOffset;
894
+ uint32_t teamIDOffset;
895
+ uint32_t spare3;
896
+ uint64_t codeLimit64;
897
+ uint64_t execSegBase;
898
+ uint64_t execSegLimit;
899
+ uint64_t execSegFlags;
900
+ } _packed;
901
+
902
+ enum CodeSignatureFlags {
903
+ kSecCodeSignatureHost = 0x0001,
904
+ kSecCodeSignatureAdhoc = 0x0002,
905
+ kSecCodeSignatureForceHard = 0x0100,
906
+ kSecCodeSignatureForceKill = 0x0200,
907
+ kSecCodeSignatureForceExpiration = 0x0400,
908
+ kSecCodeSignatureRestrict = 0x0800,
909
+ kSecCodeSignatureEnforcement = 0x1000,
910
+ kSecCodeSignatureLibraryValidation = 0x2000,
911
+ };
912
+
913
+ enum Kind : uint32_t {
914
+ exprForm = 1, // prefix expr form
915
+ };
916
+
917
+ enum ExprOp : uint32_t {
918
+ opFalse, // unconditionally false
919
+ opTrue, // unconditionally true
920
+ opIdent, // match canonical code [string]
921
+ opAppleAnchor, // signed by Apple as Apple's product
922
+ opAnchorHash, // match anchor [cert hash]
923
+ opInfoKeyValue, // *legacy* - use opInfoKeyField [key; value]
924
+ opAnd, // binary prefix expr AND expr [expr; expr]
925
+ opOr, // binary prefix expr OR expr [expr; expr]
926
+ opCDHash, // match hash of CodeDirectory directly [cd hash]
927
+ opNot, // logical inverse [expr]
928
+ opInfoKeyField, // Info.plist key field [string; match suffix]
929
+ opCertField, // Certificate field [cert index; field name; match suffix]
930
+ opTrustedCert, // require trust settings to approve one particular cert [cert index]
931
+ opTrustedCerts, // require trust settings to approve the cert chain
932
+ opCertGeneric, // Certificate component by OID [cert index; oid; match suffix]
933
+ opAppleGenericAnchor, // signed by Apple in any capacity
934
+ opEntitlementField, // entitlement dictionary field [string; match suffix]
935
+ opCertPolicy, // Certificate policy by OID [cert index; oid; match suffix]
936
+ opNamedAnchor, // named anchor type
937
+ opNamedCode, // named subroutine
938
+ opPlatform, // platform constraint [integer]
939
+ exprOpCount // (total opcode count in use)
940
+ };
941
+
942
+ enum MatchOperation {
943
+ matchExists, // anything but explicit "false" - no value stored
944
+ matchEqual, // equal (CFEqual)
945
+ matchContains, // partial match (substring)
946
+ matchBeginsWith, // partial match (initial substring)
947
+ matchEndsWith, // partial match (terminal substring)
948
+ matchLessThan, // less than (string with numeric comparison)
949
+ matchGreaterThan, // greater than (string with numeric comparison)
950
+ matchLessEqual, // less or equal (string with numeric comparison)
951
+ matchGreaterEqual, // greater or equal (string with numeric comparison)
952
+ };
953
+
954
+ #define OID_ISO_MEMBER 42
955
+ #define OID_US OID_ISO_MEMBER, 134, 72
956
+ #define APPLE_OID OID_US, 0x86, 0xf7, 0x63
957
+ #define APPLE_ADS_OID APPLE_OID, 0x64
958
+ #define APPLE_EXTENSION_OID APPLE_ADS_OID, 6
959
+
960
+ #ifndef LDID_NOFLAGT
961
+ extern "C" uint32_t hash(uint8_t *k, uint32_t length, uint32_t initval);
962
+ #endif
963
+
964
+ struct Algorithm {
965
+ size_t size_;
966
+ uint8_t type_;
967
+
968
+ Algorithm(size_t size, uint8_t type) :
969
+ size_(size),
970
+ type_(type)
971
+ {
972
+ }
973
+
974
+ virtual const uint8_t *operator [](const ldid::Hash &hash) const = 0;
975
+
976
+ virtual void operator ()(uint8_t *hash, const void *data, size_t size) const = 0;
977
+ virtual void operator ()(ldid::Hash &hash, const void *data, size_t size) const = 0;
978
+ virtual void operator ()(std::vector<char> &hash, const void *data, size_t size) const = 0;
979
+
980
+ virtual const char *name() = 0;
981
+ };
982
+
983
+ struct AlgorithmSHA1 :
984
+ Algorithm
985
+ {
986
+ AlgorithmSHA1() :
987
+ Algorithm(LDID_SHA1_DIGEST_LENGTH, CS_HASHTYPE_SHA160_160)
988
+ {
989
+ }
990
+
991
+ virtual const uint8_t *operator [](const ldid::Hash &hash) const {
992
+ return hash.sha1_;
993
+ }
994
+
995
+ void operator ()(uint8_t *hash, const void *data, size_t size) const {
996
+ LDID_SHA1(static_cast<const uint8_t *>(data), size, hash);
997
+ }
998
+
999
+ void operator ()(ldid::Hash &hash, const void *data, size_t size) const {
1000
+ return operator()(hash.sha1_, data, size);
1001
+ }
1002
+
1003
+ void operator ()(std::vector<char> &hash, const void *data, size_t size) const {
1004
+ hash.resize(LDID_SHA1_DIGEST_LENGTH);
1005
+ return operator ()(reinterpret_cast<uint8_t *>(hash.data()), data, size);
1006
+ }
1007
+
1008
+ virtual const char *name() {
1009
+ return "sha1";
1010
+ }
1011
+ };
1012
+
1013
+ struct AlgorithmSHA256 :
1014
+ Algorithm
1015
+ {
1016
+ AlgorithmSHA256() :
1017
+ Algorithm(LDID_SHA256_DIGEST_LENGTH, CS_HASHTYPE_SHA256_256)
1018
+ {
1019
+ }
1020
+
1021
+ virtual const uint8_t *operator [](const ldid::Hash &hash) const {
1022
+ return hash.sha256_;
1023
+ }
1024
+
1025
+ void operator ()(uint8_t *hash, const void *data, size_t size) const {
1026
+ LDID_SHA256(static_cast<const uint8_t *>(data), size, hash);
1027
+ }
1028
+
1029
+ void operator ()(ldid::Hash &hash, const void *data, size_t size) const {
1030
+ return operator()(hash.sha256_, data, size);
1031
+ }
1032
+
1033
+ void operator ()(std::vector<char> &hash, const void *data, size_t size) const {
1034
+ hash.resize(LDID_SHA256_DIGEST_LENGTH);
1035
+ return operator ()(reinterpret_cast<uint8_t *>(hash.data()), data, size);
1036
+ }
1037
+
1038
+ virtual const char *name() {
1039
+ return "sha256";
1040
+ }
1041
+ };
1042
+
1043
+ static bool do_sha1(true);
1044
+ static bool do_sha256(true);
1045
+
1046
+ static const std::vector<Algorithm *> &GetAlgorithms() {
1047
+ static AlgorithmSHA1 sha1;
1048
+ static AlgorithmSHA256 sha256;
1049
+
1050
+ static std::vector<Algorithm *> algorithms;
1051
+ if (algorithms.empty()) {
1052
+ if (do_sha1)
1053
+ algorithms.push_back(&sha1);
1054
+ if (do_sha256)
1055
+ algorithms.push_back(&sha256);
1056
+ }
1057
+
1058
+ return algorithms;
1059
+ }
1060
+
1061
+ struct Baton {
1062
+ std::string entitlements_;
1063
+ };
1064
+
1065
+ struct CodesignAllocation {
1066
+ FatMachHeader mach_header_;
1067
+ uint32_t offset_;
1068
+ uint32_t size_;
1069
+ uint32_t limit_;
1070
+ uint32_t alloc_;
1071
+ uint32_t align_;
1072
+ const char *arch_;
1073
+ Baton baton_;
1074
+
1075
+ CodesignAllocation(FatMachHeader mach_header, size_t offset, size_t size, size_t limit, size_t alloc, size_t align, const char *arch, const Baton &baton) :
1076
+ mach_header_(mach_header),
1077
+ offset_(offset),
1078
+ size_(size),
1079
+ limit_(limit),
1080
+ alloc_(alloc),
1081
+ align_(align),
1082
+ arch_(arch),
1083
+ baton_(baton)
1084
+ {
1085
+ }
1086
+ };
1087
+
1088
+ #ifndef LDID_NOTOOLS
1089
+ class File {
1090
+ private:
1091
+ int file_;
1092
+
1093
+ public:
1094
+ File() :
1095
+ file_(-1)
1096
+ {
1097
+ }
1098
+
1099
+ ~File() {
1100
+ if (file_ != -1)
1101
+ _syscall(close(file_));
1102
+ }
1103
+
1104
+ void open(const char *path, int flags) {
1105
+ _assert(file_ == -1);
1106
+ file_ = _syscall(::open(path, flags));
1107
+ }
1108
+
1109
+ int file() const {
1110
+ return file_;
1111
+ }
1112
+ };
1113
+
1114
+ class Map {
1115
+ private:
1116
+ File file_;
1117
+ void *data_;
1118
+ size_t size_;
1119
+
1120
+ void clear() {
1121
+ if (data_ == NULL)
1122
+ return;
1123
+ _syscall(munmap(data_, size_));
1124
+ data_ = NULL;
1125
+ size_ = 0;
1126
+ }
1127
+
1128
+ public:
1129
+ Map() :
1130
+ data_(NULL),
1131
+ size_(0)
1132
+ {
1133
+ }
1134
+
1135
+ Map(const std::string &path, int oflag, int pflag, int mflag) :
1136
+ Map()
1137
+ {
1138
+ open(path, oflag, pflag, mflag);
1139
+ }
1140
+
1141
+ Map(const std::string &path, bool edit) :
1142
+ Map()
1143
+ {
1144
+ open(path, edit);
1145
+ }
1146
+
1147
+ ~Map() {
1148
+ clear();
1149
+ }
1150
+
1151
+ bool empty() const {
1152
+ return data_ == NULL;
1153
+ }
1154
+
1155
+ void open(const std::string &path, int oflag, int pflag, int mflag) {
1156
+ clear();
1157
+
1158
+ file_.open(path.c_str(), oflag);
1159
+ int file(file_.file());
1160
+
1161
+ struct stat stat;
1162
+ _syscall(fstat(file, &stat));
1163
+ size_ = stat.st_size;
1164
+
1165
+ data_ = _syscall(mmap(NULL, size_, pflag, mflag, file, 0));
1166
+ }
1167
+
1168
+ void open(const std::string &path, bool edit) {
1169
+ if (edit)
1170
+ open(path, O_RDWR, PROT_READ | PROT_WRITE, MAP_SHARED);
1171
+ else
1172
+ open(path, O_RDONLY, PROT_READ, MAP_PRIVATE);
1173
+ }
1174
+
1175
+ void *data() const {
1176
+ return data_;
1177
+ }
1178
+
1179
+ size_t size() const {
1180
+ return size_;
1181
+ }
1182
+
1183
+ operator std::string() const {
1184
+ return std::string(static_cast<char *>(data_), size_);
1185
+ }
1186
+ };
1187
+ #endif
1188
+
1189
+ namespace ldid {
1190
+
1191
+ #ifndef LDID_NOPLIST
1192
+ static plist_t plist(const std::string &data);
1193
+ #endif
1194
+
1195
+ void Analyze(const MachHeader &mach_header, const Functor<void (const char *data, size_t size)> &entitle) {
1196
+ _foreach (load_command, mach_header.GetLoadCommands())
1197
+ if (mach_header.Swap(load_command->cmd) == LC_CODE_SIGNATURE) {
1198
+ auto signature(reinterpret_cast<struct linkedit_data_command *>(load_command));
1199
+ auto offset(mach_header.Swap(signature->dataoff));
1200
+ auto pointer(reinterpret_cast<uint8_t *>(mach_header.GetBase()) + offset);
1201
+ auto super(reinterpret_cast<struct SuperBlob *>(pointer));
1202
+
1203
+ for (size_t index(0); index != Swap(super->count); ++index)
1204
+ if (Swap(super->index[index].type) == CSSLOT_ENTITLEMENTS) {
1205
+ auto begin(Swap(super->index[index].offset));
1206
+ auto blob(reinterpret_cast<struct Blob *>(pointer + begin));
1207
+ auto writ(Swap(blob->length) - sizeof(*blob));
1208
+ entitle(reinterpret_cast<char *>(blob + 1), writ);
1209
+ }
1210
+ }
1211
+ }
1212
+
1213
+ std::string Analyze(const void *data, size_t size) {
1214
+ std::string entitlements;
1215
+
1216
+ FatHeader fat_header(const_cast<void *>(data), size);
1217
+ _foreach (mach_header, fat_header.GetMachHeaders())
1218
+ Analyze(mach_header, fun([&](const char *data, size_t size) {
1219
+ if (entitlements.empty())
1220
+ entitlements.assign(data, size);
1221
+ else
1222
+ _assert(entitlements.compare(0, entitlements.size(), data, size) == 0);
1223
+ }));
1224
+
1225
+ return entitlements;
1226
+ }
1227
+
1228
+ static void Allocate(const void *idata, size_t isize, std::streambuf &output, const Functor<size_t (const MachHeader &, Baton &, size_t)> &allocate, const Functor<size_t (const MachHeader &, const Baton &, std::streambuf &output, size_t, const std::string &, const char *, const Progress &)> &save, const Progress &progress) {
1229
+ FatHeader source(const_cast<void *>(idata), isize);
1230
+
1231
+ size_t offset(0);
1232
+ if (source.IsFat())
1233
+ offset += sizeof(fat_header) + sizeof(fat_arch) * source.Swap(source->nfat_arch);
1234
+
1235
+ std::vector<CodesignAllocation> allocations;
1236
+ _foreach (mach_header, source.GetMachHeaders()) {
1237
+ struct linkedit_data_command *signature(NULL);
1238
+ struct symtab_command *symtab(NULL);
1239
+
1240
+ _foreach (load_command, mach_header.GetLoadCommands()) {
1241
+ uint32_t cmd(mach_header.Swap(load_command->cmd));
1242
+ if (false);
1243
+ else if (cmd == LC_CODE_SIGNATURE)
1244
+ signature = reinterpret_cast<struct linkedit_data_command *>(load_command);
1245
+ else if (cmd == LC_SYMTAB)
1246
+ symtab = reinterpret_cast<struct symtab_command *>(load_command);
1247
+ }
1248
+
1249
+ size_t size;
1250
+ if (signature == NULL)
1251
+ size = mach_header.GetSize();
1252
+ else {
1253
+ size = mach_header.Swap(signature->dataoff);
1254
+ _assert(size <= mach_header.GetSize());
1255
+ }
1256
+
1257
+ if (symtab != NULL) {
1258
+ auto end(mach_header.Swap(symtab->stroff) + mach_header.Swap(symtab->strsize));
1259
+ if (symtab->stroff != 0 || symtab->strsize != 0) {
1260
+ _assert(end <= size);
1261
+ _assert(end >= size - 0x10);
1262
+ size = end;
1263
+ }
1264
+ }
1265
+
1266
+ Baton baton;
1267
+ size_t alloc(allocate(mach_header, baton, size));
1268
+
1269
+ auto *fat_arch(mach_header.GetFatArch());
1270
+ uint32_t align;
1271
+
1272
+ if (fat_arch != NULL)
1273
+ align = source.Swap(fat_arch->align);
1274
+ else switch (mach_header.GetCPUType()) {
1275
+ case CPU_TYPE_POWERPC:
1276
+ case CPU_TYPE_POWERPC64:
1277
+ case CPU_TYPE_X86:
1278
+ case CPU_TYPE_X86_64:
1279
+ align = 0xc;
1280
+ break;
1281
+ case CPU_TYPE_ARM:
1282
+ case CPU_TYPE_ARM64:
1283
+ align = 0xe;
1284
+ break;
1285
+ default:
1286
+ align = 0x0;
1287
+ break;
1288
+ }
1289
+
1290
+ const char *arch(NULL);
1291
+ switch (mach_header.GetCPUType()) {
1292
+ case CPU_TYPE_POWERPC:
1293
+ arch = "ppc";
1294
+ break;
1295
+ case CPU_TYPE_POWERPC64:
1296
+ arch = "ppc64";
1297
+ break;
1298
+ case CPU_TYPE_X86:
1299
+ arch = "i386";
1300
+ break;
1301
+ case CPU_TYPE_X86_64:
1302
+ arch = "x86_64";
1303
+ break;
1304
+ case CPU_TYPE_ARM:
1305
+ arch = "arm";
1306
+ break;
1307
+ case CPU_TYPE_ARM64:
1308
+ arch = "arm64";
1309
+ break;
1310
+ }
1311
+
1312
+ offset = Align(offset, 1 << align);
1313
+
1314
+ uint32_t limit(size);
1315
+ if (alloc != 0)
1316
+ limit = Align(limit, 0x10);
1317
+
1318
+ allocations.push_back(CodesignAllocation(mach_header, offset, size, limit, alloc, align, arch, baton));
1319
+ offset += size + alloc;
1320
+ offset = Align(offset, 0x10);
1321
+ }
1322
+
1323
+ size_t position(0);
1324
+
1325
+ if (source.IsFat()) {
1326
+ fat_header fat_header;
1327
+ fat_header.magic = Swap(FAT_MAGIC);
1328
+ fat_header.nfat_arch = Swap(uint32_t(allocations.size()));
1329
+ put(output, &fat_header, sizeof(fat_header));
1330
+ position += sizeof(fat_header);
1331
+
1332
+ _foreach (allocation, allocations) {
1333
+ auto &mach_header(allocation.mach_header_);
1334
+
1335
+ fat_arch fat_arch;
1336
+ fat_arch.cputype = Swap(mach_header->cputype);
1337
+ fat_arch.cpusubtype = Swap(mach_header->cpusubtype);
1338
+ fat_arch.offset = Swap(allocation.offset_);
1339
+ fat_arch.size = Swap(allocation.limit_ + allocation.alloc_);
1340
+ fat_arch.align = Swap(allocation.align_);
1341
+ put(output, &fat_arch, sizeof(fat_arch));
1342
+ position += sizeof(fat_arch);
1343
+ }
1344
+ }
1345
+
1346
+ _foreach (allocation, allocations) {
1347
+ progress(allocation.arch_);
1348
+ auto &mach_header(allocation.mach_header_);
1349
+
1350
+ pad(output, allocation.offset_ - position);
1351
+ position = allocation.offset_;
1352
+
1353
+ std::vector<std::string> commands;
1354
+
1355
+ _foreach (load_command, mach_header.GetLoadCommands()) {
1356
+ std::string copy(reinterpret_cast<const char *>(load_command), load_command->cmdsize);
1357
+
1358
+ switch (mach_header.Swap(load_command->cmd)) {
1359
+ case LC_CODE_SIGNATURE:
1360
+ continue;
1361
+ break;
1362
+
1363
+ case LC_SEGMENT: {
1364
+ auto segment_command(reinterpret_cast<struct segment_command *>(&copy[0]));
1365
+ if (strncmp(segment_command->segname, "__LINKEDIT", 16) != 0)
1366
+ break;
1367
+ size_t size(mach_header.Swap(allocation.limit_ + allocation.alloc_ - mach_header.Swap(segment_command->fileoff)));
1368
+ segment_command->filesize = size;
1369
+ segment_command->vmsize = Align(size, 1 << allocation.align_);
1370
+ } break;
1371
+
1372
+ case LC_SEGMENT_64: {
1373
+ auto segment_command(reinterpret_cast<struct segment_command_64 *>(&copy[0]));
1374
+ if (strncmp(segment_command->segname, "__LINKEDIT", 16) != 0)
1375
+ break;
1376
+ size_t size(mach_header.Swap(allocation.limit_ + allocation.alloc_ - mach_header.Swap(segment_command->fileoff)));
1377
+ segment_command->filesize = size;
1378
+ segment_command->vmsize = Align(size, 1 << allocation.align_);
1379
+ } break;
1380
+ }
1381
+
1382
+ commands.push_back(copy);
1383
+ }
1384
+
1385
+ if (allocation.alloc_ != 0) {
1386
+ linkedit_data_command signature;
1387
+ signature.cmd = mach_header.Swap(LC_CODE_SIGNATURE);
1388
+ signature.cmdsize = mach_header.Swap(uint32_t(sizeof(signature)));
1389
+ signature.dataoff = mach_header.Swap(allocation.limit_);
1390
+ signature.datasize = mach_header.Swap(allocation.alloc_);
1391
+ commands.push_back(std::string(reinterpret_cast<const char *>(&signature), sizeof(signature)));
1392
+ }
1393
+
1394
+ size_t begin(position);
1395
+
1396
+ uint32_t after(0);
1397
+ _foreach(command, commands)
1398
+ after += command.size();
1399
+
1400
+ std::stringbuf altern;
1401
+
1402
+ struct mach_header header(*mach_header);
1403
+ header.ncmds = mach_header.Swap(uint32_t(commands.size()));
1404
+ header.sizeofcmds = mach_header.Swap(after);
1405
+ put(output, &header, sizeof(header));
1406
+ put(altern, &header, sizeof(header));
1407
+ position += sizeof(header);
1408
+
1409
+ if (mach_header.Bits64()) {
1410
+ auto pad(mach_header.Swap(uint32_t(0)));
1411
+ put(output, &pad, sizeof(pad));
1412
+ put(altern, &pad, sizeof(pad));
1413
+ position += sizeof(pad);
1414
+ }
1415
+
1416
+ _foreach(command, commands) {
1417
+ put(output, command.data(), command.size());
1418
+ put(altern, command.data(), command.size());
1419
+ position += command.size();
1420
+ }
1421
+
1422
+ uint32_t before(mach_header.Swap(mach_header->sizeofcmds));
1423
+ if (before > after) {
1424
+ pad(output, before - after);
1425
+ pad(altern, before - after);
1426
+ position += before - after;
1427
+ }
1428
+
1429
+ auto top(reinterpret_cast<char *>(mach_header.GetBase()));
1430
+
1431
+ std::string overlap(altern.str());
1432
+ overlap.append(top + overlap.size(), Align(overlap.size(), 0x1000) - overlap.size());
1433
+
1434
+ put(output, top + (position - begin), allocation.size_ - (position - begin), progress);
1435
+ position = begin + allocation.size_;
1436
+
1437
+ pad(output, allocation.limit_ - allocation.size_);
1438
+ position += allocation.limit_ - allocation.size_;
1439
+
1440
+ size_t saved(save(mach_header, allocation.baton_, output, allocation.limit_, overlap, top, progress));
1441
+ if (allocation.alloc_ > saved)
1442
+ pad(output, allocation.alloc_ - saved);
1443
+ else
1444
+ _assert(allocation.alloc_ == saved);
1445
+ position += allocation.alloc_;
1446
+ }
1447
+ }
1448
+
1449
+ }
1450
+
1451
+ typedef std::map<uint32_t, std::string> Blobs;
1452
+
1453
+ static void insert(Blobs &blobs, uint32_t slot, const std::stringbuf &buffer) {
1454
+ auto value(buffer.str());
1455
+ std::swap(blobs[slot], value);
1456
+ }
1457
+
1458
+ static const std::string &insert(Blobs &blobs, uint32_t slot, uint32_t magic, const std::stringbuf &buffer) {
1459
+ auto value(buffer.str());
1460
+ Blob blob;
1461
+ blob.magic = Swap(magic);
1462
+ blob.length = Swap(uint32_t(sizeof(blob) + value.size()));
1463
+ value.insert(0, reinterpret_cast<char *>(&blob), sizeof(blob));
1464
+ auto &save(blobs[slot]);
1465
+ std::swap(save, value);
1466
+ return save;
1467
+ }
1468
+
1469
+ static size_t put(std::streambuf &output, uint32_t magic, const Blobs &blobs) {
1470
+ size_t total(0);
1471
+ _foreach (blob, blobs)
1472
+ total += blob.second.size();
1473
+
1474
+ struct SuperBlob super;
1475
+ super.blob.magic = Swap(magic);
1476
+ super.blob.length = Swap(uint32_t(sizeof(SuperBlob) + blobs.size() * sizeof(BlobIndex) + total));
1477
+ super.count = Swap(uint32_t(blobs.size()));
1478
+ put(output, &super, sizeof(super));
1479
+
1480
+ size_t offset(sizeof(SuperBlob) + sizeof(BlobIndex) * blobs.size());
1481
+
1482
+ _foreach (blob, blobs) {
1483
+ BlobIndex index;
1484
+ index.type = Swap(blob.first);
1485
+ index.offset = Swap(uint32_t(offset));
1486
+ put(output, &index, sizeof(index));
1487
+ offset += blob.second.size();
1488
+ }
1489
+
1490
+ _foreach (blob, blobs)
1491
+ put(output, blob.second.data(), blob.second.size());
1492
+
1493
+ return offset;
1494
+ }
1495
+
1496
+ #ifndef LDID_NOSMIME
1497
+ class Buffer {
1498
+ private:
1499
+ BIO *bio_;
1500
+
1501
+ public:
1502
+ Buffer(BIO *bio) :
1503
+ bio_(bio)
1504
+ {
1505
+ _assert(bio_ != NULL);
1506
+ }
1507
+
1508
+ Buffer() :
1509
+ bio_(BIO_new(BIO_s_mem()))
1510
+ {
1511
+ }
1512
+
1513
+ Buffer(const char *data, size_t size) :
1514
+ Buffer(BIO_new_mem_buf(const_cast<char *>(data), size))
1515
+ {
1516
+ }
1517
+
1518
+ Buffer(const std::string &data) :
1519
+ Buffer(data.data(), data.size())
1520
+ {
1521
+ }
1522
+
1523
+ Buffer(PKCS7 *pkcs) :
1524
+ Buffer()
1525
+ {
1526
+ _assert(i2d_PKCS7_bio(bio_, pkcs) != 0);
1527
+ }
1528
+
1529
+ ~Buffer() {
1530
+ BIO_free_all(bio_);
1531
+ }
1532
+
1533
+ operator BIO *() const {
1534
+ return bio_;
1535
+ }
1536
+
1537
+ explicit operator std::string() const {
1538
+ char *data;
1539
+ auto size(BIO_get_mem_data(bio_, &data));
1540
+ return std::string(data, size);
1541
+ }
1542
+ };
1543
+
1544
+ class Stuff {
1545
+ private:
1546
+ PKCS12 *value_;
1547
+ EVP_PKEY *key_;
1548
+ X509 *cert_;
1549
+ STACK_OF(X509) *ca_;
1550
+
1551
+ public:
1552
+ Stuff(BIO *bio) :
1553
+ value_(d2i_PKCS12_bio(bio, NULL)),
1554
+ ca_(NULL)
1555
+ {
1556
+ _assert(value_ != NULL);
1557
+ _assert(PKCS12_parse(value_, "", &key_, &cert_, &ca_) != 0);
1558
+
1559
+ _assert(key_ != NULL);
1560
+ _assert(cert_ != NULL);
1561
+
1562
+ if (ca_ == NULL)
1563
+ ca_ = sk_X509_new_null();
1564
+ _assert(ca_ != NULL);
1565
+ }
1566
+
1567
+ Stuff(const std::string &data) :
1568
+ Stuff(Buffer(data))
1569
+ {
1570
+ }
1571
+
1572
+ ~Stuff() {
1573
+ sk_X509_pop_free(ca_, X509_free);
1574
+ X509_free(cert_);
1575
+ EVP_PKEY_free(key_);
1576
+ PKCS12_free(value_);
1577
+ }
1578
+
1579
+ operator PKCS12 *() const {
1580
+ return value_;
1581
+ }
1582
+
1583
+ operator EVP_PKEY *() const {
1584
+ return key_;
1585
+ }
1586
+
1587
+ operator X509 *() const {
1588
+ return cert_;
1589
+ }
1590
+
1591
+ operator STACK_OF(X509) *() const {
1592
+ return ca_;
1593
+ }
1594
+ };
1595
+
1596
+ class Signature {
1597
+ private:
1598
+ PKCS7 *value_;
1599
+
1600
+ public:
1601
+ Signature(const Stuff &stuff, const Buffer &data, const std::string &xml) {
1602
+ value_ = PKCS7_new();
1603
+ _assert(value_ != NULL);
1604
+
1605
+ _assert(PKCS7_set_type(value_, NID_pkcs7_signed));
1606
+ _assert(PKCS7_content_new(value_, NID_pkcs7_data));
1607
+
1608
+ STACK_OF(X509) *certs(stuff);
1609
+ for (unsigned i(0), e(sk_X509_num(certs)); i != e; i++)
1610
+ _assert(PKCS7_add_certificate(value_, sk_X509_value(certs, e - i - 1)));
1611
+
1612
+ // XXX: this is the same as PKCS7_sign_add_signer(value_, stuff, stuff, NULL, PKCS7_NOSMIMECAP)
1613
+ _assert(X509_check_private_key(stuff, stuff));
1614
+ auto info(PKCS7_add_signature(value_, stuff, stuff, EVP_sha1()));
1615
+ _assert(info != NULL);
1616
+ _assert(PKCS7_add_certificate(value_, stuff));
1617
+ _assert(PKCS7_add_signed_attribute(info, NID_pkcs9_contentType, V_ASN1_OBJECT, OBJ_nid2obj(NID_pkcs7_data)));
1618
+
1619
+ PKCS7_set_detached(value_, 1);
1620
+
1621
+ ASN1_OCTET_STRING *string(ASN1_OCTET_STRING_new());
1622
+ _assert(string != NULL);
1623
+ try {
1624
+ _assert(ASN1_STRING_set(string, xml.data(), xml.size()));
1625
+
1626
+ static auto nid(OBJ_create("1.2.840.113635.100.9.1", "", ""));
1627
+ _assert(PKCS7_add_signed_attribute(info, nid, V_ASN1_OCTET_STRING, string));
1628
+ } catch (...) {
1629
+ ASN1_OCTET_STRING_free(string);
1630
+ throw;
1631
+ }
1632
+
1633
+ // XXX: this is the same as PKCS7_final(value_, data, PKCS7_BINARY)
1634
+ BIO *bio(PKCS7_dataInit(value_, NULL));
1635
+ _assert(bio != NULL);
1636
+ _scope({ BIO_free_all(bio); });
1637
+ SMIME_crlf_copy(data, bio, PKCS7_BINARY);
1638
+ BIO_flush(bio);
1639
+ _assert(PKCS7_dataFinal(value_, bio));
1640
+ }
1641
+
1642
+ ~Signature() {
1643
+ PKCS7_free(value_);
1644
+ }
1645
+
1646
+ operator PKCS7 *() const {
1647
+ return value_;
1648
+ }
1649
+ };
1650
+ #endif
1651
+
1652
+ class NullBuffer :
1653
+ public std::streambuf
1654
+ {
1655
+ public:
1656
+ virtual std::streamsize xsputn(const char_type *data, std::streamsize size) {
1657
+ return size;
1658
+ }
1659
+
1660
+ virtual int_type overflow(int_type next) {
1661
+ return next;
1662
+ }
1663
+ };
1664
+
1665
+ class Digest {
1666
+ public:
1667
+ uint8_t sha1_[LDID_SHA1_DIGEST_LENGTH];
1668
+ };
1669
+
1670
+ class HashBuffer :
1671
+ public std::streambuf
1672
+ {
1673
+ private:
1674
+ ldid::Hash &hash_;
1675
+
1676
+ LDID_SHA1_CTX sha1_;
1677
+ LDID_SHA256_CTX sha256_;
1678
+
1679
+ public:
1680
+ HashBuffer(ldid::Hash &hash) :
1681
+ hash_(hash)
1682
+ {
1683
+ LDID_SHA1_Init(&sha1_);
1684
+ LDID_SHA256_Init(&sha256_);
1685
+ }
1686
+
1687
+ ~HashBuffer() {
1688
+ LDID_SHA1_Final(reinterpret_cast<uint8_t *>(hash_.sha1_), &sha1_);
1689
+ LDID_SHA256_Final(reinterpret_cast<uint8_t *>(hash_.sha256_), &sha256_);
1690
+ }
1691
+
1692
+ virtual std::streamsize xsputn(const char_type *data, std::streamsize size) {
1693
+ LDID_SHA1_Update(&sha1_, data, size);
1694
+ LDID_SHA256_Update(&sha256_, data, size);
1695
+ return size;
1696
+ }
1697
+
1698
+ virtual int_type overflow(int_type next) {
1699
+ if (next == traits_type::eof())
1700
+ return sync();
1701
+ char value(next);
1702
+ xsputn(&value, 1);
1703
+ return next;
1704
+ }
1705
+ };
1706
+
1707
+ class HashProxy :
1708
+ public HashBuffer
1709
+ {
1710
+ private:
1711
+ std::streambuf &buffer_;
1712
+
1713
+ public:
1714
+ HashProxy(ldid::Hash &hash, std::streambuf &buffer) :
1715
+ HashBuffer(hash),
1716
+ buffer_(buffer)
1717
+ {
1718
+ }
1719
+
1720
+ virtual std::streamsize xsputn(const char_type *data, std::streamsize size) {
1721
+ _assert(HashBuffer::xsputn(data, size) == size);
1722
+ return buffer_.sputn(data, size);
1723
+ }
1724
+ };
1725
+
1726
+ #ifndef LDID_NOTOOLS
1727
+ static bool Starts(const std::string &lhs, const std::string &rhs) {
1728
+ return lhs.size() >= rhs.size() && lhs.compare(0, rhs.size(), rhs) == 0;
1729
+ }
1730
+
1731
+ class Split {
1732
+ public:
1733
+ std::string dir;
1734
+ std::string base;
1735
+
1736
+ Split(const std::string &path) {
1737
+ size_t slash(path.rfind('/'));
1738
+ if (slash == std::string::npos)
1739
+ base = path;
1740
+ else {
1741
+ dir = path.substr(0, slash + 1);
1742
+ base = path.substr(slash + 1);
1743
+ }
1744
+ }
1745
+ };
1746
+
1747
+ static void mkdir_p(const std::string &path) {
1748
+ if (path.empty())
1749
+ return;
1750
+ #ifdef __WIN32__
1751
+ if (_syscall(mkdir(path.c_str()), EEXIST) == -EEXIST)
1752
+ return;
1753
+ #else
1754
+ if (_syscall(mkdir(path.c_str(), 0755), EEXIST) == -EEXIST)
1755
+ return;
1756
+ #endif
1757
+ auto slash(path.rfind('/', path.size() - 1));
1758
+ if (slash == std::string::npos)
1759
+ return;
1760
+ mkdir_p(path.substr(0, slash));
1761
+ }
1762
+
1763
+ static std::string Temporary(std::filebuf &file, const Split &split) {
1764
+ std::string temp(split.dir + ".ldid." + split.base);
1765
+ mkdir_p(split.dir);
1766
+ _assert_(file.open(temp.c_str(), std::ios::out | std::ios::trunc | std::ios::binary) == &file, "open(): %s", temp.c_str());
1767
+ return temp;
1768
+ }
1769
+
1770
+ static void Commit(const std::string &path, const std::string &temp) {
1771
+ struct stat info;
1772
+ if (_syscall(stat(path.c_str(), &info), ENOENT) == 0) {
1773
+ #ifndef __WIN32__
1774
+ _syscall(chown(temp.c_str(), info.st_uid, info.st_gid));
1775
+ #endif
1776
+ _syscall(chmod(temp.c_str(), info.st_mode));
1777
+ }
1778
+
1779
+ _syscall(rename(temp.c_str(), path.c_str()));
1780
+ }
1781
+ #endif
1782
+
1783
+ namespace ldid {
1784
+
1785
+ #ifndef LDID_NOSMIME
1786
+ static void get(std::string &value, X509_NAME *name, int nid) {
1787
+ auto index(X509_NAME_get_index_by_NID(name, nid, -1));
1788
+ _assert(index >= 0);
1789
+ auto next(X509_NAME_get_index_by_NID(name, nid, index));
1790
+ _assert(next == -1);
1791
+ auto entry(X509_NAME_get_entry(name, index));
1792
+ _assert(entry != NULL);
1793
+ auto asn(X509_NAME_ENTRY_get_data(entry));
1794
+ _assert(asn != NULL);
1795
+ value.assign(reinterpret_cast<char *>(ASN1_STRING_data(asn)), ASN1_STRING_length(asn));
1796
+ }
1797
+ #endif
1798
+
1799
+ static void req(std::streambuf &buffer, uint32_t value) {
1800
+ value = Swap(value);
1801
+ put(buffer, &value, sizeof(value));
1802
+ }
1803
+
1804
+ static void req(std::streambuf &buffer, const std::string &value) {
1805
+ req(buffer, value.size());
1806
+ put(buffer, value.data(), value.size());
1807
+ static uint8_t zeros[] = {0,0,0,0};
1808
+ put(buffer, zeros, 3 - (value.size() + 3) % 4);
1809
+ }
1810
+
1811
+ template <size_t Size_>
1812
+ static void req(std::streambuf &buffer, uint8_t (&&data)[Size_]) {
1813
+ req(buffer, Size_);
1814
+ put(buffer, data, Size_);
1815
+ static uint8_t zeros[] = {0,0,0,0};
1816
+ put(buffer, zeros, 3 - (Size_ + 3) % 4);
1817
+ }
1818
+
1819
+ Hash Sign(const void *idata, size_t isize, std::streambuf &output, const std::string &identifier, const std::string &entitlements, bool merge, const std::string &requirements, const std::string &key, const Slots &slots, uint32_t flags, bool platform, const Progress &progress) {
1820
+ Hash hash;
1821
+
1822
+
1823
+ std::string team;
1824
+ std::string common;
1825
+
1826
+ #ifndef LDID_NOSMIME
1827
+ if (!key.empty()) {
1828
+ Stuff stuff(key);
1829
+ auto name(X509_get_subject_name(stuff));
1830
+ _assert(name != NULL);
1831
+ get(team, name, NID_organizationalUnitName);
1832
+ get(common, name, NID_commonName);
1833
+ }
1834
+ #endif
1835
+
1836
+
1837
+ std::stringbuf backing;
1838
+
1839
+ if (!requirements.empty()) {
1840
+ put(backing, requirements.data(), requirements.size());
1841
+ } else {
1842
+ Blobs blobs;
1843
+
1844
+ std::stringbuf requirement;
1845
+ req(requirement, exprForm);
1846
+ req(requirement, opAnd);
1847
+ req(requirement, opIdent);
1848
+ req(requirement, identifier);
1849
+ req(requirement, opAnd);
1850
+ req(requirement, opAppleGenericAnchor);
1851
+ req(requirement, opAnd);
1852
+ req(requirement, opCertField);
1853
+ req(requirement, 0);
1854
+ req(requirement, "subject.CN");
1855
+ req(requirement, matchEqual);
1856
+ req(requirement, common);
1857
+ req(requirement, opCertGeneric);
1858
+ req(requirement, 1);
1859
+ req(requirement, (uint8_t []) {APPLE_EXTENSION_OID, 2, 1});
1860
+ req(requirement, matchExists);
1861
+ insert(blobs, 3, CSMAGIC_REQUIREMENT, requirement);
1862
+
1863
+ put(backing, CSMAGIC_REQUIREMENTS, blobs);
1864
+ }
1865
+
1866
+
1867
+ // XXX: this is just a "sufficiently large number"
1868
+ size_t certificate(0x3000);
1869
+
1870
+ Allocate(idata, isize, output, fun([&](const MachHeader &mach_header, Baton &baton, size_t size) -> size_t {
1871
+ size_t alloc(sizeof(struct SuperBlob));
1872
+
1873
+ uint32_t normal((size + PageSize_ - 1) / PageSize_);
1874
+
1875
+ uint32_t special(0);
1876
+
1877
+ _foreach (slot, slots)
1878
+ special = std::max(special, slot.first);
1879
+
1880
+ mach_header.ForSection(fun([&](const char *segment, const char *section, void *data, size_t size) {
1881
+ if (strcmp(segment, "__TEXT") == 0 && section != NULL && strcmp(section, "__info_plist") == 0)
1882
+ special = std::max(special, CSSLOT_INFOSLOT);
1883
+ }));
1884
+
1885
+ special = std::max(special, CSSLOT_REQUIREMENTS);
1886
+ alloc += sizeof(struct BlobIndex);
1887
+ alloc += backing.str().size();
1888
+
1889
+ if (!merge)
1890
+ baton.entitlements_ = entitlements;
1891
+ else {
1892
+ #ifndef LDID_NOPLIST
1893
+ Analyze(mach_header, fun([&](const char *data, size_t size) {
1894
+ baton.entitlements_.assign(data, size);
1895
+ }));
1896
+
1897
+ if (baton.entitlements_.empty())
1898
+ baton.entitlements_ = entitlements;
1899
+ else if (!entitlements.empty()) {
1900
+ auto combined(plist(baton.entitlements_));
1901
+ _scope({ plist_free(combined); });
1902
+ _assert(plist_get_node_type(combined) == PLIST_DICT);
1903
+
1904
+ auto merging(plist(entitlements));
1905
+ _scope({ plist_free(merging); });
1906
+ _assert(plist_get_node_type(merging) == PLIST_DICT);
1907
+
1908
+ plist_dict_iter iterator(NULL);
1909
+ plist_dict_new_iter(merging, &iterator);
1910
+ _scope({ free(iterator); });
1911
+
1912
+ for (;;) {
1913
+ char *key(NULL);
1914
+ plist_t value(NULL);
1915
+ plist_dict_next_item(merging, iterator, &key, &value);
1916
+ if (key == NULL)
1917
+ break;
1918
+ _scope({ free(key); });
1919
+ plist_dict_set_item(combined, key, plist_copy(value));
1920
+ }
1921
+
1922
+ char *xml(NULL);
1923
+ uint32_t size;
1924
+ plist_to_xml(combined, &xml, &size);
1925
+ _scope({ free(xml); });
1926
+
1927
+ baton.entitlements_.assign(xml, size);
1928
+ }
1929
+ #else
1930
+ _assert(false);
1931
+ #endif
1932
+ }
1933
+
1934
+ if (!baton.entitlements_.empty()) {
1935
+ special = std::max(special, CSSLOT_ENTITLEMENTS);
1936
+ alloc += sizeof(struct BlobIndex);
1937
+ alloc += sizeof(struct Blob);
1938
+ alloc += baton.entitlements_.size();
1939
+ }
1940
+
1941
+ size_t directory(0);
1942
+
1943
+ directory += sizeof(struct BlobIndex);
1944
+ directory += sizeof(struct Blob);
1945
+ directory += sizeof(struct CodeDirectory);
1946
+ directory += identifier.size() + 1;
1947
+
1948
+ if (!team.empty())
1949
+ directory += team.size() + 1;
1950
+
1951
+ for (Algorithm *algorithm : GetAlgorithms())
1952
+ alloc = Align(alloc + directory + (special + normal) * algorithm->size_, 16);
1953
+
1954
+ #ifndef LDID_NOSMIME
1955
+ if (!key.empty()) {
1956
+ alloc += sizeof(struct BlobIndex);
1957
+ alloc += sizeof(struct Blob);
1958
+ alloc += certificate;
1959
+ }
1960
+ #endif
1961
+
1962
+ return alloc;
1963
+ }), fun([&](const MachHeader &mach_header, const Baton &baton, std::streambuf &output, size_t limit, const std::string &overlap, const char *top, const Progress &progress) -> size_t {
1964
+ Blobs blobs;
1965
+
1966
+ if (true) {
1967
+ insert(blobs, CSSLOT_REQUIREMENTS, backing);
1968
+ }
1969
+
1970
+ if (!baton.entitlements_.empty()) {
1971
+ std::stringbuf data;
1972
+ put(data, baton.entitlements_.data(), baton.entitlements_.size());
1973
+ insert(blobs, CSSLOT_ENTITLEMENTS, CSMAGIC_EMBEDDED_ENTITLEMENTS, data);
1974
+ }
1975
+
1976
+ Slots posts(slots);
1977
+
1978
+ mach_header.ForSection(fun([&](const char *segment, const char *section, void *data, size_t size) {
1979
+ if (strcmp(segment, "__TEXT") == 0 && section != NULL && strcmp(section, "__info_plist") == 0) {
1980
+ auto &slot(posts[CSSLOT_INFOSLOT]);
1981
+ for (Algorithm *algorithm : GetAlgorithms())
1982
+ (*algorithm)(slot, data, size);
1983
+ }
1984
+ }));
1985
+
1986
+ unsigned total(0);
1987
+ for (Algorithm *pointer : GetAlgorithms()) {
1988
+ Algorithm &algorithm(*pointer);
1989
+
1990
+ std::stringbuf data;
1991
+
1992
+ uint32_t special(0);
1993
+ _foreach (blob, blobs)
1994
+ special = std::max(special, blob.first);
1995
+ _foreach (slot, posts)
1996
+ special = std::max(special, slot.first);
1997
+ uint32_t normal((limit + PageSize_ - 1) / PageSize_);
1998
+
1999
+ CodeDirectory directory;
2000
+ directory.version = Swap(uint32_t(0x00020400));
2001
+ directory.flags = Swap(uint32_t(flags));
2002
+ directory.nSpecialSlots = Swap(special);
2003
+ directory.codeLimit = Swap(uint32_t(limit));
2004
+ directory.nCodeSlots = Swap(normal);
2005
+ directory.hashSize = algorithm.size_;
2006
+ directory.hashType = algorithm.type_;
2007
+ directory.platform = platform ? 0x01 : 0x00;
2008
+ directory.pageSize = PageShift_;
2009
+ directory.spare2 = Swap(uint32_t(0));
2010
+ directory.scatterOffset = Swap(uint32_t(0));
2011
+ directory.spare3 = Swap(uint32_t(0));
2012
+ directory.codeLimit64 = Swap(uint64_t(0));;
2013
+ directory.execSegBase = Swap(uint64_t(0));
2014
+ directory.execSegLimit = Swap(uint64_t(0));
2015
+ directory.execSegFlags = Swap(uint64_t(0));
2016
+
2017
+ uint32_t offset(sizeof(Blob) + sizeof(CodeDirectory));
2018
+
2019
+ directory.identOffset = Swap(uint32_t(offset));
2020
+ offset += identifier.size() + 1;
2021
+
2022
+ if (team.empty())
2023
+ directory.teamIDOffset = Swap(uint32_t(0));
2024
+ else {
2025
+ directory.teamIDOffset = Swap(uint32_t(offset));
2026
+ offset += team.size() + 1;
2027
+ }
2028
+
2029
+ offset += special * algorithm.size_;
2030
+ directory.hashOffset = Swap(uint32_t(offset));
2031
+ offset += normal * algorithm.size_;
2032
+
2033
+ put(data, &directory, sizeof(directory));
2034
+
2035
+ put(data, identifier.c_str(), identifier.size() + 1);
2036
+ if (!team.empty())
2037
+ put(data, team.c_str(), team.size() + 1);
2038
+
2039
+ std::vector<uint8_t> storage((special + normal) * algorithm.size_);
2040
+ auto *hashes(&storage[special * algorithm.size_]);
2041
+
2042
+ memset(storage.data(), 0, special * algorithm.size_);
2043
+
2044
+ _foreach (blob, blobs) {
2045
+ auto local(reinterpret_cast<const Blob *>(&blob.second[0]));
2046
+ algorithm(hashes - blob.first * algorithm.size_, local, Swap(local->length));
2047
+ }
2048
+
2049
+ _foreach (slot, posts)
2050
+ memcpy(hashes - slot.first * algorithm.size_, algorithm[slot.second], algorithm.size_);
2051
+
2052
+ progress(0);
2053
+ if (normal != 1)
2054
+ for (size_t i = 0; i != normal - 1; ++i) {
2055
+ algorithm(hashes + i * algorithm.size_, (PageSize_ * i < overlap.size() ? overlap.data() : top) + PageSize_ * i, PageSize_);
2056
+ progress(double(i) / normal);
2057
+ }
2058
+ if (normal != 0)
2059
+ algorithm(hashes + (normal - 1) * algorithm.size_, top + PageSize_ * (normal - 1), ((limit - 1) % PageSize_) + 1);
2060
+ progress(1);
2061
+
2062
+ put(data, storage.data(), storage.size());
2063
+
2064
+ const auto &save(insert(blobs, total == 0 ? CSSLOT_CODEDIRECTORY : CSSLOT_ALTERNATE + total - 1, CSMAGIC_CODEDIRECTORY, data));
2065
+ algorithm(hash, save.data(), save.size());
2066
+
2067
+ ++total;
2068
+ }
2069
+
2070
+ #ifndef LDID_NOSMIME
2071
+ if (!key.empty()) {
2072
+ #ifdef LDID_NOPLIST
2073
+ auto plist(CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
2074
+ _scope({ CFRelease(plist); });
2075
+
2076
+ auto cdhashes(CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks));
2077
+ _scope({ CFRelease(cdhashes); });
2078
+
2079
+ CFDictionarySetValue(plist, CFSTR("cdhashes"), cdhashes);
2080
+ #else
2081
+ auto plist(plist_new_dict());
2082
+ _scope({ plist_free(plist); });
2083
+
2084
+ auto cdhashes(plist_new_array());
2085
+ plist_dict_set_item(plist, "cdhashes", cdhashes);
2086
+ #endif
2087
+
2088
+ unsigned total(0);
2089
+ for (Algorithm *pointer : GetAlgorithms()) {
2090
+ Algorithm &algorithm(*pointer);
2091
+ (void) algorithm;
2092
+
2093
+ const auto &blob(blobs[total == 0 ? CSSLOT_CODEDIRECTORY : CSSLOT_ALTERNATE + total - 1]);
2094
+ ++total;
2095
+
2096
+ std::vector<char> hash;
2097
+ algorithm(hash, blob.data(), blob.size());
2098
+ hash.resize(20);
2099
+
2100
+ #ifdef LDID_NOPLIST
2101
+ auto value(CFDataCreate(kCFAllocatorDefault, reinterpret_cast<const UInt8 *>(hash.data()), hash.size()));
2102
+ _scope({ CFRelease(value); });
2103
+ CFArrayAppendValue(cdhashes, value);
2104
+ #else
2105
+ plist_array_append_item(cdhashes, plist_new_data(hash.data(), hash.size()));
2106
+ #endif
2107
+ }
2108
+
2109
+ #ifdef LDID_NOPLIST
2110
+ auto created(CFPropertyListCreateXMLData(kCFAllocatorDefault, plist));
2111
+ _scope({ CFRelease(created); });
2112
+ auto xml(reinterpret_cast<const char *>(CFDataGetBytePtr(created)));
2113
+ auto size(CFDataGetLength(created));
2114
+ #else
2115
+ char *xml(NULL);
2116
+ uint32_t size;
2117
+ plist_to_xml(plist, &xml, &size);
2118
+ _scope({ free(xml); });
2119
+ #endif
2120
+
2121
+ std::stringbuf data;
2122
+ const std::string &sign(blobs[CSSLOT_CODEDIRECTORY]);
2123
+
2124
+ Stuff stuff(key);
2125
+ Buffer bio(sign);
2126
+
2127
+ Signature signature(stuff, sign, std::string(xml, size));
2128
+ Buffer result(signature);
2129
+ std::string value(result);
2130
+ put(data, value.data(), value.size());
2131
+
2132
+ const auto &save(insert(blobs, CSSLOT_SIGNATURESLOT, CSMAGIC_BLOBWRAPPER, data));
2133
+ _assert(save.size() <= certificate);
2134
+ }
2135
+ #endif
2136
+
2137
+ return put(output, CSMAGIC_EMBEDDED_SIGNATURE, blobs);
2138
+ }), progress);
2139
+
2140
+ return hash;
2141
+ }
2142
+
2143
+ #ifndef LDID_NOTOOLS
2144
+ static void Unsign(void *idata, size_t isize, std::streambuf &output, const Progress &progress) {
2145
+ Allocate(idata, isize, output, fun([](const MachHeader &mach_header, Baton &baton, size_t size) -> size_t {
2146
+ return 0;
2147
+ }), fun([](const MachHeader &mach_header, const Baton &baton, std::streambuf &output, size_t limit, const std::string &overlap, const char *top, const Progress &progress) -> size_t {
2148
+ return 0;
2149
+ }), progress);
2150
+ }
2151
+
2152
+ std::string DiskFolder::Path(const std::string &path) const {
2153
+ return path_ + "/" + path;
2154
+ }
2155
+
2156
+ DiskFolder::DiskFolder(const std::string &path) :
2157
+ path_(path)
2158
+ {
2159
+ }
2160
+
2161
+ DiskFolder::~DiskFolder() {
2162
+ if (!std::uncaught_exception())
2163
+ for (const auto &commit : commit_)
2164
+ Commit(commit.first, commit.second);
2165
+ }
2166
+
2167
+ #ifndef __WIN32__
2168
+ std::string readlink(const std::string &path) {
2169
+ for (size_t size(1024); ; size *= 2) {
2170
+ std::string data;
2171
+ data.resize(size);
2172
+
2173
+ int writ(_syscall(::readlink(path.c_str(), &data[0], data.size())));
2174
+ if (size_t(writ) >= size)
2175
+ continue;
2176
+
2177
+ data.resize(writ);
2178
+ return data;
2179
+ }
2180
+ }
2181
+ #endif
2182
+
2183
+ void DiskFolder::Find(const std::string &root, const std::string &base, const Functor<void (const std::string &)> &code, const Functor<void (const std::string &, const Functor<std::string ()> &)> &link) const {
2184
+ std::string path(Path(root) + base);
2185
+
2186
+ DIR *dir(opendir(path.c_str()));
2187
+ _assert(dir != NULL);
2188
+ _scope({ _syscall(closedir(dir)); });
2189
+
2190
+ while (auto child = readdir(dir)) {
2191
+ std::string name(child->d_name);
2192
+ if (name == "." || name == "..")
2193
+ continue;
2194
+ if (Starts(name, ".ldid."))
2195
+ continue;
2196
+
2197
+ bool directory;
2198
+
2199
+ #if defined(__WIN32__) || defined(__CYGWIN__) || defined(__MINGW32__)
2200
+ struct stat info;
2201
+ _syscall(stat((path + name).c_str(), &info));
2202
+ if (false);
2203
+ else if (S_ISDIR(info.st_mode))
2204
+ directory = true;
2205
+ else if (S_ISREG(info.st_mode))
2206
+ directory = false;
2207
+ else
2208
+ _assert_(false, "st_mode=%x", info.st_mode);
2209
+ #else
2210
+ switch (child->d_type) {
2211
+ case DT_DIR:
2212
+ directory = true;
2213
+ break;
2214
+ case DT_REG:
2215
+ directory = false;
2216
+ break;
2217
+ case DT_LNK:
2218
+ link(base + name, fun([&]() { return readlink(path + name); }));
2219
+ continue;
2220
+ default:
2221
+ _assert_(false, "d_type=%u", child->d_type);
2222
+ }
2223
+ #endif
2224
+
2225
+ if (directory)
2226
+ Find(root, base + name + "/", code, link);
2227
+ else
2228
+ code(base + name);
2229
+ }
2230
+ }
2231
+
2232
+ void DiskFolder::Save(const std::string &path, bool edit, const void *flag, const Functor<void (std::streambuf &)> &code) {
2233
+ if (!edit) {
2234
+ // XXX: use nullbuf
2235
+ std::stringbuf save;
2236
+ code(save);
2237
+ } else {
2238
+ std::filebuf save;
2239
+ auto from(Path(path));
2240
+ commit_[from] = Temporary(save, from);
2241
+ code(save);
2242
+ }
2243
+ }
2244
+
2245
+ bool DiskFolder::Look(const std::string &path) const {
2246
+ return _syscall(access(Path(path).c_str(), R_OK), ENOENT) == 0;
2247
+ }
2248
+
2249
+ void DiskFolder::Open(const std::string &path, const Functor<void (std::streambuf &, size_t, const void *)> &code) const {
2250
+ std::filebuf data;
2251
+ auto result(data.open(Path(path).c_str(), std::ios::binary | std::ios::in));
2252
+ _assert_(result == &data, "DiskFolder::Open(%s)", path.c_str());
2253
+
2254
+ auto length(data.pubseekoff(0, std::ios::end, std::ios::in));
2255
+ data.pubseekpos(0, std::ios::in);
2256
+ code(data, length, NULL);
2257
+ }
2258
+
2259
+ void DiskFolder::Find(const std::string &path, const Functor<void (const std::string &)> &code, const Functor<void (const std::string &, const Functor<std::string ()> &)> &link) const {
2260
+ Find(path, "", code, link);
2261
+ }
2262
+ #endif
2263
+
2264
+ SubFolder::SubFolder(Folder &parent, const std::string &path) :
2265
+ parent_(parent),
2266
+ path_(path)
2267
+ {
2268
+ }
2269
+
2270
+ void SubFolder::Save(const std::string &path, bool edit, const void *flag, const Functor<void (std::streambuf &)> &code) {
2271
+ return parent_.Save(path_ + path, edit, flag, code);
2272
+ }
2273
+
2274
+ bool SubFolder::Look(const std::string &path) const {
2275
+ return parent_.Look(path_ + path);
2276
+ }
2277
+
2278
+ void SubFolder::Open(const std::string &path, const Functor<void (std::streambuf &, size_t, const void *)> &code) const {
2279
+ return parent_.Open(path_ + path, code);
2280
+ }
2281
+
2282
+ void SubFolder::Find(const std::string &path, const Functor<void (const std::string &)> &code, const Functor<void (const std::string &, const Functor<std::string ()> &)> &link) const {
2283
+ return parent_.Find(path_ + path, code, link);
2284
+ }
2285
+
2286
+ std::string UnionFolder::Map(const std::string &path) const {
2287
+ auto remap(remaps_.find(path));
2288
+ if (remap == remaps_.end())
2289
+ return path;
2290
+ return remap->second;
2291
+ }
2292
+
2293
+ void UnionFolder::Map(const std::string &path, const Functor<void (const std::string &)> &code, const std::string &file, const Functor<void (const Functor<void (std::streambuf &, size_t, const void *)> &)> &save) const {
2294
+ if (file.size() >= path.size() && file.substr(0, path.size()) == path)
2295
+ code(file.substr(path.size()));
2296
+ }
2297
+
2298
+ UnionFolder::UnionFolder(Folder &parent) :
2299
+ parent_(parent)
2300
+ {
2301
+ }
2302
+
2303
+ void UnionFolder::Save(const std::string &path, bool edit, const void *flag, const Functor<void (std::streambuf &)> &code) {
2304
+ return parent_.Save(Map(path), edit, flag, code);
2305
+ }
2306
+
2307
+ bool UnionFolder::Look(const std::string &path) const {
2308
+ auto file(resets_.find(path));
2309
+ if (file != resets_.end())
2310
+ return true;
2311
+ return parent_.Look(Map(path));
2312
+ }
2313
+
2314
+ void UnionFolder::Open(const std::string &path, const Functor<void (std::streambuf &, size_t, const void *)> &code) const {
2315
+ auto file(resets_.find(path));
2316
+ if (file == resets_.end())
2317
+ return parent_.Open(Map(path), code);
2318
+ auto &entry(file->second);
2319
+
2320
+ auto &data(*entry.data_);
2321
+ auto length(data.pubseekoff(0, std::ios::end, std::ios::in));
2322
+ data.pubseekpos(0, std::ios::in);
2323
+ code(data, length, entry.flag_);
2324
+ }
2325
+
2326
+ void UnionFolder::Find(const std::string &path, const Functor<void (const std::string &)> &code, const Functor<void (const std::string &, const Functor<std::string ()> &)> &link) const {
2327
+ for (auto &reset : resets_)
2328
+ Map(path, code, reset.first, fun([&](const Functor<void (std::streambuf &, size_t, const void *)> &code) {
2329
+ auto &entry(reset.second);
2330
+ auto &data(*entry.data_);
2331
+ auto length(data.pubseekoff(0, std::ios::end, std::ios::in));
2332
+ data.pubseekpos(0, std::ios::in);
2333
+ code(data, length, entry.flag_);
2334
+ }));
2335
+
2336
+ for (auto &remap : remaps_)
2337
+ Map(path, code, remap.first, fun([&](const Functor<void (std::streambuf &, size_t, const void *)> &code) {
2338
+ parent_.Open(remap.second, fun([&](std::streambuf &data, size_t length, const void *flag) {
2339
+ code(data, length, flag);
2340
+ }));
2341
+ }));
2342
+
2343
+ parent_.Find(path, fun([&](const std::string &name) {
2344
+ if (deletes_.find(path + name) == deletes_.end())
2345
+ code(name);
2346
+ }), fun([&](const std::string &name, const Functor<std::string ()> &read) {
2347
+ if (deletes_.find(path + name) == deletes_.end())
2348
+ link(name, read);
2349
+ }));
2350
+ }
2351
+
2352
+ #ifndef LDID_NOTOOLS
2353
+ static void copy(std::streambuf &source, std::streambuf &target, size_t length, const Progress &progress) {
2354
+ progress(0);
2355
+ size_t total(0);
2356
+ for (;;) {
2357
+ char data[4096 * 4];
2358
+ size_t writ(source.sgetn(data, sizeof(data)));
2359
+ if (writ == 0)
2360
+ break;
2361
+ _assert(target.sputn(data, writ) == writ);
2362
+ total += writ;
2363
+ progress(double(total) / length);
2364
+ }
2365
+ }
2366
+
2367
+ #ifndef LDID_NOPLIST
2368
+ static plist_t plist(const std::string &data) {
2369
+ plist_t plist(NULL);
2370
+ if (Starts(data, "bplist00"))
2371
+ plist_from_bin(data.data(), data.size(), &plist);
2372
+ else
2373
+ plist_from_xml(data.data(), data.size(), &plist);
2374
+ _assert(plist != NULL);
2375
+ return plist;
2376
+ }
2377
+
2378
+ static void plist_d(std::streambuf &buffer, size_t length, const Functor<void (plist_t)> &code) {
2379
+ std::stringbuf data;
2380
+ copy(buffer, data, length, dummy_);
2381
+ auto node(plist(data.str()));
2382
+ _scope({ plist_free(node); });
2383
+ _assert(plist_get_node_type(node) == PLIST_DICT);
2384
+ code(node);
2385
+ }
2386
+
2387
+ static std::string plist_s(plist_t node) {
2388
+ _assert(node != NULL);
2389
+ _assert(plist_get_node_type(node) == PLIST_STRING);
2390
+ char *data;
2391
+ plist_get_string_val(node, &data);
2392
+ _scope({ free(data); });
2393
+ return data;
2394
+ }
2395
+ #endif
2396
+
2397
+ enum Mode {
2398
+ NoMode,
2399
+ OptionalMode,
2400
+ OmitMode,
2401
+ NestedMode,
2402
+ TopMode,
2403
+ };
2404
+
2405
+ class Expression {
2406
+ private:
2407
+ regex_t regex_;
2408
+ std::vector<std::string> matches_;
2409
+
2410
+ public:
2411
+ Expression(const std::string &code) {
2412
+ _assert_(regcomp(&regex_, code.c_str(), REG_EXTENDED) == 0, "regcomp()");
2413
+ matches_.resize(regex_.re_nsub + 1);
2414
+ }
2415
+
2416
+ ~Expression() {
2417
+ regfree(&regex_);
2418
+ }
2419
+
2420
+ bool operator ()(const std::string &data) {
2421
+ regmatch_t matches[matches_.size()];
2422
+ auto value(regexec(&regex_, data.c_str(), matches_.size(), matches, 0));
2423
+ if (value == REG_NOMATCH)
2424
+ return false;
2425
+ _assert_(value == 0, "regexec()");
2426
+ for (size_t i(0); i != matches_.size(); ++i)
2427
+ matches_[i].assign(data.data() + matches[i].rm_so, matches[i].rm_eo - matches[i].rm_so);
2428
+ return true;
2429
+ }
2430
+
2431
+ const std::string &operator [](size_t index) const {
2432
+ return matches_[index];
2433
+ }
2434
+ };
2435
+
2436
+ struct Rule {
2437
+ unsigned weight_;
2438
+ Mode mode_;
2439
+ std::string code_;
2440
+
2441
+ mutable std::unique_ptr<Expression> regex_;
2442
+
2443
+ Rule(unsigned weight, Mode mode, const std::string &code) :
2444
+ weight_(weight),
2445
+ mode_(mode),
2446
+ code_(code)
2447
+ {
2448
+ }
2449
+
2450
+ Rule(const Rule &rhs) :
2451
+ weight_(rhs.weight_),
2452
+ mode_(rhs.mode_),
2453
+ code_(rhs.code_)
2454
+ {
2455
+ }
2456
+
2457
+ void Compile() const {
2458
+ regex_.reset(new Expression(code_));
2459
+ }
2460
+
2461
+ bool operator ()(const std::string &data) const {
2462
+ _assert(regex_.get() != NULL);
2463
+ return (*regex_)(data);
2464
+ }
2465
+
2466
+ bool operator <(const Rule &rhs) const {
2467
+ if (weight_ > rhs.weight_)
2468
+ return true;
2469
+ if (weight_ < rhs.weight_)
2470
+ return false;
2471
+ return mode_ > rhs.mode_;
2472
+ }
2473
+ };
2474
+
2475
+ struct RuleCode {
2476
+ bool operator ()(const Rule *lhs, const Rule *rhs) const {
2477
+ return lhs->code_ < rhs->code_;
2478
+ }
2479
+ };
2480
+
2481
+ #ifndef LDID_NOPLIST
2482
+ static Hash Sign(const uint8_t *prefix, size_t size, std::streambuf &buffer, Hash &hash, std::streambuf &save, const std::string &identifier, const std::string &entitlements, bool merge, const std::string &requirements, const std::string &key, const Slots &slots, size_t length, uint32_t flags, bool platform, const Progress &progress) {
2483
+ // XXX: this is a miserable fail
2484
+ std::stringbuf temp;
2485
+ put(temp, prefix, size);
2486
+ copy(buffer, temp, length - size, progress);
2487
+ // XXX: this is a stupid hack
2488
+ pad(temp, 0x10 - (length & 0xf));
2489
+ auto data(temp.str());
2490
+
2491
+ HashProxy proxy(hash, save);
2492
+ return Sign(data.data(), data.size(), proxy, identifier, entitlements, merge, requirements, key, slots, flags, platform, progress);
2493
+ }
2494
+
2495
+ Bundle Sign(const std::string &root, Folder &folder, const std::string &key, std::map<std::string, Hash> &remote, const std::string &requirements, const Functor<std::string (const std::string &, const std::string &)> &alter, const Progress &progress) {
2496
+ std::string executable;
2497
+ std::string identifier;
2498
+
2499
+ bool mac(false);
2500
+
2501
+ std::string info("Info.plist");
2502
+ if (!folder.Look(info) && folder.Look("Resources/" + info)) {
2503
+ mac = true;
2504
+ info = "Resources/" + info;
2505
+ }
2506
+
2507
+ folder.Open(info, fun([&](std::streambuf &buffer, size_t length, const void *flag) {
2508
+ plist_d(buffer, length, fun([&](plist_t node) {
2509
+ executable = plist_s(plist_dict_get_item(node, "CFBundleExecutable"));
2510
+ identifier = plist_s(plist_dict_get_item(node, "CFBundleIdentifier"));
2511
+ }));
2512
+ }));
2513
+
2514
+ if (!mac && folder.Look("MacOS/" + executable)) {
2515
+ executable = "MacOS/" + executable;
2516
+ mac = true;
2517
+ }
2518
+
2519
+ progress(root + "*");
2520
+
2521
+ std::string entitlements;
2522
+ folder.Open(executable, fun([&](std::streambuf &buffer, size_t length, const void *flag) {
2523
+ // XXX: this is a miserable fail
2524
+ std::stringbuf temp;
2525
+ copy(buffer, temp, length, progress);
2526
+ // XXX: this is a stupid hack
2527
+ pad(temp, 0x10 - (length & 0xf));
2528
+ auto data(temp.str());
2529
+ entitlements = alter(root, Analyze(data.data(), data.size()));
2530
+ }));
2531
+
2532
+ static const std::string directory("_CodeSignature/");
2533
+ static const std::string signature(directory + "CodeResources");
2534
+
2535
+ std::map<std::string, std::multiset<Rule>> versions;
2536
+
2537
+ auto &rules1(versions[""]);
2538
+ auto &rules2(versions["2"]);
2539
+
2540
+ const std::string resources(mac ? "Resources/" : "");
2541
+
2542
+ if (true) {
2543
+ rules1.insert(Rule{1, NoMode, "^" + resources});
2544
+ rules1.insert(Rule{1000, OptionalMode, "^" + resources + ".*\\.lproj/"});
2545
+ rules1.insert(Rule{1100, OmitMode, "^" + resources + ".*\\.lproj/locversion.plist$"});
2546
+ rules1.insert(Rule{1010, NoMode, "^Base\\.lproj/"});
2547
+ rules1.insert(Rule{1, NoMode, "^version.plist$"});
2548
+ }
2549
+
2550
+ if (true) {
2551
+ rules2.insert(Rule{11, NoMode, ".*\\.dSYM($|/)"});
2552
+ rules2.insert(Rule{20, NoMode, "^" + resources});
2553
+ rules2.insert(Rule{2000, OmitMode, "^(.*/)?\\.DS_Store$"});
2554
+ rules2.insert(Rule{10, NestedMode, "^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/"});
2555
+ rules2.insert(Rule{1, NoMode, "^.*"});
2556
+ rules2.insert(Rule{1000, OptionalMode, "^" + resources + ".*\\.lproj/"});
2557
+ rules2.insert(Rule{1100, OmitMode, "^" + resources + ".*\\.lproj/locversion.plist$"});
2558
+ rules2.insert(Rule{1010, NoMode, "^Base\\.lproj/"});
2559
+ rules2.insert(Rule{20, OmitMode, "^Info\\.plist$"});
2560
+ rules2.insert(Rule{20, OmitMode, "^PkgInfo$"});
2561
+ rules2.insert(Rule{10, NestedMode, "^[^/]+$"});
2562
+ rules2.insert(Rule{20, NoMode, "^embedded\\.provisionprofile$"});
2563
+ rules2.insert(Rule{20, NoMode, "^version\\.plist$"});
2564
+ }
2565
+
2566
+ std::map<std::string, Hash> local;
2567
+
2568
+ std::string failure(mac ? "Contents/|Versions/[^/]*/Resources/" : "");
2569
+ Expression nested("^(Frameworks/[^/]*\\.framework|PlugIns/[^/]*\\.appex(()|/[^/]*.app))/(" + failure + ")Info\\.plist$");
2570
+ std::map<std::string, Bundle> bundles;
2571
+
2572
+ folder.Find("", fun([&](const std::string &name) {
2573
+ if (!nested(name))
2574
+ return;
2575
+ auto bundle(root + Split(name).dir);
2576
+ bundle.resize(bundle.size() - resources.size());
2577
+ SubFolder subfolder(folder, bundle);
2578
+
2579
+ bundles[nested[1]] = Sign(bundle, subfolder, key, local, "", Starts(name, "PlugIns/") ? alter :
2580
+ static_cast<const Functor<std::string (const std::string &, const std::string &)> &>(fun([&](const std::string &, const std::string &) -> std::string { return entitlements; }))
2581
+ , progress);
2582
+ }), fun([&](const std::string &name, const Functor<std::string ()> &read) {
2583
+ }));
2584
+
2585
+ std::set<std::string> excludes;
2586
+
2587
+ auto exclude([&](const std::string &name) {
2588
+ // BundleDiskRep::adjustResources -> builder.addExclusion
2589
+ if (name == executable || Starts(name, directory) || Starts(name, "_MASReceipt/") || name == "CodeResources")
2590
+ return true;
2591
+
2592
+ for (const auto &bundle : bundles)
2593
+ if (Starts(name, bundle.first + "/")) {
2594
+ excludes.insert(name);
2595
+ return true;
2596
+ }
2597
+
2598
+ return false;
2599
+ });
2600
+
2601
+ std::map<std::string, std::string> links;
2602
+
2603
+ folder.Find("", fun([&](const std::string &name) {
2604
+ if (exclude(name))
2605
+ return;
2606
+
2607
+ if (local.find(name) != local.end())
2608
+ return;
2609
+ auto &hash(local[name]);
2610
+
2611
+ folder.Open(name, fun([&](std::streambuf &data, size_t length, const void *flag) {
2612
+ progress(root + name);
2613
+
2614
+ union {
2615
+ struct {
2616
+ uint32_t magic;
2617
+ uint32_t count;
2618
+ };
2619
+
2620
+ uint8_t bytes[8];
2621
+ } header;
2622
+
2623
+ auto size(most(data, &header.bytes, sizeof(header.bytes)));
2624
+
2625
+ if (name != "_WatchKitStub/WK" && size == sizeof(header.bytes))
2626
+ switch (Swap(header.magic)) {
2627
+ case FAT_MAGIC:
2628
+ // Java class file format
2629
+ if (Swap(header.count) >= 40)
2630
+ break;
2631
+ case FAT_CIGAM:
2632
+ case MH_MAGIC: case MH_MAGIC_64:
2633
+ case MH_CIGAM: case MH_CIGAM_64:
2634
+ folder.Save(name, true, flag, fun([&](std::streambuf &save) {
2635
+ Slots slots;
2636
+ Sign(header.bytes, size, data, hash, save, identifier, "", false, "", key, slots, length, 0, false, Progression(progress, root + name));
2637
+ }));
2638
+ return;
2639
+ }
2640
+
2641
+ folder.Save(name, false, flag, fun([&](std::streambuf &save) {
2642
+ HashProxy proxy(hash, save);
2643
+ put(proxy, header.bytes, size);
2644
+ copy(data, proxy, length - size, progress);
2645
+ }));
2646
+ }));
2647
+ }), fun([&](const std::string &name, const Functor<std::string ()> &read) {
2648
+ if (exclude(name))
2649
+ return;
2650
+
2651
+ links[name] = read();
2652
+ }));
2653
+
2654
+ auto plist(plist_new_dict());
2655
+ _scope({ plist_free(plist); });
2656
+
2657
+ for (const auto &version : versions) {
2658
+ auto files(plist_new_dict());
2659
+ plist_dict_set_item(plist, ("files" + version.first).c_str(), files);
2660
+
2661
+ for (const auto &rule : version.second)
2662
+ rule.Compile();
2663
+
2664
+ bool old(&version.second == &rules1);
2665
+
2666
+ for (const auto &hash : local)
2667
+ for (const auto &rule : version.second)
2668
+ if (rule(hash.first)) {
2669
+ if (!old && mac && excludes.find(hash.first) != excludes.end());
2670
+ else if (old && rule.mode_ == NoMode)
2671
+ plist_dict_set_item(files, hash.first.c_str(), plist_new_data(reinterpret_cast<const char *>(hash.second.sha1_), sizeof(hash.second.sha1_)));
2672
+ else if (rule.mode_ != OmitMode) {
2673
+ auto entry(plist_new_dict());
2674
+ plist_dict_set_item(entry, "hash", plist_new_data(reinterpret_cast<const char *>(hash.second.sha1_), sizeof(hash.second.sha1_)));
2675
+ if (!old)
2676
+ plist_dict_set_item(entry, "hash2", plist_new_data(reinterpret_cast<const char *>(hash.second.sha256_), sizeof(hash.second.sha256_)));
2677
+ if (rule.mode_ == OptionalMode)
2678
+ plist_dict_set_item(entry, "optional", plist_new_bool(true));
2679
+ plist_dict_set_item(files, hash.first.c_str(), entry);
2680
+ }
2681
+
2682
+ break;
2683
+ }
2684
+
2685
+ for (const auto &link : links)
2686
+ for (const auto &rule : version.second)
2687
+ if (rule(link.first)) {
2688
+ if (rule.mode_ != OmitMode) {
2689
+ auto entry(plist_new_dict());
2690
+ plist_dict_set_item(entry, "symlink", plist_new_string(link.second.c_str()));
2691
+ if (rule.mode_ == OptionalMode)
2692
+ plist_dict_set_item(entry, "optional", plist_new_bool(true));
2693
+ plist_dict_set_item(files, link.first.c_str(), entry);
2694
+ }
2695
+
2696
+ break;
2697
+ }
2698
+
2699
+ if (!old && mac)
2700
+ for (const auto &bundle : bundles) {
2701
+ auto entry(plist_new_dict());
2702
+ plist_dict_set_item(entry, "cdhash", plist_new_data(reinterpret_cast<const char *>(bundle.second.hash.sha256_), sizeof(bundle.second.hash.sha256_)));
2703
+ plist_dict_set_item(entry, "requirement", plist_new_string("anchor apple generic"));
2704
+ plist_dict_set_item(files, bundle.first.c_str(), entry);
2705
+ }
2706
+ }
2707
+
2708
+ for (const auto &version : versions) {
2709
+ auto rules(plist_new_dict());
2710
+ plist_dict_set_item(plist, ("rules" + version.first).c_str(), rules);
2711
+
2712
+ std::multiset<const Rule *, RuleCode> ordered;
2713
+ for (const auto &rule : version.second)
2714
+ ordered.insert(&rule);
2715
+
2716
+ for (const auto &rule : ordered)
2717
+ if (rule->weight_ == 1 && rule->mode_ == NoMode)
2718
+ plist_dict_set_item(rules, rule->code_.c_str(), plist_new_bool(true));
2719
+ else {
2720
+ auto entry(plist_new_dict());
2721
+ plist_dict_set_item(rules, rule->code_.c_str(), entry);
2722
+
2723
+ switch (rule->mode_) {
2724
+ case NoMode:
2725
+ break;
2726
+ case OmitMode:
2727
+ plist_dict_set_item(entry, "omit", plist_new_bool(true));
2728
+ break;
2729
+ case OptionalMode:
2730
+ plist_dict_set_item(entry, "optional", plist_new_bool(true));
2731
+ break;
2732
+ case NestedMode:
2733
+ plist_dict_set_item(entry, "nested", plist_new_bool(true));
2734
+ break;
2735
+ case TopMode:
2736
+ plist_dict_set_item(entry, "top", plist_new_bool(true));
2737
+ break;
2738
+ }
2739
+
2740
+ if (rule->weight_ >= 10000)
2741
+ plist_dict_set_item(entry, "weight", plist_new_uint(rule->weight_));
2742
+ else if (rule->weight_ != 1)
2743
+ plist_dict_set_item(entry, "weight", plist_new_real(rule->weight_));
2744
+ }
2745
+ }
2746
+
2747
+ folder.Save(signature, true, NULL, fun([&](std::streambuf &save) {
2748
+ HashProxy proxy(local[signature], save);
2749
+ char *xml(NULL);
2750
+ uint32_t size;
2751
+ plist_to_xml(plist, &xml, &size);
2752
+ _scope({ free(xml); });
2753
+ put(proxy, xml, size);
2754
+ }));
2755
+
2756
+ Bundle bundle;
2757
+ bundle.path = executable;
2758
+
2759
+ folder.Open(executable, fun([&](std::streambuf &buffer, size_t length, const void *flag) {
2760
+ progress(root + executable);
2761
+ folder.Save(executable, true, flag, fun([&](std::streambuf &save) {
2762
+ Slots slots;
2763
+ slots[1] = local.at(info);
2764
+ slots[3] = local.at(signature);
2765
+ bundle.hash = Sign(NULL, 0, buffer, local[executable], save, identifier, entitlements, false, requirements, key, slots, length, 0, false, Progression(progress, root + executable));
2766
+ }));
2767
+ }));
2768
+
2769
+ for (const auto &entry : local)
2770
+ remote[root + entry.first] = entry.second;
2771
+
2772
+ return bundle;
2773
+ }
2774
+
2775
+ Bundle Sign(const std::string &root, Folder &folder, const std::string &key, const std::string &requirements, const Functor<std::string (const std::string &, const std::string &)> &alter, const Progress &progress) {
2776
+ std::map<std::string, Hash> local;
2777
+ return Sign(root, folder, key, local, requirements, alter, progress);
2778
+ }
2779
+ #endif
2780
+
2781
+ #endif
2782
+ }
2783
+
2784
+ static void usage(const char *argv0) {
2785
+ fprintf(stderr, "usage: %s -S[entitlements.xml] <binary>\n", argv0);
2786
+ fprintf(stderr, " %s -e MobileSafari\n", argv0);
2787
+ fprintf(stderr, " %s -S cat\n", argv0);
2788
+ fprintf(stderr, " %s -Stfp.xml gdb\n", argv0);
2789
+ fprintf(stderr, "\n");
2790
+ fprintf(stderr, "Other Options\n");
2791
+ fprintf(stderr, " -Kkey.p12 Sign using private key in key.p12\n");
2792
+ fprintf(stderr, " -M Merge entitlements with any existing\n");
2793
+ fprintf(stderr, " -d Print CDHash of file\n");
2794
+ }
2795
+
2796
+ static void print_hash(char *buf, uint8_t* hash, unsigned int hash_length)
2797
+ {
2798
+ int i = 0;
2799
+ char* p = buf;
2800
+ for (i = 0; i < hash_length; i++) {
2801
+ p += sprintf(p, "%02x", hash[i]);
2802
+ }
2803
+ }
2804
+
2805
+ #ifndef LDID_NOTOOLS
2806
+ int main(int argc, char *argv[]) {
2807
+ #ifndef LDID_NOSMIME
2808
+ OpenSSL_add_all_algorithms();
2809
+ #endif
2810
+
2811
+ union {
2812
+ uint16_t word;
2813
+ uint8_t byte[2];
2814
+ } endian = {1};
2815
+
2816
+ little_ = endian.byte[0];
2817
+
2818
+ bool flag_r(false);
2819
+ bool flag_e(false);
2820
+ bool flag_q(false);
2821
+
2822
+ bool flag_H(false);
2823
+
2824
+ #ifndef LDID_NOFLAGT
2825
+ bool flag_T(false);
2826
+ #endif
2827
+
2828
+ bool flag_S(false);
2829
+ bool flag_s(false);
2830
+
2831
+ bool flag_d(false);
2832
+ bool flag_D(false);
2833
+
2834
+ bool flag_A(false);
2835
+ bool flag_a(false);
2836
+
2837
+ bool flag_u(false);
2838
+
2839
+ bool flag_M(false);
2840
+
2841
+ uint32_t flags(0);
2842
+ bool platform(false);
2843
+
2844
+ uint32_t flag_CPUType(_not(uint32_t));
2845
+ uint32_t flag_CPUSubtype(_not(uint32_t));
2846
+
2847
+ const char *flag_I(NULL);
2848
+
2849
+ #ifndef LDID_NOFLAGT
2850
+ bool timeh(false);
2851
+ uint32_t timev(0);
2852
+ #endif
2853
+
2854
+ Map entitlements;
2855
+ Map requirements;
2856
+ Map key;
2857
+ ldid::Slots slots;
2858
+
2859
+ std::vector<std::string> files;
2860
+
2861
+ if (argc == 1) {
2862
+ usage(argv[0]);
2863
+ return 0;
2864
+ }
2865
+
2866
+ for (int argi(1); argi != argc; ++argi)
2867
+ if (argv[argi][0] != '-')
2868
+ files.push_back(argv[argi]);
2869
+ else switch (argv[argi][1]) {
2870
+ case 'r':
2871
+ _assert(!flag_s);
2872
+ _assert(!flag_S);
2873
+ flag_r = true;
2874
+ break;
2875
+
2876
+ case 'e': flag_e = true; break;
2877
+
2878
+ case 'E': {
2879
+ const char *string = argv[argi] + 2;
2880
+ const char *colon = strchr(string, ':');
2881
+ _assert(colon != NULL);
2882
+ Map file(colon + 1, O_RDONLY, PROT_READ, MAP_PRIVATE);
2883
+ char *arge;
2884
+ unsigned number(strtoul(string, &arge, 0));
2885
+ _assert(arge == colon);
2886
+ auto &slot(slots[number]);
2887
+ for (Algorithm *algorithm : GetAlgorithms())
2888
+ (*algorithm)(slot, file.data(), file.size());
2889
+ } break;
2890
+
2891
+ case 'q': flag_q = true; break;
2892
+
2893
+ case 'H': {
2894
+ const char *hash = argv[argi] + 2;
2895
+
2896
+ if (!flag_H) {
2897
+ flag_H = true;
2898
+
2899
+ do_sha1 = false;
2900
+ do_sha256 = false;
2901
+
2902
+ fprintf(stderr, "WARNING: -H is only present for compatibility with a fork of ldid\n");
2903
+ fprintf(stderr, " you should NOT be manually specifying the hash algorithm\n");
2904
+ }
2905
+
2906
+ if (false);
2907
+ else if (strcmp(hash, "sha1") == 0)
2908
+ do_sha1 = true;
2909
+ else if (strcmp(hash, "sha256") == 0)
2910
+ do_sha256 = true;
2911
+ else _assert(false);
2912
+ } break;
2913
+
2914
+ case 'Q': {
2915
+ const char *xml = argv[argi] + 2;
2916
+ requirements.open(xml, O_RDONLY, PROT_READ, MAP_PRIVATE);
2917
+ } break;
2918
+
2919
+ case 'd': flag_d = true; break;
2920
+
2921
+ case 'D': flag_D = true; break;
2922
+
2923
+ case 'a': flag_a = true; break;
2924
+
2925
+ case 'A':
2926
+ _assert(!flag_A);
2927
+ flag_A = true;
2928
+ if (argv[argi][2] != '\0') {
2929
+ const char *cpu = argv[argi] + 2;
2930
+ const char *colon = strchr(cpu, ':');
2931
+ _assert(colon != NULL);
2932
+ char *arge;
2933
+ flag_CPUType = strtoul(cpu, &arge, 0);
2934
+ _assert(arge == colon);
2935
+ flag_CPUSubtype = strtoul(colon + 1, &arge, 0);
2936
+ _assert(arge == argv[argi] + strlen(argv[argi]));
2937
+ }
2938
+ break;
2939
+
2940
+ case 'C': {
2941
+ const char *name = argv[argi] + 2;
2942
+ if (false);
2943
+ else if (strcmp(name, "host") == 0)
2944
+ flags |= kSecCodeSignatureHost;
2945
+ else if (strcmp(name, "adhoc") == 0)
2946
+ flags |= kSecCodeSignatureAdhoc;
2947
+ else if (strcmp(name, "hard") == 0)
2948
+ flags |= kSecCodeSignatureForceHard;
2949
+ else if (strcmp(name, "kill") == 0)
2950
+ flags |= kSecCodeSignatureForceKill;
2951
+ else if (strcmp(name, "expires") == 0)
2952
+ flags |= kSecCodeSignatureForceExpiration;
2953
+ else if (strcmp(name, "restrict") == 0)
2954
+ flags |= kSecCodeSignatureRestrict;
2955
+ else if (strcmp(name, "enforcement") == 0)
2956
+ flags |= kSecCodeSignatureEnforcement;
2957
+ else if (strcmp(name, "library-validation") == 0)
2958
+ flags |= kSecCodeSignatureLibraryValidation;
2959
+ else _assert(false);
2960
+ } break;
2961
+
2962
+ case 'P':
2963
+ platform = true;
2964
+ break;
2965
+
2966
+ case 's':
2967
+ _assert(!flag_r);
2968
+ _assert(!flag_S);
2969
+ flag_s = true;
2970
+ break;
2971
+
2972
+ case 'S':
2973
+ _assert(!flag_r);
2974
+ _assert(!flag_s);
2975
+ flag_S = true;
2976
+ if (argv[argi][2] != '\0') {
2977
+ const char *xml = argv[argi] + 2;
2978
+ entitlements.open(xml, O_RDONLY, PROT_READ, MAP_PRIVATE);
2979
+ }
2980
+ break;
2981
+
2982
+ case 'M':
2983
+ flag_M = true;
2984
+ break;
2985
+
2986
+ case 'K':
2987
+ if (argv[argi][2] != '\0')
2988
+ key.open(argv[argi] + 2, O_RDONLY, PROT_READ, MAP_PRIVATE);
2989
+ break;
2990
+
2991
+ #ifndef LDID_NOFLAGT
2992
+ case 'T': {
2993
+ flag_T = true;
2994
+ if (argv[argi][2] == '-')
2995
+ timeh = true;
2996
+ else {
2997
+ char *arge;
2998
+ timev = strtoul(argv[argi] + 2, &arge, 0);
2999
+ _assert(arge == argv[argi] + strlen(argv[argi]));
3000
+ }
3001
+ } break;
3002
+ #endif
3003
+
3004
+ case 'u': {
3005
+ flag_u = true;
3006
+ } break;
3007
+
3008
+ case 'I': {
3009
+ flag_I = argv[argi] + 2;
3010
+ } break;
3011
+
3012
+ default:
3013
+ usage(argv[0]);
3014
+ return 1;
3015
+ break;
3016
+ }
3017
+
3018
+ _assert(flag_S || key.empty());
3019
+ _assert(flag_S || flag_I == NULL);
3020
+
3021
+ if (files.empty())
3022
+ return 0;
3023
+
3024
+ size_t filei(0), filee(0);
3025
+ _foreach (file, files) try {
3026
+ std::string path(file);
3027
+
3028
+ struct stat info;
3029
+ _syscall(stat(path.c_str(), &info));
3030
+
3031
+ if (S_ISDIR(info.st_mode)) {
3032
+ #ifndef LDID_NOPLIST
3033
+ _assert(!flag_r);
3034
+ ldid::DiskFolder folder(path);
3035
+ path += "/" + Sign("", folder, key, requirements, ldid::fun([&](const std::string &, const std::string &) -> std::string { return entitlements; }), dummy_).path;
3036
+ #else
3037
+ _assert(false);
3038
+ #endif
3039
+ } else if (flag_S || flag_r) {
3040
+ Map input(path, O_RDONLY, PROT_READ, MAP_PRIVATE);
3041
+
3042
+ std::filebuf output;
3043
+ Split split(path);
3044
+ auto temp(Temporary(output, split));
3045
+
3046
+ if (flag_r)
3047
+ ldid::Unsign(input.data(), input.size(), output, dummy_);
3048
+ else {
3049
+ std::string identifier(flag_I ?: split.base.c_str());
3050
+ ldid::Sign(input.data(), input.size(), output, identifier, entitlements, flag_M, requirements, key, slots, flags, platform, dummy_);
3051
+ }
3052
+
3053
+ Commit(path, temp);
3054
+ }
3055
+
3056
+ bool modify(false);
3057
+ #ifndef LDID_NOFLAGT
3058
+ if (flag_T)
3059
+ modify = true;
3060
+ #endif
3061
+ if (flag_s)
3062
+ modify = true;
3063
+
3064
+ Map mapping(path, modify);
3065
+ FatHeader fat_header(mapping.data(), mapping.size());
3066
+
3067
+ _foreach (mach_header, fat_header.GetMachHeaders()) {
3068
+ struct linkedit_data_command *signature(NULL);
3069
+ struct encryption_info_command *encryption(NULL);
3070
+
3071
+ if (flag_A) {
3072
+ if (mach_header.GetCPUType() != flag_CPUType)
3073
+ continue;
3074
+ if (mach_header.GetCPUSubtype() != flag_CPUSubtype)
3075
+ continue;
3076
+ }
3077
+
3078
+ if (flag_a)
3079
+ printf("cpu=0x%x:0x%x\n", mach_header.GetCPUType(), mach_header.GetCPUSubtype());
3080
+
3081
+ _foreach (load_command, mach_header.GetLoadCommands()) {
3082
+ uint32_t cmd(mach_header.Swap(load_command->cmd));
3083
+
3084
+ if (false);
3085
+ else if (cmd == LC_CODE_SIGNATURE)
3086
+ signature = reinterpret_cast<struct linkedit_data_command *>(load_command);
3087
+ else if (cmd == LC_ENCRYPTION_INFO || cmd == LC_ENCRYPTION_INFO_64)
3088
+ encryption = reinterpret_cast<struct encryption_info_command *>(load_command);
3089
+ else if (cmd == LC_LOAD_DYLIB) {
3090
+ volatile struct dylib_command *dylib_command(reinterpret_cast<struct dylib_command *>(load_command));
3091
+ const char *name(reinterpret_cast<const char *>(load_command) + mach_header.Swap(dylib_command->dylib.name));
3092
+
3093
+ if (strcmp(name, "/System/Library/Frameworks/UIKit.framework/UIKit") == 0) {
3094
+ if (flag_u) {
3095
+ Version version;
3096
+ version.value = mach_header.Swap(dylib_command->dylib.current_version);
3097
+ printf("uikit=%u.%u.%u\n", version.major, version.minor, version.patch);
3098
+ }
3099
+ }
3100
+ }
3101
+ #ifndef LDID_NOFLAGT
3102
+ else if (cmd == LC_ID_DYLIB) {
3103
+ volatile struct dylib_command *dylib_command(reinterpret_cast<struct dylib_command *>(load_command));
3104
+
3105
+ if (flag_T) {
3106
+ uint32_t timed;
3107
+
3108
+ if (!timeh)
3109
+ timed = timev;
3110
+ else {
3111
+ dylib_command->dylib.timestamp = 0;
3112
+ timed = hash(reinterpret_cast<uint8_t *>(mach_header.GetBase()), mach_header.GetSize(), timev);
3113
+ }
3114
+
3115
+ dylib_command->dylib.timestamp = mach_header.Swap(timed);
3116
+ }
3117
+ }
3118
+ #endif
3119
+ }
3120
+
3121
+ if (flag_D) {
3122
+ _assert(encryption != NULL);
3123
+ encryption->cryptid = mach_header.Swap(0);
3124
+ }
3125
+
3126
+ if (flag_e) {
3127
+ _assert(signature != NULL);
3128
+
3129
+ uint32_t data = mach_header.Swap(signature->dataoff);
3130
+
3131
+ uint8_t *top = reinterpret_cast<uint8_t *>(mach_header.GetBase());
3132
+ uint8_t *blob = top + data;
3133
+ struct SuperBlob *super = reinterpret_cast<struct SuperBlob *>(blob);
3134
+
3135
+ for (size_t index(0); index != Swap(super->count); ++index)
3136
+ if (Swap(super->index[index].type) == CSSLOT_ENTITLEMENTS) {
3137
+ uint32_t begin = Swap(super->index[index].offset);
3138
+ struct Blob *entitlements = reinterpret_cast<struct Blob *>(blob + begin);
3139
+ fwrite(entitlements + 1, 1, Swap(entitlements->length) - sizeof(*entitlements), stdout);
3140
+ }
3141
+ }
3142
+
3143
+ if (flag_q) {
3144
+ _assert(signature != NULL);
3145
+
3146
+ uint32_t data = mach_header.Swap(signature->dataoff);
3147
+
3148
+ uint8_t *top = reinterpret_cast<uint8_t *>(mach_header.GetBase());
3149
+ uint8_t *blob = top + data;
3150
+ struct SuperBlob *super = reinterpret_cast<struct SuperBlob *>(blob);
3151
+
3152
+ for (size_t index(0); index != Swap(super->count); ++index)
3153
+ if (Swap(super->index[index].type) == CSSLOT_REQUIREMENTS) {
3154
+ uint32_t begin = Swap(super->index[index].offset);
3155
+ struct Blob *requirement = reinterpret_cast<struct Blob *>(blob + begin);
3156
+ fwrite(requirement, 1, Swap(requirement->length), stdout);
3157
+ }
3158
+ }
3159
+
3160
+ if (flag_d) {
3161
+ _assert(signature != NULL);
3162
+
3163
+ uint32_t data = mach_header.Swap(signature->dataoff);
3164
+ uint8_t *top = reinterpret_cast<uint8_t *>(mach_header.GetBase());
3165
+ uint8_t *blob = top + data;
3166
+ struct SuperBlob *super = reinterpret_cast<struct SuperBlob *>(blob);
3167
+ bool has_alternate = false;
3168
+ char cdhash_sha1_str[LDID_SHA1_DIGEST_LENGTH*2 + 1] = {0, };
3169
+ char cdhash_sha256_str[LDID_SHA256_DIGEST_LENGTH*2 + 1] = {0, };
3170
+ int max_hash_type = 0;
3171
+ char* cdhash_str = NULL;
3172
+ char hash_choices[64] = {0, };
3173
+
3174
+ for (size_t index(0); index != Swap(super->count); ++index) {
3175
+ switch (Swap(super->index[index].type)) {
3176
+ case CSSLOT_ALTERNATE:
3177
+ has_alternate = true;
3178
+ case CSSLOT_CODEDIRECTORY:
3179
+ {
3180
+ uint32_t begin = Swap(super->index[index].offset);
3181
+ struct CodeDirectory *directory = reinterpret_cast<struct CodeDirectory *>(blob + begin + sizeof(Blob));
3182
+ struct Blob *cdblob = reinterpret_cast<struct Blob *>(blob + begin);
3183
+ if (directory->hashType == 1) {
3184
+ uint8_t cdhash_sha1[LDID_SHA1_DIGEST_LENGTH];
3185
+ LDID_SHA1((const unsigned char*)cdblob, Swap(cdblob->length), cdhash_sha1);
3186
+ print_hash(cdhash_sha1_str, cdhash_sha1, LDID_SHA1_DIGEST_LENGTH);
3187
+ printf("CandidateCDHash sha1=%s\n", cdhash_sha1_str);
3188
+ if (*hash_choices) strcat(hash_choices, ",");
3189
+ strcat(hash_choices, "sha1");
3190
+ if (1 > max_hash_type) {
3191
+ max_hash_type = 1;
3192
+ cdhash_str = &cdhash_sha1_str[0];
3193
+ }
3194
+ } else if (directory->hashType == 2) {
3195
+ uint8_t cdhash_sha256[LDID_SHA256_DIGEST_LENGTH];
3196
+ LDID_SHA256((const unsigned char*)cdblob, Swap(cdblob->length), cdhash_sha256);
3197
+ print_hash(cdhash_sha256_str, cdhash_sha256, LDID_SHA1_DIGEST_LENGTH);
3198
+ printf("CandidateCDHash sha256=%s\n", cdhash_sha256_str);
3199
+ cdhash_sha256_str[LDID_SHA1_DIGEST_LENGTH*2] = '\0';
3200
+ if (*hash_choices) strcat(hash_choices, ",");
3201
+ strcat(hash_choices, "sha256");
3202
+ if (2 > max_hash_type) {
3203
+ max_hash_type = 2;
3204
+ cdhash_str = &cdhash_sha256_str[0];
3205
+ }
3206
+ }
3207
+ }
3208
+ break;
3209
+ }
3210
+ }
3211
+ if (has_alternate) {
3212
+ printf("Hash choices=%s\n", hash_choices);
3213
+ }
3214
+ if (cdhash_str) {
3215
+ printf("CDHash=%s\n", cdhash_str);
3216
+ }
3217
+ }
3218
+
3219
+ if (flag_s) {
3220
+ _assert(signature != NULL);
3221
+
3222
+ uint32_t data = mach_header.Swap(signature->dataoff);
3223
+
3224
+ uint8_t *top = reinterpret_cast<uint8_t *>(mach_header.GetBase());
3225
+ uint8_t *blob = top + data;
3226
+ struct SuperBlob *super = reinterpret_cast<struct SuperBlob *>(blob);
3227
+
3228
+ for (size_t index(0); index != Swap(super->count); ++index)
3229
+ if (Swap(super->index[index].type) == CSSLOT_CODEDIRECTORY) {
3230
+ uint32_t begin = Swap(super->index[index].offset);
3231
+ struct CodeDirectory *directory = reinterpret_cast<struct CodeDirectory *>(blob + begin + sizeof(Blob));
3232
+
3233
+ uint8_t (*hashes)[LDID_SHA1_DIGEST_LENGTH] = reinterpret_cast<uint8_t (*)[LDID_SHA1_DIGEST_LENGTH]>(blob + begin + Swap(directory->hashOffset));
3234
+ uint32_t pages = Swap(directory->nCodeSlots);
3235
+
3236
+ if (pages != 1)
3237
+ for (size_t i = 0; i != pages - 1; ++i)
3238
+ LDID_SHA1(top + PageSize_ * i, PageSize_, hashes[i]);
3239
+ if (pages != 0)
3240
+ LDID_SHA1(top + PageSize_ * (pages - 1), ((data - 1) % PageSize_) + 1, hashes[pages - 1]);
3241
+ }
3242
+ }
3243
+ }
3244
+
3245
+ ++filei;
3246
+ } catch (const char *) {
3247
+ ++filee;
3248
+ ++filei;
3249
+ }
3250
+
3251
+ return filee;
3252
+ }
3253
+ #endif