From f7aa9f666a1c7ab343b4ce8f1677ea253c4e126e Mon Sep 17 00:00:00 2001 From: Apple Date: Mon, 1 Oct 2007 21:50:55 +0000 Subject: [PATCH] securityd-32661.tar.gz --- APPLE_LICENSE | 367 +++++ doc/BLOBFORMAT | 1 - doc/securityd.1 | 4 +- etc/CodeEquivalenceCandidates | 9 +- etc/authorization.plist | 287 ++-- etc/com.apple.securityd.plist | 25 + etc/securityd-installCD.plist | 12 - etc/securityd.plist | 12 - etc/startup.mk | 6 +- securityd.xcode/project.pbxproj | 1942 --------------------------- securityd.xcodeproj/project.pbxproj | 1213 +++++++++++++++++ src/AuthorizationDBPlist.cpp | 237 ++-- src/AuthorizationDBPlist.h | 6 +- src/AuthorizationEngine.cpp | 47 +- src/AuthorizationMechEval.cpp | 30 +- src/AuthorizationMechEval.h | 1 + src/AuthorizationRule.cpp | 560 ++++---- src/AuthorizationRule.h | 7 +- src/SharedMemoryServer.cpp | 150 +++ src/SharedMemoryServer.h | 36 + src/acl_keychain.cpp | 138 +- src/acl_keychain.h | 18 +- src/acls.cpp | 107 +- src/acls.h | 41 +- src/agentquery.cpp | 38 +- src/agentquery.h | 3 +- src/authhost.cpp | 53 +- src/authority.cpp | 16 +- src/authority.h | 17 +- src/child.cpp | 2 + src/clientid.cpp | 194 +++ src/clientid.h | 81 ++ src/codesigdb.cpp | 274 +++- src/codesigdb.h | 18 +- src/connection.cpp | 30 +- src/connection.h | 40 +- src/credential.cpp | 179 +++ src/credential.h | 101 ++ src/csproxy.cpp | 478 +++++++ src/csproxy.h | 116 ++ src/database.cpp | 7 +- src/database.h | 6 +- src/dbcrypto.cpp | 172 ++- src/dbcrypto.h | 5 +- src/flippers.cpp | 115 -- src/flippers.h | 91 -- src/generate.cf | 44 - src/generate.mk | 39 - src/generate.pl | 74 - src/kcdatabase.cpp | 217 ++- src/kcdatabase.h | 20 +- src/kckey.cpp | 10 +- src/kckey.h | 2 +- src/localdatabase.cpp | 3 +- src/localkey.cpp | 6 +- src/main.cpp | 66 +- src/notifications.cpp | 161 ++- src/notifications.h | 86 +- src/osxcodewrap.cpp | 64 + src/osxcodewrap.h | 60 + src/pcscmonitor.cpp | 73 +- src/pcscmonitor.h | 9 +- src/process.cpp | 117 +- src/process.h | 39 +- src/securityd.exp | 0 src/securityd.order | 1 - src/server.cpp | 156 ++- src/server.h | 32 +- src/session.cpp | 47 +- src/session.h | 20 +- src/token.cpp | 45 +- src/token.h | 3 +- src/tokenacl.cpp | 7 +- src/tokencache.cpp | 8 +- src/tokend.cpp | 4 +- src/tokend.h | 6 +- src/tokendatabase.cpp | 146 +- src/tokendatabase.h | 20 +- src/transition.cpp | 910 ++++++++----- src/transwalkers.cpp | 190 --- src/transwalkers.h | 313 ----- 81 files changed, 5869 insertions(+), 4421 deletions(-) create mode 100644 APPLE_LICENSE create mode 100644 etc/com.apple.securityd.plist delete mode 100644 etc/securityd-installCD.plist delete mode 100644 etc/securityd.plist delete mode 100644 securityd.xcode/project.pbxproj create mode 100644 securityd.xcodeproj/project.pbxproj create mode 100644 src/SharedMemoryServer.cpp create mode 100644 src/SharedMemoryServer.h create mode 100644 src/clientid.cpp create mode 100644 src/clientid.h create mode 100644 src/credential.cpp create mode 100644 src/credential.h create mode 100644 src/csproxy.cpp create mode 100644 src/csproxy.h delete mode 100644 src/flippers.cpp delete mode 100644 src/flippers.h delete mode 100644 src/generate.cf delete mode 100644 src/generate.mk delete mode 100755 src/generate.pl create mode 100644 src/osxcodewrap.cpp create mode 100644 src/osxcodewrap.h create mode 100644 src/securityd.exp delete mode 100644 src/transwalkers.cpp delete mode 100644 src/transwalkers.h diff --git a/APPLE_LICENSE b/APPLE_LICENSE new file mode 100644 index 0000000..fe81a60 --- /dev/null +++ b/APPLE_LICENSE @@ -0,0 +1,367 @@ +APPLE PUBLIC SOURCE LICENSE +Version 2.0 - August 6, 2003 + +Please read this License carefully before downloading this software. +By downloading or using this software, you are agreeing to be bound by +the terms of this License. If you do not or cannot agree to the terms +of this License, please do not download or use the software. + +1. General; Definitions. This License applies to any program or other +work which Apple Computer, Inc. ("Apple") makes publicly available and +which contains a notice placed by Apple identifying such program or +work as "Original Code" and stating that it is subject to the terms of +this Apple Public Source License version 2.0 ("License"). As used in +this License: + +1.1 "Applicable Patent Rights" mean: (a) in the case where Apple is +the grantor of rights, (i) claims of patents that are now or hereafter +acquired, owned by or assigned to Apple and (ii) that cover subject +matter contained in the Original Code, but only to the extent +necessary to use, reproduce and/or distribute the Original Code +without infringement; and (b) in the case where You are the grantor of +rights, (i) claims of patents that are now or hereafter acquired, +owned by or assigned to You and (ii) that cover subject matter in Your +Modifications, taken alone or in combination with Original Code. + +1.2 "Contributor" means any person or entity that creates or +contributes to the creation of Modifications. + +1.3 "Covered Code" means the Original Code, Modifications, the +combination of Original Code and any Modifications, and/or any +respective portions thereof. + +1.4 "Externally Deploy" means: (a) to sublicense, distribute or +otherwise make Covered Code available, directly or indirectly, to +anyone other than You; and/or (b) to use Covered Code, alone or as +part of a Larger Work, in any way to provide a service, including but +not limited to delivery of content, through electronic communication +with a client other than You. + +1.5 "Larger Work" means a work which combines Covered Code or portions +thereof with code not governed by the terms of this License. + +1.6 "Modifications" mean any addition to, deletion from, and/or change +to, the substance and/or structure of the Original Code, any previous +Modifications, the combination of Original Code and any previous +Modifications, and/or any respective portions thereof. When code is +released as a series of files, a Modification is: (a) any addition to +or deletion from the contents of a file containing Covered Code; +and/or (b) any new file or other representation of computer program +statements that contains any part of Covered Code. + +1.7 "Original Code" means (a) the Source Code of a program or other +work as originally made available by Apple under this License, +including the Source Code of any updates or upgrades to such programs +or works made available by Apple under this License, and that has been +expressly identified by Apple as such in the header file(s) of such +work; and (b) the object code compiled from such Source Code and +originally made available by Apple under this License. + +1.8 "Source Code" means the human readable form of a program or other +work that is suitable for making modifications to it, including all +modules it contains, plus any associated interface definition files, +scripts used to control compilation and installation of an executable +(object code). + +1.9 "You" or "Your" means an individual or a legal entity exercising +rights under this License. For legal entities, "You" or "Your" +includes any entity which controls, is controlled by, or is under +common control with, You, where "control" means (a) the power, direct +or indirect, to cause the direction or management of such entity, +whether by contract or otherwise, or (b) ownership of fifty percent +(50%) or more of the outstanding shares or beneficial ownership of +such entity. + +2. Permitted Uses; Conditions & Restrictions. Subject to the terms +and conditions of this License, Apple hereby grants You, effective on +the date You accept this License and download the Original Code, a +world-wide, royalty-free, non-exclusive license, to the extent of +Apple's Applicable Patent Rights and copyrights covering the Original +Code, to do the following: + +2.1 Unmodified Code. You may use, reproduce, display, perform, +internally distribute within Your organization, and Externally Deploy +verbatim, unmodified copies of the Original Code, for commercial or +non-commercial purposes, provided that in each instance: + +(a) You must retain and reproduce in all copies of Original Code the +copyright and other proprietary notices and disclaimers of Apple as +they appear in the Original Code, and keep intact all notices in the +Original Code that refer to this License; and + +(b) You must include a copy of this License with every copy of Source +Code of Covered Code and documentation You distribute or Externally +Deploy, and You may not offer or impose any terms on such Source Code +that alter or restrict this License or the recipients' rights +hereunder, except as permitted under Section 6. + +2.2 Modified Code. You may modify Covered Code and use, reproduce, +display, perform, internally distribute within Your organization, and +Externally Deploy Your Modifications and Covered Code, for commercial +or non-commercial purposes, provided that in each instance You also +meet all of these conditions: + +(a) You must satisfy all the conditions of Section 2.1 with respect to +the Source Code of the Covered Code; + +(b) You must duplicate, to the extent it does not already exist, the +notice in Exhibit A in each file of the Source Code of all Your +Modifications, and cause the modified files to carry prominent notices +stating that You changed the files and the date of any change; and + +(c) If You Externally Deploy Your Modifications, You must make +Source Code of all Your Externally Deployed Modifications either +available to those to whom You have Externally Deployed Your +Modifications, or publicly available. Source Code of Your Externally +Deployed Modifications must be released under the terms set forth in +this License, including the license grants set forth in Section 3 +below, for as long as you Externally Deploy the Covered Code or twelve +(12) months from the date of initial External Deployment, whichever is +longer. You should preferably distribute the Source Code of Your +Externally Deployed Modifications electronically (e.g. download from a +web site). + +2.3 Distribution of Executable Versions. In addition, if You +Externally Deploy Covered Code (Original Code and/or Modifications) in +object code, executable form only, You must include a prominent +notice, in the code itself as well as in related documentation, +stating that Source Code of the Covered Code is available under the +terms of this License with information on how and where to obtain such +Source Code. + +2.4 Third Party Rights. You expressly acknowledge and agree that +although Apple and each Contributor grants the licenses to their +respective portions of the Covered Code set forth herein, no +assurances are provided by Apple or any Contributor that the Covered +Code does not infringe the patent or other intellectual property +rights of any other entity. Apple and each Contributor disclaim any +liability to You for claims brought by any other entity based on +infringement of intellectual property rights or otherwise. As a +condition to exercising the rights and licenses granted hereunder, You +hereby assume sole responsibility to secure any other intellectual +property rights needed, if any. For example, if a third party patent +license is required to allow You to distribute the Covered Code, it is +Your responsibility to acquire that license before distributing the +Covered Code. + +3. Your Grants. In consideration of, and as a condition to, the +licenses granted to You under this License, You hereby grant to any +person or entity receiving or distributing Covered Code under this +License a non-exclusive, royalty-free, perpetual, irrevocable license, +under Your Applicable Patent Rights and other intellectual property +rights (other than patent) owned or controlled by You, to use, +reproduce, display, perform, modify, sublicense, distribute and +Externally Deploy Your Modifications of the same scope and extent as +Apple's licenses under Sections 2.1 and 2.2 above. + +4. Larger Works. You may create a Larger Work by combining Covered +Code with other code not governed by the terms of this License and +distribute the Larger Work as a single product. In each such instance, +You must make sure the requirements of this License are fulfilled for +the Covered Code or any portion thereof. + +5. Limitations on Patent License. Except as expressly stated in +Section 2, no other patent rights, express or implied, are granted by +Apple herein. Modifications and/or Larger Works may require additional +patent licenses from Apple which Apple may grant in its sole +discretion. + +6. Additional Terms. You may choose to offer, and to charge a fee for, +warranty, support, indemnity or liability obligations and/or other +rights consistent with the scope of the license granted herein +("Additional Terms") to one or more recipients of Covered Code. +However, You may do so only on Your own behalf and as Your sole +responsibility, and not on behalf of Apple or any Contributor. You +must obtain the recipient's agreement that any such Additional Terms +are offered by You alone, and You hereby agree to indemnify, defend +and hold Apple and every Contributor harmless for any liability +incurred by or claims asserted against Apple or such Contributor by +reason of any such Additional Terms. + +7. Versions of the License. Apple may publish revised and/or new +versions of this License from time to time. Each version will be given +a distinguishing version number. Once Original Code has been published +under a particular version of this License, You may continue to use it +under the terms of that version. You may also choose to use such +Original Code under the terms of any subsequent version of this +License published by Apple. No one other than Apple has the right to +modify the terms applicable to Covered Code created under this +License. + +8. NO WARRANTY OR SUPPORT. The Covered Code may contain in whole or in +part pre-release, untested, or not fully tested works. The Covered +Code may contain errors that could cause failures or loss of data, and +may be incomplete or contain inaccuracies. You expressly acknowledge +and agree that use of the Covered Code, or any portion thereof, is at +Your sole and entire risk. THE COVERED CODE IS PROVIDED "AS IS" AND +WITHOUT WARRANTY, UPGRADES OR SUPPORT OF ANY KIND AND APPLE AND +APPLE'S LICENSOR(S) (COLLECTIVELY REFERRED TO AS "APPLE" FOR THE +PURPOSES OF SECTIONS 8 AND 9) AND ALL CONTRIBUTORS EXPRESSLY DISCLAIM +ALL WARRANTIES AND/OR CONDITIONS, EXPRESS OR IMPLIED, INCLUDING, BUT +NOT LIMITED TO, THE IMPLIED WARRANTIES AND/OR CONDITIONS OF +MERCHANTABILITY, OF SATISFACTORY QUALITY, OF FITNESS FOR A PARTICULAR +PURPOSE, OF ACCURACY, OF QUIET ENJOYMENT, AND NONINFRINGEMENT OF THIRD +PARTY RIGHTS. APPLE AND EACH CONTRIBUTOR DOES NOT WARRANT AGAINST +INTERFERENCE WITH YOUR ENJOYMENT OF THE COVERED CODE, THAT THE +FUNCTIONS CONTAINED IN THE COVERED CODE WILL MEET YOUR REQUIREMENTS, +THAT THE OPERATION OF THE COVERED CODE WILL BE UNINTERRUPTED OR +ERROR-FREE, OR THAT DEFECTS IN THE COVERED CODE WILL BE CORRECTED. NO +ORAL OR WRITTEN INFORMATION OR ADVICE GIVEN BY APPLE, AN APPLE +AUTHORIZED REPRESENTATIVE OR ANY CONTRIBUTOR SHALL CREATE A WARRANTY. +You acknowledge that the Covered Code is not intended for use in the +operation of nuclear facilities, aircraft navigation, communication +systems, or air traffic control machines in which case the failure of +the Covered Code could lead to death, personal injury, or severe +physical or environmental damage. + +9. LIMITATION OF LIABILITY. TO THE EXTENT NOT PROHIBITED BY LAW, IN NO +EVENT SHALL APPLE OR ANY CONTRIBUTOR BE LIABLE FOR ANY INCIDENTAL, +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING +TO THIS LICENSE OR YOUR USE OR INABILITY TO USE THE COVERED CODE, OR +ANY PORTION THEREOF, WHETHER UNDER A THEORY OF CONTRACT, WARRANTY, +TORT (INCLUDING NEGLIGENCE), PRODUCTS LIABILITY OR OTHERWISE, EVEN IF +APPLE OR SUCH CONTRIBUTOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES AND NOTWITHSTANDING THE FAILURE OF ESSENTIAL PURPOSE OF ANY +REMEDY. SOME JURISDICTIONS DO NOT ALLOW THE LIMITATION OF LIABILITY OF +INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS LIMITATION MAY NOT APPLY +TO YOU. In no event shall Apple's total liability to You for all +damages (other than as may be required by applicable law) under this +License exceed the amount of fifty dollars ($50.00). + +10. Trademarks. This License does not grant any rights to use the +trademarks or trade names "Apple", "Apple Computer", "Mac", "Mac OS", +"QuickTime", "QuickTime Streaming Server" or any other trademarks, +service marks, logos or trade names belonging to Apple (collectively +"Apple Marks") or to any trademark, service mark, logo or trade name +belonging to any Contributor. You agree not to use any Apple Marks in +or as part of the name of products derived from the Original Code or +to endorse or promote products derived from the Original Code other +than as expressly permitted by and in strict compliance at all times +with Apple's third party trademark usage guidelines which are posted +at http://www.apple.com/legal/guidelinesfor3rdparties.html. + +11. Ownership. Subject to the licenses granted under this License, +each Contributor retains all rights, title and interest in and to any +Modifications made by such Contributor. Apple retains all rights, +title and interest in and to the Original Code and any Modifications +made by or on behalf of Apple ("Apple Modifications"), and such Apple +Modifications will not be automatically subject to this License. Apple +may, at its sole discretion, choose to license such Apple +Modifications under this License, or on different terms from those +contained in this License or may choose not to license them at all. + +12. Termination. + +12.1 Termination. This License and the rights granted hereunder will +terminate: + +(a) automatically without notice from Apple if You fail to comply with +any term(s) of this License and fail to cure such breach within 30 +days of becoming aware of such breach; + +(b) immediately in the event of the circumstances described in Section +13.5(b); or + +(c) automatically without notice from Apple if You, at any time during +the term of this License, commence an action for patent infringement +against Apple; provided that Apple did not first commence +an action for patent infringement against You in that instance. + +12.2 Effect of Termination. Upon termination, You agree to immediately +stop any further use, reproduction, modification, sublicensing and +distribution of the Covered Code. All sublicenses to the Covered Code +which have been properly granted prior to termination shall survive +any termination of this License. Provisions which, by their nature, +should remain in effect beyond the termination of this License shall +survive, including but not limited to Sections 3, 5, 8, 9, 10, 11, +12.2 and 13. No party will be liable to any other for compensation, +indemnity or damages of any sort solely as a result of terminating +this License in accordance with its terms, and termination of this +License will be without prejudice to any other right or remedy of +any party. + +13. Miscellaneous. + +13.1 Government End Users. The Covered Code is a "commercial item" as +defined in FAR 2.101. Government software and technical data rights in +the Covered Code include only those rights customarily provided to the +public as defined in this License. This customary commercial license +in technical data and software is provided in accordance with FAR +12.211 (Technical Data) and 12.212 (Computer Software) and, for +Department of Defense purchases, DFAR 252.227-7015 (Technical Data -- +Commercial Items) and 227.7202-3 (Rights in Commercial Computer +Software or Computer Software Documentation). Accordingly, all U.S. +Government End Users acquire Covered Code with only those rights set +forth herein. + +13.2 Relationship of Parties. This License will not be construed as +creating an agency, partnership, joint venture or any other form of +legal association between or among You, Apple or any Contributor, and +You will not represent to the contrary, whether expressly, by +implication, appearance or otherwise. + +13.3 Independent Development. Nothing in this License will impair +Apple's right to acquire, license, develop, have others develop for +it, market and/or distribute technology or products that perform the +same or similar functions as, or otherwise compete with, +Modifications, Larger Works, technology or products that You may +develop, produce, market or distribute. + +13.4 Waiver; Construction. Failure by Apple or any Contributor to +enforce any provision of this License will not be deemed a waiver of +future enforcement of that or any other provision. Any law or +regulation which provides that the language of a contract shall be +construed against the drafter will not apply to this License. + +13.5 Severability. (a) If for any reason a court of competent +jurisdiction finds any provision of this License, or portion thereof, +to be unenforceable, that provision of the License will be enforced to +the maximum extent permissible so as to effect the economic benefits +and intent of the parties, and the remainder of this License will +continue in full force and effect. (b) Notwithstanding the foregoing, +if applicable law prohibits or restricts You from fully and/or +specifically complying with Sections 2 and/or 3 or prevents the +enforceability of either of those Sections, this License will +immediately terminate and You must immediately discontinue any use of +the Covered Code and destroy all copies of it that are in your +possession or control. + +13.6 Dispute Resolution. Any litigation or other dispute resolution +between You and Apple relating to this License shall take place in the +Northern District of California, and You and Apple hereby consent to +the personal jurisdiction of, and venue in, the state and federal +courts within that District with respect to this License. The +application of the United Nations Convention on Contracts for the +International Sale of Goods is expressly excluded. + +13.7 Entire Agreement; Governing Law. This License constitutes the +entire agreement between the parties with respect to the subject +matter hereof. This License shall be governed by the laws of the +United States and the State of California, except that body of +California law concerning conflicts of law. + +Where You are located in the province of Quebec, Canada, the following +clause applies: The parties hereby confirm that they have requested +that this License and all related documents be drafted in English. Les +parties ont exige que le present contrat et tous les documents +connexes soient rediges en anglais. + +EXHIBIT A. + +"Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights +Reserved. + +This file contains Original Code and/or Modifications of Original Code +as defined in and that are subject to the Apple Public Source License +Version 2.0 (the 'License'). You may not use this file except in +compliance with the License. Please obtain a copy of the License at +http://www.opensource.apple.com/apsl/ and read it before using this +file. + +The Original Code and all software distributed under the License are +distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER +EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, +INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. +Please see the License for the specific language governing rights and +limitations under the License." diff --git a/doc/BLOBFORMAT b/doc/BLOBFORMAT index 22528f7..6e42669 100644 --- a/doc/BLOBFORMAT +++ b/doc/BLOBFORMAT @@ -61,4 +61,3 @@ Decode (input DSK, DEK, KB output PRIVATE_KEY_BYTES, PUBLIC_KEY_BYTES) 5. Reverse the order of the octects in TEMP3 and call the result TEMP2. 6. Split TEMP2 in IV (first 8 bytes) and TEMP1 (rest). 7. Decrypt TEMP1 using DEK (3DES) and IV in CBC mode with PKCS1 padding. Call the plaintext PRIVATE_KEY_BYTES. - diff --git a/doc/securityd.1 b/doc/securityd.1 index e9ded69..b23cae7 100644 --- a/doc/securityd.1 +++ b/doc/securityd.1 @@ -31,6 +31,6 @@ is mediated through the This command is not intended to be invoked directly. .Sh HISTORY .Nm -was first introduced in Mac OS X version 10.0 (Cheetah) as the "Security Server" and was renamed in 10.4 (Panther). +was first introduced in Mac OS X version 10.0 (Cheetah) as the "Security Server" and was renamed in 10.4 (Tiger). .Sh AUTHORS -.An "Perry Kiehtreiber" +.An "Perry The Cynic" diff --git a/etc/CodeEquivalenceCandidates b/etc/CodeEquivalenceCandidates index 5404062..41674bc 100644 --- a/etc/CodeEquivalenceCandidates +++ b/etc/CodeEquivalenceCandidates @@ -21,6 +21,7 @@ /System/Library/CoreServices/loginwindow.app /System/Library/CoreServices/MirrorAgent.app /System/Library/CoreServices/SecurityAgent.app +/System/Library/CoreServices/SecurityAgent.app/Contents/Resources/authorizationhost /System/Library/CoreServices/SyncServer.app /System/Library/CoreServices/SyncServer.app/Contents/Resources/safaritool /System/Library/CoreServices/SystemUIServer.app @@ -36,11 +37,17 @@ /System/Library/Frameworks/SecurityFoundation.framework/Resources/dotmacfx.app /System/Library/Frameworks/SecurityFoundation.framework/Resources/kcSync.app /System/Library/PreferencePanes/Mac.prefPane -/System/Library/PreferencePanes/Mac.prefPane/Contents/Resources/dotMacPrefTool +/System/Library/PreferencePanes/Mac.prefPane/Contents/Resources/dotMacPrefTool +/System/Library/PreferencePanes/Mac.prefPane/Contents/Versions/A/Resources/dotMacPrefTool +/System/Library/PreferencePanes/Mac.prefPane/Contents/Versions/Current/Resources/dotMacPrefTool /System/Library/PrivateFrameworks/Admin.framework/Resources/writeconfig /System/Library/PrivateFrameworks/Admin.framework/Versions/A/Resources/writeconfig +/System/Library/PrivateFrameworks/Apple80211.framework/Resources/airport /System/Library/PrivateFrameworks/Apple80211.framework/Versions/A/Resources/airport +/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport +/System/Library/PrivateFrameworks/Apple80211.framework/Resources/AirPortNetworkPrefs.bundle/Contents/Resources/AirPortCfgTool /System/Library/PrivateFrameworks/Apple80211.framework/Versions/A/Resources/AirPortNetworkPrefs.bundle/Contents/Resources/AirPortCfgTool +/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/AirPortNetworkPrefs.bundle/Contents/Resources/AirPortCfgTool /System/Library/PrivateFrameworks/DotmacLegacy.framework/Resources/dotMacTranslator /System/Library/PrivateFrameworks/DotmacLegacy.framework/Versions/A/Resources/dotMacTranslator /System/Library/PrivateFrameworks/DotmacLegacy.framework/Versions/Current/Resources/dotMacTranslator diff --git a/etc/authorization.plist b/etc/authorization.plist index 0dc7382..c5d1370 100644 --- a/etc/authorization.plist +++ b/etc/authorization.plist @@ -15,7 +15,7 @@ deny rule: this is always denied user rule: successful authentication as a user in the specified group(5) allows the associated right. -The shared property specifies whether a credential generated on success is shared with other apps (same "session"). This property defaults to false if not specified. +The shared property specifies whether a credential generated on success is shared with other apps (i.e., those in the same "session"). This property defaults to false if not specified. The timeout property specifies the maximum age of a (cached/shared) credential accepted for this rule. @@ -30,7 +30,7 @@ See remaining rules for examples. class rule comment - All other rights will be matched by this rule. + Matches otherwise unmatched rights (i.e., is a default). rule default @@ -39,21 +39,21 @@ See remaining rules for examples. class allow comment - wildcard right for adding rights. Anyone is allowed to add any (non-wildcard) rights + Wildcard right for adding rights. Anyone is allowed to add any (non-wildcard) rights. config.config. class deny comment - wildcard right for any change to meta-rights for db modification. Not allowed programmatically (just edit this file) + Wildcard right for any change to meta-rights for db modification. Not allowed programmatically (just edit this file). config.modify. class rule comment - wildcard right for modifying rights. Admins are allowed to modify any (non-wildcard) rights. Root does not require authentication. + Wildcard right for modifying rights. Admins are allowed to modify any (non-wildcard) rights. Root does not require authentication. k-of-n 1 rule @@ -67,7 +67,7 @@ See remaining rules for examples. class rule comment - wildcard right for deleting rights. Admins are allowed to delete any (non-wildcard) rights. Root does not require authentication. + Wildcard right for deleting rights. Admins are allowed to delete any (non-wildcard) rights. Root does not require authentication. k-of-n 1 rule @@ -81,7 +81,7 @@ See remaining rules for examples. class deny comment - wildcard right for deleting system rights. + Wildcard right for deleting system rights. com.apple. @@ -111,9 +111,7 @@ See remaining rules for examples. class user comment - Used by the dvd player to set the regioncode the first time. Note that changed the region code after it has been set requires a different right (system.device.dvd.setregion.change) -Credentials remain valid indefinitely after they've been obtained. -An acquired credential is shared amongst all clients. + Used by the DVD player to set the region code the first time. Note that changing the region code after it has been set requires a different right (system.device.dvd.setregion.change). group admin shared @@ -124,52 +122,35 @@ An acquired credential is shared amongst all clients. class evaluate-mechanisms comment - Login mechanism based rule. Not for general use, yet. -builtin:krb5authenticate can be used to hinge local authentication on a successful kerberos authentication and kdc verification. -builtin:krb5authnoverify skips the kdc verification. Both fall back on local authentication. + Login mechanism based rule. Not for general use, yet. mechanisms - builtin:auto-login,privileged - loginwindow_builtin:login + builtin:smartcard-sniffer,privileged + loginwindow:login builtin:reset-password,privileged - authinternal - builtin:getuserinfo,privileged - builtin:sso,privileged + builtin:auto-login,privileged + builtin:authenticate,privileged HomeDirMechanism:login,privileged HomeDirMechanism:status MCXMechanism:login - loginwindow_builtin:success - loginwindow_builtin:done + loginwindow:success + loginwindow:done system.login.done class evaluate-mechanisms - comment - builtin:krb5login can be used to do kerberos authentication as a side-effect of logging in. Local username/password will be used. mechanisms - system.login.pam - - class - evaluate-mechanisms - tries - 1 - mechanisms - - push_hints_to_context - authinternal - - system.login.screensaver class rule comment - the owner as well as any admin can unlock the screensaver;modify the group key to change this. + The owner or any administrator can unlock the screensaver. rule authenticate-session-owner-or-admin @@ -192,7 +173,7 @@ builtin:krb5authnoverify skips the kdc verification. Both fall back on local au class evaluate-mechanisms comment - Used by Security framework when you add an item to a unconfigured default keychain + Used by the Security framework when you add an item to an unconfigured default keychain. mechanisms loginKC:queryCreate @@ -224,7 +205,7 @@ builtin:krb5authnoverify skips the kdc verification. Both fall back on local au class user comment - This right is checked by the Admin framework when making changes to the system preferences. + Checked by the Admin framework when making changes to certain System Preferences. group admin shared @@ -237,20 +218,22 @@ builtin:krb5authnoverify skips the kdc verification. Both fall back on local au class user comment - This right is checked by the Admin framework when making changes to the accounts preference pane + Checked by the Admin framework when making changes to the Accounts preference pane. group admin shared - system.printingmanager + system.preferences.parental-controls class - rule + user comment - The following right is checked for printing to locked printers. - rule - authenticate-admin + Checked when making changes to the Parental Controls preference pane. + group + admin + shared + system.preferences.accessibility @@ -259,7 +242,7 @@ builtin:krb5authnoverify skips the kdc verification. Both fall back on local au class user comment - This right is checked by the Admin framework when enabling or disabling the Accessibility APIs + Checked by the Admin framework when enabling or disabling the Accessibility APIs. group admin shared @@ -267,12 +250,93 @@ builtin:krb5authnoverify skips the kdc verification. Both fall back on local au timeout 0 + system.printingmanager + + class + rule + comment + For printing to locked printers. + rule + authenticate-admin + + system.print.admin + + class + rule + k-of-n + 1 + rule + + is-lpadmin + is-admin + default + + + system.identity.write. + + class + rule + comment + For creating, changing or deleting local user accounts and groups. + k-of-n + 1 + rule + + is-admin + authenticate-admin + + + system.identity.write.credential + + class + rule + comment + Checked when changing authentication credentials (password or certificate) for a local user account. + rule + default + + system.identity.write.self + + class + user + comment + Checked when changing authentication credentials (password or certificate) for the current user's account. + authenticate-user + + session-owner + + + system.global-login-items. + + class + rule + k-of-n + 1 + rule + + is-admin + default + + + system.sharepoints. + + allow-root + + class + user + comment + Checked when making changes to the Sharepoints. + group + admin + shared + + com.apple.activitymonitor.kill class user comment - Used by Activity Monitor to authorize killing processes not owned by the user + Used by Activity Monitor to authorize killing processes not owned by the user. group admin shared @@ -287,7 +351,7 @@ builtin:krb5authnoverify skips the kdc verification. Both fall back on local au class user comment - This right is checked when changing parental controls for Safari + Checked when changing parental controls for Safari. group admin shared @@ -295,6 +359,17 @@ builtin:krb5authnoverify skips the kdc verification. Both fall back on local au timeout 0 + com.apple.docset.install + + class + user + comment + Used by Xcode to restrict access to a daemon it uses to install and update documentation sets. + group + admin + shared + + system.privilege.admin allow-root @@ -302,13 +377,9 @@ builtin:krb5authnoverify skips the kdc verification. Both fall back on local au class user comment - Used by AuthorizationExecuteWithPrivileges(...) - AuthorizationExecuteWithPrivileges is used by programs requesting - to run a tool as root (ie. some installers). - Credentials remain valid 5 minutes after they've been obtained. - An acquired credential isn't shared with other clients. - Clients running as root will be granted this right automatically. - + Used by AuthorizationExecuteWithPrivileges(...). + AuthorizationExecuteWithPrivileges() is used by programs requesting + to run a tool as root (e.g., some installers). group admin shared @@ -316,12 +387,29 @@ builtin:krb5authnoverify skips the kdc verification. Both fall back on local au timeout 300 + system.privilege.taskport + + allow-root + + class + user + comment + Used by task_for_pid(...). + Task_for_pid is called by programs requesting full control over another program + for things like debugging or performance analysis. This authorization only applies + if the requesting and target programs are run by the same user; it will never + authorize access to the program of another user. + group + admin + shared + + system.restart class evaluate-mechanisms comment - Multisession restart mechanisms + Checked if the foreground console user tries to restart the system while other users are logged in via fast-user switching. mechanisms RestartAuthorization:restart @@ -334,7 +422,7 @@ builtin:krb5authnoverify skips the kdc verification. Both fall back on local au class evaluate-mechanisms comment - Multisession shutdown mechanisms + Checked if the foreground console user tries to shut down the system while other users are logged in via fast-user switching. mechanisms RestartAuthorization:shutdown @@ -347,7 +435,7 @@ builtin:krb5authnoverify skips the kdc verification. Both fall back on local au class allow comment - authorization to burn media + For burning media. system.services.directory.configure @@ -362,14 +450,14 @@ builtin:krb5authnoverify skips the kdc verification. Both fall back on local au timeout 300 comment - authorization to make directory service changes + For making Directory Services changes. com.apple.server.admin.streaming class user comment - Used for admin requests with the QuickTime Streaming Server. + For making administrative requests to the QuickTime Streaming Server. group admin shared @@ -379,12 +467,30 @@ builtin:krb5authnoverify skips the kdc verification. Both fall back on local au timeout 0 + com.apple.trust-settings.admin + + comment + For modifying Trust Settings in the Local Admin domain. + allow-root + + class + user + group + admin + + com.apple.trust-settings.user + + rule + authenticate-session-owner + comment + For modifying per-user Trust Settings. + system.install.admin.user class user comment - Used by installer tool: user installling in admin domain (/Applications) + Checked when user is installing in admin domain (/Applications). group admin shared @@ -397,7 +503,7 @@ builtin:krb5authnoverify skips the kdc verification. Both fall back on local au class user comment - Used by installer tool: user installling in root domain (/System) + Checked when user is installing in root domain (/System). group admin shared @@ -410,7 +516,7 @@ builtin:krb5authnoverify skips the kdc verification. Both fall back on local au class user comment - Used by installer tool: admin installling in root domain (/System) + Checked when admin is installing in root domain (/System). group admin shared @@ -423,7 +529,7 @@ builtin:krb5authnoverify skips the kdc verification. Both fall back on local au class rule comment - Used to determine administrative access to the Application Server management tool. + For administrative access to the Application Server management tool. rule appserver-admin @@ -432,7 +538,7 @@ builtin:krb5authnoverify skips the kdc verification. Both fall back on local au class rule comment - Used to determine user access to the Application Server management tool. + For user access to the Application Server management tool. k-of-n 1 rule @@ -441,12 +547,23 @@ builtin:krb5authnoverify skips the kdc verification. Both fall back on local au appserver-user + com.apple.dashboard.advisory.allow + + class + user + group + admin + shared + + timeout + 300 + com.apple.desktopservices class user comment - authorize privileged file operations from the finder + For privileged file operations from within the Finder. group admin shared @@ -476,6 +593,8 @@ builtin:krb5authnoverify skips the kdc verification. Both fall back on local au class evaluate-mechanisms + tries + 1 mechanisms builtin:confirm-access @@ -498,14 +617,14 @@ builtin:krb5authnoverify skips the kdc verification. Both fall back on local au class allow comment - allow anyone + Allow anyone. authenticate-admin class user comment - require the user asking for authorization to authenticate as an admin + Authenticate as an administrator. group admin shared @@ -513,21 +632,12 @@ builtin:krb5authnoverify skips the kdc verification. Both fall back on local au timeout 0 - authenticate-session-user - - class - user - comment - authenticate session owner - session-owner - - authenticate-session-owner class user comment - authenticate session owner + Authenticate as the session owner. session-owner @@ -538,7 +648,7 @@ builtin:krb5authnoverify skips the kdc verification. Both fall back on local au class user comment - the owner as well as any admin can authorize + Authenticate either as the owner or as an administrator. group admin session-owner @@ -551,7 +661,7 @@ builtin:krb5authnoverify skips the kdc verification. Both fall back on local au class user comment - verify the user asking for authorization is an admin + Verify that the user asking for authorization is an administrator. group admin authenticate-user @@ -559,6 +669,17 @@ builtin:krb5authnoverify skips the kdc verification. Both fall back on local au shared true + is-lpadmin + + class + user + comment + Verify that the user asking for authorization is an lp administrator. + group + lpadmin + authenticate-user + + is-root allow-root @@ -568,7 +689,7 @@ builtin:krb5authnoverify skips the kdc verification. Both fall back on local au authenticate-user comment - verify the process that created this authref is root + Verify that the process that created this AuthorizationRef is running as root. appserver-user @@ -589,8 +710,9 @@ builtin:krb5authnoverify skips the kdc verification. Both fall back on local au class user comment - All other rights will be matched by this rule. Credentials remain valid 5 minutes after they've been obtained. -An acquired credential is shared amongst all clients. + Default rule. + Credentials remain valid for 5 minutes after they've been obtained. + An acquired credential is shared by all clients. group admin @@ -605,8 +727,9 @@ An acquired credential is shared amongst all clients. evaluate-mechanisms mechanisms + builtin:smartcard-sniffer,privileged builtin:authenticate - authinternal + builtin:authenticate,privileged diff --git a/etc/com.apple.securityd.plist b/etc/com.apple.securityd.plist new file mode 100644 index 0000000..d9f2292 --- /dev/null +++ b/etc/com.apple.securityd.plist @@ -0,0 +1,25 @@ + + + + + Label + com.apple.SecurityServer + ProgramArguments + + /usr/sbin/securityd + -i + + MachServices + + com.apple.SecurityServer + + ResetAtClose + + + + RunAtLoad + + LaunchOnlyOnce + + + diff --git a/etc/securityd-installCD.plist b/etc/securityd-installCD.plist deleted file mode 100644 index ce87d8d..0000000 --- a/etc/securityd-installCD.plist +++ /dev/null @@ -1,12 +0,0 @@ - - - - - ServiceName - com.apple.securityd - Command - /usr/sbin/securityd -c /var/tmp/tokencache -s off - OnDemand - - - diff --git a/etc/securityd.plist b/etc/securityd.plist deleted file mode 100644 index 82d83c3..0000000 --- a/etc/securityd.plist +++ /dev/null @@ -1,12 +0,0 @@ - - - - - ServiceName - com.apple.securityd - Command - /usr/sbin/securityd - OnDemand - - - diff --git a/etc/startup.mk b/etc/startup.mk index f3912c3..04c77e0 100644 --- a/etc/startup.mk +++ b/etc/startup.mk @@ -8,12 +8,12 @@ SYSTEM_LIBRARY_DIR=$(DSTROOT)/System/Library SYSTEM_CORE_SERVICES_DIR=/System/Library/CoreServices ETC_DIR=$(DSTROOT)/private/etc +LAUNCH_DIR=$(DSTROOT)/System/Library/LaunchDaemons AUTHORIZATION_LOCATION=$(ETC_DIR) AUTHORIZATION_PLIST=$(AUTHORIZATION_LOCATION)/authorization VARDB=$(DSTROOT)/private/var/db CANDIDATES=$(VARDB)/CodeEquivalenceCandidates -DST=$(ETC_DIR)/mach_init.d SRC=$(SRCROOT)/etc @@ -33,8 +33,8 @@ profile: # Install # install: - mkdir -p $(DST) - cp $(SRC)/securityd.plist $(SRC)/securityd-installCD.plist $(DST) + mkdir -p $(LAUNCH_DIR) + cp $(SRC)/com.apple.securityd.plist $(LAUNCH_DIR) mkdir -p $(AUTHORIZATION_LOCATION) cp $(SRC)/authorization.plist $(AUTHORIZATION_PLIST) chown root:wheel $(AUTHORIZATION_PLIST) diff --git a/securityd.xcode/project.pbxproj b/securityd.xcode/project.pbxproj deleted file mode 100644 index 52f503b..0000000 --- a/securityd.xcode/project.pbxproj +++ /dev/null @@ -1,1942 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 39; - objects = { - 405845650663B2010083E58C = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.cpp; - path = AuthorizationMechEval.cpp; - refType = 4; - sourceTree = ""; - }; - 405845660663B2010083E58C = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - path = AuthorizationMechEval.h; - refType = 4; - sourceTree = ""; - }; - 405845670663B2010083E58C = { - fileRef = 405845650663B2010083E58C; - isa = PBXBuildFile; - settings = { - }; - }; - 405845680663B2010083E58C = { - fileRef = 405845660663B2010083E58C; - isa = PBXBuildFile; - settings = { - }; - }; - 40689F840725DCE00021A502 = { - fileEncoding = 4; - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - path = authhost.h; - refType = 4; - sourceTree = ""; - }; - 40689F850725DCE00021A502 = { - fileEncoding = 4; - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.cpp; - path = authhost.cpp; - refType = 4; - sourceTree = ""; - }; - 40689F860725DCE00021A502 = { - fileRef = 40689F840725DCE00021A502; - isa = PBXBuildFile; - settings = { - }; - }; - 40689F870725DCE00021A502 = { - fileRef = 40689F850725DCE00021A502; - isa = PBXBuildFile; - settings = { - }; - }; -//400 -//401 -//402 -//403 -//404 -//4C0 -//4C1 -//4C2 -//4C3 -//4C4 - 4C01B3D706FFC621004B3A01 = { - buildActionMask = 8; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - 4C01B3DA06FFC640004B3A01, - ); - isa = PBXCopyFilesBuildPhase; - runOnlyForDeploymentPostprocessing = 1; - }; - 4C01B3DA06FFC640004B3A01 = { - fileRef = 4CE1878706FFC5D60079D235; - isa = PBXBuildFile; - settings = { - }; - }; - 4C9264970534866F004B0E72 = { - children = ( - 4C9264B70534866F004B0E72, - C28AE81406CD7DA100BE0061, - C2C8B29806F8A60F000EBDA2, - C28AE81706CD7DC500BE0061, - C28AE81A06CD7DE200BE0061, - C28AE82306CD7E0F00BE0061, - C28AE82606CD7E4700BE0061, - C28AE81106CD7D7800BE0061, - C28AE83906CD7EE900BE0061, - ); - isa = PBXGroup; - path = src; - refType = 4; - sourceTree = ""; - }; - 4C9264980534866F004B0E72 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.cpp; - path = acl_keychain.cpp; - refType = 4; - sourceTree = ""; - }; - 4C9264990534866F004B0E72 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - path = acl_keychain.h; - refType = 4; - sourceTree = ""; - }; - 4C92649A0534866F004B0E72 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.cpp; - path = acls.cpp; - refType = 4; - sourceTree = ""; - }; - 4C92649B0534866F004B0E72 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - path = acls.h; - refType = 4; - sourceTree = ""; - }; - 4C92649C0534866F004B0E72 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.cpp; - path = agentquery.cpp; - refType = 4; - sourceTree = ""; - }; - 4C92649D0534866F004B0E72 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - path = agentquery.h; - refType = 4; - sourceTree = ""; - }; - 4C92649E0534866F004B0E72 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.cpp; - path = authority.cpp; - refType = 4; - sourceTree = ""; - }; - 4C92649F0534866F004B0E72 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - path = authority.h; - refType = 4; - sourceTree = ""; - }; - 4C9264A00534866F004B0E72 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.cpp; - path = AuthorizationDBPlist.cpp; - refType = 4; - sourceTree = ""; - }; - 4C9264A10534866F004B0E72 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - path = AuthorizationDBPlist.h; - refType = 4; - sourceTree = ""; - }; - 4C9264A20534866F004B0E72 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.cpp; - path = AuthorizationEngine.cpp; - refType = 4; - sourceTree = ""; - }; - 4C9264A30534866F004B0E72 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - path = AuthorizationEngine.h; - refType = 4; - sourceTree = ""; - }; - 4C9264A40534866F004B0E72 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.cpp; - path = AuthorizationRule.cpp; - refType = 4; - sourceTree = ""; - }; - 4C9264A50534866F004B0E72 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - path = AuthorizationRule.h; - refType = 4; - sourceTree = ""; - }; - 4C9264A80534866F004B0E72 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.cpp; - path = codesigdb.cpp; - refType = 4; - sourceTree = ""; - }; - 4C9264A90534866F004B0E72 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - path = codesigdb.h; - refType = 4; - sourceTree = ""; - }; - 4C9264AA0534866F004B0E72 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.cpp; - path = connection.cpp; - refType = 4; - sourceTree = ""; - }; - 4C9264AB0534866F004B0E72 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - path = connection.h; - refType = 4; - sourceTree = ""; - }; - 4C9264AC0534866F004B0E72 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.cpp; - path = dbcrypto.cpp; - refType = 4; - sourceTree = ""; - }; - 4C9264AD0534866F004B0E72 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - path = dbcrypto.h; - refType = 4; - sourceTree = ""; - }; - 4C9264AE0534866F004B0E72 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.cpp; - path = entropy.cpp; - refType = 4; - sourceTree = ""; - }; - 4C9264AF0534866F004B0E72 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - path = entropy.h; - refType = 4; - sourceTree = ""; - }; - 4C9264B00534866F004B0E72 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.cpp; - path = flippers.cpp; - refType = 4; - sourceTree = ""; - }; - 4C9264B10534866F004B0E72 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - path = flippers.h; - refType = 4; - sourceTree = ""; - }; - 4C9264B20534866F004B0E72 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = text; - path = generate.cf; - refType = 4; - sourceTree = ""; - }; - 4C9264B30534866F004B0E72 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = text; - path = generate.mk; - refType = 4; - sourceTree = ""; - }; - 4C9264B40534866F004B0E72 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = text.script.perl; - path = generate.pl; - refType = 4; - sourceTree = ""; - }; - 4C9264B50534866F004B0E72 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.cpp; - path = key.cpp; - refType = 4; - sourceTree = ""; - }; - 4C9264B60534866F004B0E72 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - path = key.h; - refType = 4; - sourceTree = ""; - }; - 4C9264B70534866F004B0E72 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.cpp; - path = main.cpp; - refType = 4; - sourceTree = ""; - }; - 4C9264B80534866F004B0E72 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.cpp; - path = notifications.cpp; - refType = 4; - sourceTree = ""; - }; - 4C9264B90534866F004B0E72 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - path = notifications.h; - refType = 4; - sourceTree = ""; - }; - 4C9264BA0534866F004B0E72 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.cpp; - path = process.cpp; - refType = 4; - sourceTree = ""; - }; - 4C9264BB0534866F004B0E72 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - path = process.h; - refType = 4; - sourceTree = ""; - }; - 4C9264BC0534866F004B0E72 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = text; - path = securityd.order; - refType = 4; - sourceTree = ""; - }; - 4C9264BE0534866F004B0E72 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.cpp; - path = server.cpp; - refType = 4; - sourceTree = ""; - }; - 4C9264BF0534866F004B0E72 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - path = server.h; - refType = 4; - sourceTree = ""; - }; - 4C9264C00534866F004B0E72 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.cpp; - path = session.cpp; - refType = 4; - sourceTree = ""; - }; - 4C9264C10534866F004B0E72 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - path = session.h; - refType = 4; - sourceTree = ""; - }; - 4C9264C20534866F004B0E72 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.cpp; - path = transition.cpp; - refType = 4; - sourceTree = ""; - }; - 4C9264C30534866F004B0E72 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.cpp; - path = transwalkers.cpp; - refType = 4; - sourceTree = ""; - }; - 4C9264C40534866F004B0E72 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - path = transwalkers.h; - refType = 4; - sourceTree = ""; - }; - 4C9264C80534866F004B0E72 = { - fileRef = 4C9264980534866F004B0E72; - isa = PBXBuildFile; - settings = { - }; - }; - 4C9264C90534866F004B0E72 = { - fileRef = 4C9264990534866F004B0E72; - isa = PBXBuildFile; - settings = { - }; - }; - 4C9264CA0534866F004B0E72 = { - fileRef = 4C92649A0534866F004B0E72; - isa = PBXBuildFile; - settings = { - }; - }; - 4C9264CB0534866F004B0E72 = { - fileRef = 4C92649B0534866F004B0E72; - isa = PBXBuildFile; - settings = { - }; - }; - 4C9264CC0534866F004B0E72 = { - fileRef = 4C92649C0534866F004B0E72; - isa = PBXBuildFile; - settings = { - }; - }; - 4C9264CD0534866F004B0E72 = { - fileRef = 4C92649D0534866F004B0E72; - isa = PBXBuildFile; - settings = { - }; - }; - 4C9264CE0534866F004B0E72 = { - fileRef = 4C92649E0534866F004B0E72; - isa = PBXBuildFile; - settings = { - }; - }; - 4C9264CF0534866F004B0E72 = { - fileRef = 4C92649F0534866F004B0E72; - isa = PBXBuildFile; - settings = { - }; - }; - 4C9264D00534866F004B0E72 = { - fileRef = 4C9264A00534866F004B0E72; - isa = PBXBuildFile; - settings = { - }; - }; - 4C9264D10534866F004B0E72 = { - fileRef = 4C9264A10534866F004B0E72; - isa = PBXBuildFile; - settings = { - }; - }; - 4C9264D20534866F004B0E72 = { - fileRef = 4C9264A20534866F004B0E72; - isa = PBXBuildFile; - settings = { - }; - }; - 4C9264D30534866F004B0E72 = { - fileRef = 4C9264A30534866F004B0E72; - isa = PBXBuildFile; - settings = { - }; - }; - 4C9264D40534866F004B0E72 = { - fileRef = 4C9264A40534866F004B0E72; - isa = PBXBuildFile; - settings = { - }; - }; - 4C9264D50534866F004B0E72 = { - fileRef = 4C9264A50534866F004B0E72; - isa = PBXBuildFile; - settings = { - }; - }; - 4C9264D80534866F004B0E72 = { - fileRef = 4C9264A80534866F004B0E72; - isa = PBXBuildFile; - settings = { - }; - }; - 4C9264D90534866F004B0E72 = { - fileRef = 4C9264A90534866F004B0E72; - isa = PBXBuildFile; - settings = { - }; - }; - 4C9264DA0534866F004B0E72 = { - fileRef = 4C9264AA0534866F004B0E72; - isa = PBXBuildFile; - settings = { - }; - }; - 4C9264DB0534866F004B0E72 = { - fileRef = 4C9264AB0534866F004B0E72; - isa = PBXBuildFile; - settings = { - }; - }; - 4C9264DC0534866F004B0E72 = { - fileRef = 4C9264AC0534866F004B0E72; - isa = PBXBuildFile; - settings = { - }; - }; - 4C9264DD0534866F004B0E72 = { - fileRef = 4C9264AD0534866F004B0E72; - isa = PBXBuildFile; - settings = { - }; - }; - 4C9264DE0534866F004B0E72 = { - fileRef = 4C9264AE0534866F004B0E72; - isa = PBXBuildFile; - settings = { - }; - }; - 4C9264DF0534866F004B0E72 = { - fileRef = 4C9264AF0534866F004B0E72; - isa = PBXBuildFile; - settings = { - }; - }; - 4C9264E00534866F004B0E72 = { - fileRef = 4C9264B00534866F004B0E72; - isa = PBXBuildFile; - settings = { - }; - }; - 4C9264E10534866F004B0E72 = { - fileRef = 4C9264B10534866F004B0E72; - isa = PBXBuildFile; - settings = { - }; - }; - 4C9264E20534866F004B0E72 = { - fileRef = 4C9264B50534866F004B0E72; - isa = PBXBuildFile; - settings = { - }; - }; - 4C9264E30534866F004B0E72 = { - fileRef = 4C9264B60534866F004B0E72; - isa = PBXBuildFile; - settings = { - }; - }; - 4C9264E40534866F004B0E72 = { - fileRef = 4C9264B70534866F004B0E72; - isa = PBXBuildFile; - settings = { - }; - }; - 4C9264E50534866F004B0E72 = { - fileRef = 4C9264B80534866F004B0E72; - isa = PBXBuildFile; - settings = { - }; - }; - 4C9264E60534866F004B0E72 = { - fileRef = 4C9264B90534866F004B0E72; - isa = PBXBuildFile; - settings = { - }; - }; - 4C9264E70534866F004B0E72 = { - fileRef = 4C9264BA0534866F004B0E72; - isa = PBXBuildFile; - settings = { - }; - }; - 4C9264E80534866F004B0E72 = { - fileRef = 4C9264BB0534866F004B0E72; - isa = PBXBuildFile; - settings = { - }; - }; - 4C9264EA0534866F004B0E72 = { - fileRef = 4C9264BE0534866F004B0E72; - isa = PBXBuildFile; - settings = { - }; - }; - 4C9264EB0534866F004B0E72 = { - fileRef = 4C9264BF0534866F004B0E72; - isa = PBXBuildFile; - settings = { - }; - }; - 4C9264EC0534866F004B0E72 = { - fileRef = 4C9264C00534866F004B0E72; - isa = PBXBuildFile; - settings = { - }; - }; - 4C9264ED0534866F004B0E72 = { - fileRef = 4C9264C10534866F004B0E72; - isa = PBXBuildFile; - settings = { - }; - }; - 4C9264EE0534866F004B0E72 = { - fileRef = 4C9264C20534866F004B0E72; - isa = PBXBuildFile; - settings = { - }; - }; - 4C9264EF0534866F004B0E72 = { - fileRef = 4C9264C30534866F004B0E72; - isa = PBXBuildFile; - settings = { - }; - }; - 4C9264F00534866F004B0E72 = { - fileRef = 4C9264C40534866F004B0E72; - isa = PBXBuildFile; - settings = { - }; - }; - 4CA1FEAC052A3C5800F22E42 = { - children = ( - 4C9264970534866F004B0E72, - C209B39106ADBB19007B9E6D, - 4CE1878506FFC5D60079D235, - C209B39406ADBB2B007B9E6D, - C28AE82006CD7DF500BE0061, - 4CDD50150537658500FEC36D, - 4CA1FEB7052A3C6D00F22E42, - 4CD8CCBB055884E0006B3584, - ); - isa = PBXGroup; - refType = 4; - sourceTree = ""; - }; - 4CA1FEAE052A3C5800F22E42 = { - buildSettings = { - BUILD_VARIANTS = debug; - COPY_PHASE_STRIP = NO; - GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_FIX_AND_CONTINUE = YES; - GCC_GENERATE_DEBUGGING_SYMBOLS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - ZERO_LINK = YES; - }; - isa = PBXBuildStyle; - name = Development; - }; - 4CA1FEAF052A3C5800F22E42 = { - buildSettings = { - DEAD_CODE_STRIPPING = YES; - GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_FIX_AND_CONTINUE = YES; - GCC_GENERATE_DEBUGGING_SYMBOLS = NO; - ZERO_LINK = NO; - }; - isa = PBXBuildStyle; - name = Deployment; - }; - 4CA1FEB0052A3C5800F22E42 = { - buildSettings = { - }; - buildStyles = ( - 4CA1FEAE052A3C5800F22E42, - 4CA1FEAF052A3C5800F22E42, - C265A4DB06F12750000E5CFC, - ); - hasScannedForEncodings = 1; - isa = PBXProject; - mainGroup = 4CA1FEAC052A3C5800F22E42; - productRefGroup = 4CA1FEB7052A3C6D00F22E42; - projectDirPath = ""; - targets = ( - 4CA1FEB5052A3C6D00F22E42, - 4CDD4F7A053751FF00FEC36D, - 4CA4EB2C0558848900CF7791, - C209B3A506ADBCAC007B9E6D, - ); - }; - 4CA1FEB1052A3C6D00F22E42 = { - buildActionMask = 2147483647; - files = ( - 4C9264C90534866F004B0E72, - 4C9264CB0534866F004B0E72, - 4C9264CD0534866F004B0E72, - 4C9264CF0534866F004B0E72, - 4C9264D10534866F004B0E72, - 4C9264D30534866F004B0E72, - 405845680663B2010083E58C, - 4C9264D50534866F004B0E72, - 4CB5ACBC06680AE000F359A9, - 4C9264D90534866F004B0E72, - 4C9264DB0534866F004B0E72, - C2B8DBCC05E6C3CE00E6E67C, - 4C9264DD0534866F004B0E72, - 4C9264DF0534866F004B0E72, - 4C9264E10534866F004B0E72, - C2B8DBCE05E6C3CE00E6E67C, - C207646605EAD713004FEEDA, - 4C9264E30534866F004B0E72, - C20764E905ED250F004FEEDA, - C20764EB05ED250F004FEEDA, - 4C9264E60534866F004B0E72, - C2FDCAC60663CD5B0013F64C, - 4C9264E80534866F004B0E72, - C2FDCAC80663CD5B0013F64C, - 4C9264EB0534866F004B0E72, - 4C9264ED0534866F004B0E72, - C28ACF9D05C9940B00447176, - C20AF37F05F689540055732C, - C2FDCACA0663CD5B0013F64C, - C2D425F405F3C07400CB11F8, - 4C9264F00534866F004B0E72, - C26EA9540688CF34007CE21D, - C209B3B506ADBE64007B9E6D, - C22A7F8F06AF06D9006087B7, - C26D533A06C1E70A00062E1E, - C28654B306DBC2A30021E6E5, - C2813C820730534A00E243E8, - 40689F860725DCE00021A502, - ); - isa = PBXHeadersBuildPhase; - runOnlyForDeploymentPostprocessing = 0; - }; - 4CA1FEB2052A3C6D00F22E42 = { - buildActionMask = 2147483647; - files = ( - 4C9264C80534866F004B0E72, - 4C9264CA0534866F004B0E72, - 4C9264CC0534866F004B0E72, - 4C9264CE0534866F004B0E72, - 4C9264D00534866F004B0E72, - 4C9264D20534866F004B0E72, - 405845670663B2010083E58C, - 4C9264D40534866F004B0E72, - 4CB5ACBB06680AE000F359A9, - 4C9264D80534866F004B0E72, - 4C9264DA0534866F004B0E72, - C2B8DBCB05E6C3CE00E6E67C, - 4C9264DC0534866F004B0E72, - 4C9264DE0534866F004B0E72, - 4C9264E00534866F004B0E72, - C2B8DBCD05E6C3CE00E6E67C, - C207646505EAD713004FEEDA, - 4C9264E20534866F004B0E72, - C20764E805ED250F004FEEDA, - C20764EA05ED250F004FEEDA, - 4C9264E40534866F004B0E72, - 4C9264E50534866F004B0E72, - C2FDCAC50663CD5B0013F64C, - 4C9264E70534866F004B0E72, - C2FDCAC70663CD5B0013F64C, - 4C9264EA0534866F004B0E72, - 4C9264EC0534866F004B0E72, - C28ACF9C05C9940B00447176, - C20AF37E05F689540055732C, - C2FDCAC90663CD5B0013F64C, - C2D425F305F3C07400CB11F8, - 4C9264EE0534866F004B0E72, - 4C9264EF0534866F004B0E72, - C26EA9530688CF34007CE21D, - C209B3B606ADBE64007B9E6D, - C209B3B706ADBE64007B9E6D, - C22A7F8E06AF06D9006087B7, - C26D533906C1E70A00062E1E, - C28654B206DBC2A30021E6E5, - C2813C810730534A00E243E8, - 40689F870725DCE00021A502, - ); - isa = PBXSourcesBuildPhase; - runOnlyForDeploymentPostprocessing = 0; - }; - 4CA1FEB3052A3C6D00F22E42 = { - buildActionMask = 2147483647; - files = ( - ); - isa = PBXFrameworksBuildPhase; - runOnlyForDeploymentPostprocessing = 0; - }; - 4CA1FEB5052A3C6D00F22E42 = { - buildPhases = ( - 4CA1FEB1052A3C6D00F22E42, - 4CA1FEB2052A3C6D00F22E42, - 4CA1FEB3052A3C6D00F22E42, - 4C01B3D706FFC621004B3A01, - ); - buildSettings = { - BUILD_VARIANTS = "normal debug"; - CURRENT_PROJECT_VERSION = 1; - FRAMEWORK_SEARCH_PATHS = "/usr/local/SecurityPieces/Frameworks /usr/local/SecurityPieces/Components/securityd $(SYSTEM_LIBRARY_DIR)/PrivateFrameworks"; - INSTALL_PATH = /usr/sbin; - OPT_CPPXFLAGS = "$(OPT_CXFLAGS)"; - OPT_CXFLAGS = "-DNDEBUG $(OPT_INLINEXFLAGS)"; - OPT_INLINEXFLAGS = "-finline-functions"; - OPT_LDXFLAGS = "-dead_strip"; - OPT_LDXNOPIC = ",_nopic"; - OTHER_ASFLAGS_debug = "$(OTHER_CFLAGS)"; - OTHER_ASFLAGS_normal = "-DNDEBUG $(OTHER_CFLAGS)"; - OTHER_ASFLAGS_profile = "-DNDEBUG $(OTHER_CFLAGS) -pg"; - OTHER_CFLAGS_debug = "$(OTHER_CFLAGS) -O1 -fno-inline"; - OTHER_CFLAGS_normal = "$(OPT_CXFLAGS) $(OTHER_CFLAGS)"; - OTHER_CFLAGS_profile = "$(OPT_CXFLAGS) $(OTHER_CFLAGS) -pg"; - OTHER_CPLUSPLUSFLAGS_debug = "$(OTHER_CPLUSPLUSFLAGS) -O1 -fno-inline"; - OTHER_CPLUSPLUSFLAGS_normal = "$(OPT_CPPXFLAGS) $(OTHER_CPLUSPLUSFLAGS)"; - OTHER_CPLUSPLUSFLAGS_profile = "$(OPT_CPPXFLAGS) $(OTHER_CPLUSPLUSFLAGS) -pg"; - OTHER_LDFLAGS = "-lbsm"; - OTHER_LDFLAGS_debug = "$(OTHER_LDFLAGS) \"-framework\" \"Security,_debug\" \"-framework\" \"PCSC,_debug\" \"-framework\" \"IOKit\" \"-framework\" \"CoreFoundation\" \"-framework\" \"security_agent_client,_debug\" \"-framework\" \"security_tokend_client,_debug\" \"-framework\" \"security_cdsa_client,_debug\" \"-framework\" \"securityd_server,_debug\" \"-framework\" \"securityd_client,_debug\" \"-framework\" \"security_cdsa_utilities,_debug\" \"-framework\" \"security_utilities,_debug\""; - OTHER_LDFLAGS_normal = "$(OPT_LDXFLAGS) $(OTHER_LDFLAGS) \"-framework\" \"Security\" \"-framework\" \"PCSC\" \"-framework\" \"IOKit\" \"-framework\" \"CoreFoundation\" \"-framework\" \"security_agent_client$(OPT_LDXNOPIC)\" \"-framework\" \"security_tokend_client$(OPT_LDXNOPIC)\" \"-framework\" \"security_cdsa_client$(OPT_LDXNOPIC)\" \"-framework\" \"securityd_server$(OPT_LDXNOPIC)\" \"-framework\" \"securityd_client$(OPT_LDXNOPIC)\" \"-framework\" \"security_cdsa_utilities$(OPT_LDXNOPIC)\" \"-framework\" \"security_utilities$(OPT_LDXNOPIC)\""; - OTHER_LDFLAGS_profile = "$(OPT_LDXFLAGS) $(OTHER_LDFLAGS) -pg \"-framework\" \"Security,_profile\" \"-framework\" \"PCSC,_profile\" \"-framework\" \"IOKit\" \"-framework\" \"CoreFoundation\" \"-framework\" \"security_agent_client,_profile\" \"-framework\" \"security_tokend_client,_profile\" \"-framework\" \"security_cdsa_client,_profile\" \"-framework\" \"securityd_server,_profile\" \"-framework\" \"securityd_client,_profile\" \"-framework\" \"security_cdsa_utilities,_profile\" \"-framework\" \"security_utilities,_profile\""; - PRODUCT_NAME = securityd; - SECTORDER_FLAGS = "-sectorder __TEXT __text src/securityd.order -e start"; - VERSIONING_SYSTEM = "apple-generic"; - WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas"; - }; - dependencies = ( - C209B3AA06ADBD6D007B9E6D, - 4CDD4FB80537552600FEC36D, - 4CD8CCB6055884BD006B3584, - ); - isa = PBXToolTarget; - name = securityd; - productInstallPath = /usr/sbin; - productName = securityd; - productReference = 4CA1FEB6052A3C6D00F22E42; - }; - 4CA1FEB6052A3C6D00F22E42 = { - explicitFileType = "compiled.mach-o.executable"; - isa = PBXFileReference; - path = securityd; - refType = 3; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 4CA1FEB7052A3C6D00F22E42 = { - children = ( - 4CA1FEB6052A3C6D00F22E42, - C2904F9606D116A3005FF97E, - ); - isa = PBXGroup; - name = Products; - refType = 4; - sourceTree = ""; - }; - 4CA4EB2C0558848900CF7791 = { - buildArgumentsString = "-f $(SRCROOT)/etc/startup.mk $(ACTION)"; - buildPhases = ( - ); - buildSettings = { - OTHER_CFLAGS = ""; - OTHER_LDFLAGS = ""; - OTHER_REZFLAGS = ""; - PRODUCT_NAME = startup; - SECTORDER_FLAGS = ""; - WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas"; - }; - buildToolPath = /usr/bin/gnumake; - buildWorkingDirectory = ""; - dependencies = ( - ); - isa = PBXLegacyTarget; - name = startup; - passBuildSettingsInEnvironment = 1; - productName = startup; - }; - 4CB5ACB906680AE000F359A9 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.cpp; - path = child.cpp; - refType = 4; - sourceTree = ""; - }; - 4CB5ACBA06680AE000F359A9 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - path = child.h; - refType = 4; - sourceTree = ""; - }; - 4CB5ACBB06680AE000F359A9 = { - fileRef = 4CB5ACB906680AE000F359A9; - isa = PBXBuildFile; - settings = { - }; - }; - 4CB5ACBC06680AE000F359A9 = { - fileRef = 4CB5ACBA06680AE000F359A9; - isa = PBXBuildFile; - settings = { - }; - }; - 4CD8CCB5055884BD006B3584 = { - containerPortal = 4CA1FEB0052A3C5800F22E42; - isa = PBXContainerItemProxy; - proxyType = 1; - remoteGlobalIDString = 4CA4EB2C0558848900CF7791; - remoteInfo = startup; - }; - 4CD8CCB6055884BD006B3584 = { - isa = PBXTargetDependency; - target = 4CA4EB2C0558848900CF7791; - targetProxy = 4CD8CCB5055884BD006B3584; - }; - 4CD8CCBB055884E0006B3584 = { - children = ( - 4CD8CCBC055884E0006B3584, - 4CD8CCBD055884E0006B3584, - C2A7B20F079F3A90000DB673, - C2A7B20E079F3A90000DB673, - 4CD8CCC0055884E0006B3584, - ); - isa = PBXGroup; - name = "Other Installs"; - path = etc; - refType = 4; - sourceTree = ""; - }; - 4CD8CCBC055884E0006B3584 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = text.plist; - path = authorization.plist; - refType = 4; - sourceTree = ""; - }; - 4CD8CCBD055884E0006B3584 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = text; - path = CodeEquivalenceCandidates; - refType = 4; - sourceTree = ""; - }; - 4CD8CCC0055884E0006B3584 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = text; - path = startup.mk; - refType = 4; - sourceTree = ""; - }; - 4CDD4F79053751FF00FEC36D = { - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - isa = PBXShellScriptBuildPhase; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "THEADER=$BUILT_PRODUCTS_DIR/include/flip_gen.h\nTCPP=$BUILT_PRODUCTS_DIR/include/flip_gen.cpp\nmkdir -p $BUILT_PRODUCTS_DIR/include\nsrc/generate.pl src/generate.cf $THEADER.new $TCPP.new cssmtype.h $CSSM_HEADERS\ncmp -s $THEADER.new $THEADER || mv $THEADER.new $THEADER\ncmp -s $TCPP.new $TCPP || mv $TCPP.new $TCPP\n"; - }; - 4CDD4F7A053751FF00FEC36D = { - buildPhases = ( - 4CDD4F79053751FF00FEC36D, - ); - buildSettings = { - CSSM_HEADERS = "$(BUILT_PRODUCTS_DIR)/Security.framework/Headers:$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Headers"; - OTHER_CFLAGS = ""; - OTHER_LDFLAGS = ""; - OTHER_REZFLAGS = ""; - PRODUCT_NAME = flippers; - REZ_EXECUTABLE = YES; - SECTORDER_FLAGS = ""; - WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas"; - }; - dependencies = ( - ); - isa = PBXToolTarget; - name = flippers; - productInstallPath = /usr/local/bin; - productName = flippers; - productReference = C2904F9606D116A3005FF97E; - }; - 4CDD4FB70537552600FEC36D = { - containerPortal = 4CA1FEB0052A3C5800F22E42; - isa = PBXContainerItemProxy; - proxyType = 1; - remoteGlobalIDString = 4CDD4F7A053751FF00FEC36D; - remoteInfo = flippers; - }; - 4CDD4FB80537552600FEC36D = { - isa = PBXTargetDependency; - target = 4CDD4F7A053751FF00FEC36D; - targetProxy = 4CDD4FB70537552600FEC36D; - }; - 4CDD50150537658500FEC36D = { - children = ( - 4CDD5018053765A900FEC36D, - 4CDD506B0537666500FEC36D, - C276AAD60663E7A400B57276, - 4CDD5019053765A900FEC36D, - ); - isa = PBXGroup; - name = "Linked Frameworks"; - path = src; - refType = 4; - sourceTree = ""; - }; - 4CDD5018053765A900FEC36D = { - isa = PBXFileReference; - lastKnownFileType = wrapper.framework; - name = CoreFoundation.framework; - path = /System/Library/Frameworks/CoreFoundation.framework; - refType = 0; - sourceTree = ""; - }; - 4CDD5019053765A900FEC36D = { - isa = PBXFileReference; - lastKnownFileType = wrapper.framework; - name = Security.framework; - path = /System/Library/Frameworks/Security.framework; - refType = 0; - sourceTree = ""; - }; - 4CDD506B0537666500FEC36D = { - isa = PBXFileReference; - lastKnownFileType = wrapper.framework; - name = IOKit.framework; - path = /System/Library/Frameworks/IOKit.framework; - refType = 0; - sourceTree = ""; - }; - 4CE1878506FFC5D60079D235 = { - children = ( - 4CE1878606FFC5D60079D235, - 4CE1878706FFC5D60079D235, - ); - isa = PBXGroup; - path = doc; - refType = 4; - sourceTree = ""; - }; - 4CE1878606FFC5D60079D235 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = text; - path = BLOBFORMAT; - refType = 4; - sourceTree = ""; - }; - 4CE1878706FFC5D60079D235 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = text.man; - path = securityd.1; - refType = 4; - sourceTree = ""; - }; -//4C0 -//4C1 -//4C2 -//4C3 -//4C4 -//C20 -//C21 -//C22 -//C23 -//C24 - C207646305EAD713004FEEDA = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.cpp; - path = kckey.cpp; - refType = 4; - sourceTree = ""; - }; - C207646405EAD713004FEEDA = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - path = kckey.h; - refType = 4; - sourceTree = ""; - }; - C207646505EAD713004FEEDA = { - fileRef = C207646305EAD713004FEEDA; - isa = PBXBuildFile; - settings = { - }; - }; - C207646605EAD713004FEEDA = { - fileRef = C207646405EAD713004FEEDA; - isa = PBXBuildFile; - settings = { - }; - }; - C20764E405ED250F004FEEDA = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.cpp; - path = localdatabase.cpp; - refType = 4; - sourceTree = ""; - }; - C20764E505ED250F004FEEDA = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - path = localdatabase.h; - refType = 4; - sourceTree = ""; - }; - C20764E605ED250F004FEEDA = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.cpp; - path = localkey.cpp; - refType = 4; - sourceTree = ""; - }; - C20764E705ED250F004FEEDA = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - path = localkey.h; - refType = 4; - sourceTree = ""; - }; - C20764E805ED250F004FEEDA = { - fileRef = C20764E405ED250F004FEEDA; - isa = PBXBuildFile; - settings = { - }; - }; - C20764E905ED250F004FEEDA = { - fileRef = C20764E505ED250F004FEEDA; - isa = PBXBuildFile; - settings = { - }; - }; - C20764EA05ED250F004FEEDA = { - fileRef = C20764E605ED250F004FEEDA; - isa = PBXBuildFile; - settings = { - }; - }; - C20764EB05ED250F004FEEDA = { - fileRef = C20764E705ED250F004FEEDA; - isa = PBXBuildFile; - settings = { - }; - }; - C209B39106ADBB19007B9E6D = { - children = ( - C209B3AD06ADBDB4007B9E6D, - C209B3AE06ADBDB4007B9E6D, - ); - isa = PBXGroup; - path = mig; - refType = 4; - sourceTree = ""; - }; - C209B39406ADBB2B007B9E6D = { - children = ( - C209B3B206ADBE64007B9E6D, - C209B3B306ADBE64007B9E6D, - C209B3B406ADBE64007B9E6D, - ); - isa = PBXGroup; - path = derived_src; - refType = 3; - sourceTree = BUILT_PRODUCTS_DIR; - }; - C209B3A406ADBCAC007B9E6D = { - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - isa = PBXShellScriptBuildPhase; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/bash; - shellScript = "make -f mig/mig.mk\n"; - }; - C209B3A506ADBCAC007B9E6D = { - buildPhases = ( - C209B3A406ADBCAC007B9E6D, - ); - buildSettings = { - OTHER_CFLAGS = ""; - OTHER_LDFLAGS = ""; - OTHER_REZFLAGS = ""; - PRODUCT_NAME = generate; - SECTORDER_FLAGS = ""; - WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas"; - }; - dependencies = ( - ); - isa = PBXAggregateTarget; - name = mig; - productName = generate; - }; - C209B3A906ADBD6D007B9E6D = { - containerPortal = 4CA1FEB0052A3C5800F22E42; - isa = PBXContainerItemProxy; - proxyType = 1; - remoteGlobalIDString = C209B3A506ADBCAC007B9E6D; - remoteInfo = mig; - }; - C209B3AA06ADBD6D007B9E6D = { - isa = PBXTargetDependency; - target = C209B3A506ADBCAC007B9E6D; - targetProxy = C209B3A906ADBD6D007B9E6D; - }; - C209B3AD06ADBDB4007B9E6D = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = text; - path = mig.mk; - refType = 4; - sourceTree = ""; - }; - C209B3AE06ADBDB4007B9E6D = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.mig; - path = self.defs; - refType = 4; - sourceTree = ""; - }; - C209B3B206ADBE64007B9E6D = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - path = self.h; - refType = 4; - sourceTree = ""; - }; - C209B3B306ADBE64007B9E6D = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.cpp; - path = selfServer.cpp; - refType = 4; - sourceTree = ""; - }; - C209B3B406ADBE64007B9E6D = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.cpp; - path = selfUser.cpp; - refType = 4; - sourceTree = ""; - }; - C209B3B506ADBE64007B9E6D = { - fileRef = C209B3B206ADBE64007B9E6D; - isa = PBXBuildFile; - settings = { - }; - }; - C209B3B606ADBE64007B9E6D = { - fileRef = C209B3B306ADBE64007B9E6D; - isa = PBXBuildFile; - settings = { - }; - }; - C209B3B706ADBE64007B9E6D = { - fileRef = C209B3B406ADBE64007B9E6D; - isa = PBXBuildFile; - settings = { - }; - }; - C20AF37C05F689540055732C = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.cpp; - path = tempdatabase.cpp; - refType = 4; - sourceTree = ""; - }; - C20AF37D05F689540055732C = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - path = tempdatabase.h; - refType = 4; - sourceTree = ""; - }; - C20AF37E05F689540055732C = { - fileRef = C20AF37C05F689540055732C; - isa = PBXBuildFile; - settings = { - }; - }; - C20AF37F05F689540055732C = { - fileRef = C20AF37D05F689540055732C; - isa = PBXBuildFile; - settings = { - }; - }; - C22A7F8C06AF06D9006087B7 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.cpp; - path = tokend.cpp; - refType = 4; - sourceTree = ""; - }; - C22A7F8D06AF06D9006087B7 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - path = tokend.h; - refType = 4; - sourceTree = ""; - }; - C22A7F8E06AF06D9006087B7 = { - fileRef = C22A7F8C06AF06D9006087B7; - isa = PBXBuildFile; - settings = { - }; - }; - C22A7F8F06AF06D9006087B7 = { - fileRef = C22A7F8D06AF06D9006087B7; - isa = PBXBuildFile; - settings = { - }; - }; - C265A4DB06F12750000E5CFC = { - buildSettings = { - BUILD_VARIANTS = normal; - COPY_PHASE_STRIP = NO; - OPT_LDFLAGS = ""; - OPT_LDXFLAGS = ""; - OPT_LDXNOPIC = ""; - OTHER_CFLAGS_normal = "$(OTHER_CFLAGS) -O1 -fno-inline"; - OTHER_CPLUSPLUSFLAGS_normal = "$(OTHER_CPLUSPLUSFLAGS) -O1 -fno-inline"; - }; - isa = PBXBuildStyle; - name = "normal with debug"; - }; - C26D533706C1E70A00062E1E = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.cpp; - path = tokenkey.cpp; - refType = 4; - sourceTree = ""; - }; - C26D533806C1E70A00062E1E = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - path = tokenkey.h; - refType = 4; - sourceTree = ""; - }; - C26D533906C1E70A00062E1E = { - fileRef = C26D533706C1E70A00062E1E; - isa = PBXBuildFile; - settings = { - }; - }; - C26D533A06C1E70A00062E1E = { - fileRef = C26D533806C1E70A00062E1E; - isa = PBXBuildFile; - settings = { - }; - }; - C26EA9510688CF34007CE21D = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.cpp; - path = tokencache.cpp; - refType = 4; - sourceTree = ""; - }; - C26EA9520688CF34007CE21D = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - path = tokencache.h; - refType = 4; - sourceTree = ""; - }; - C26EA9530688CF34007CE21D = { - fileRef = C26EA9510688CF34007CE21D; - isa = PBXBuildFile; - settings = { - }; - }; - C26EA9540688CF34007CE21D = { - fileRef = C26EA9520688CF34007CE21D; - isa = PBXBuildFile; - settings = { - }; - }; - C276AAD60663E7A400B57276 = { - isa = PBXFileReference; - lastKnownFileType = wrapper.framework; - name = PCSC.framework; - path = /System/Library/Frameworks/PCSC.framework; - refType = 0; - sourceTree = ""; - }; - C2813C7F0730534A00E243E8 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.cpp; - path = tokenaccess.cpp; - refType = 4; - sourceTree = ""; - }; - C2813C800730534A00E243E8 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - path = tokenaccess.h; - refType = 4; - sourceTree = ""; - }; - C2813C810730534A00E243E8 = { - fileRef = C2813C7F0730534A00E243E8; - isa = PBXBuildFile; - settings = { - }; - }; - C2813C820730534A00E243E8 = { - fileRef = C2813C800730534A00E243E8; - isa = PBXBuildFile; - settings = { - }; - }; - C28654B006DBC2A30021E6E5 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.cpp; - path = tokenacl.cpp; - refType = 4; - sourceTree = ""; - }; - C28654B106DBC2A30021E6E5 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - path = tokenacl.h; - refType = 4; - sourceTree = ""; - }; - C28654B206DBC2A30021E6E5 = { - fileRef = C28654B006DBC2A30021E6E5; - isa = PBXBuildFile; - settings = { - }; - }; - C28654B306DBC2A30021E6E5 = { - fileRef = C28654B106DBC2A30021E6E5; - isa = PBXBuildFile; - settings = { - }; - }; - C28ACF9A05C9940B00447176 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.cpp; - path = structure.cpp; - refType = 4; - sourceTree = ""; - }; - C28ACF9B05C9940B00447176 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - path = structure.h; - refType = 4; - sourceTree = ""; - }; - C28ACF9C05C9940B00447176 = { - fileRef = C28ACF9A05C9940B00447176; - isa = PBXBuildFile; - settings = { - }; - }; - C28ACF9D05C9940B00447176 = { - fileRef = C28ACF9B05C9940B00447176; - isa = PBXBuildFile; - settings = { - }; - }; - C28AE7FE06CD7CFF00BE0061 = { - children = ( - C2D425F205F3C07400CB11F8, - C2D425F105F3C07400CB11F8, - C26D533806C1E70A00062E1E, - C26D533706C1E70A00062E1E, - C2813C800730534A00E243E8, - C2813C7F0730534A00E243E8, - ); - isa = PBXGroup; - name = Token; - path = ""; - refType = 4; - sourceTree = ""; - }; - C28AE80106CD7D0E00BE0061 = { - children = ( - C20AF37D05F689540055732C, - C20AF37C05F689540055732C, - ); - isa = PBXGroup; - name = Temporary; - path = ""; - refType = 4; - sourceTree = ""; - }; - C28AE80406CD7D1D00BE0061 = { - children = ( - C20764E505ED250F004FEEDA, - C20764E405ED250F004FEEDA, - C20764E705ED250F004FEEDA, - C20764E605ED250F004FEEDA, - ); - isa = PBXGroup; - name = Local; - path = ""; - refType = 4; - sourceTree = ""; - }; - C28AE80706CD7D2700BE0061 = { - children = ( - C2B8DBCA05E6C3CE00E6E67C, - C2B8DBC905E6C3CE00E6E67C, - C207646405EAD713004FEEDA, - C207646305EAD713004FEEDA, - ); - isa = PBXGroup; - name = Keychain; - path = ""; - refType = 4; - sourceTree = ""; - }; - C28AE80A06CD7D3000BE0061 = { - children = ( - 4C9264B40534866F004B0E72, - 4C9264B20534866F004B0E72, - 4C9264B30534866F004B0E72, - ); - isa = PBXGroup; - name = Generate; - path = ""; - refType = 4; - sourceTree = ""; - }; - C28AE80E06CD7D5300BE0061 = { - children = ( - 4C9264B10534866F004B0E72, - 4C9264B00534866F004B0E72, - C28AE80A06CD7D3000BE0061, - ); - isa = PBXGroup; - name = Flippers; - path = ""; - refType = 4; - sourceTree = ""; - }; - C28AE81106CD7D7800BE0061 = { - children = ( - 40689F840725DCE00021A502, - 40689F850725DCE00021A502, - 4C92649F0534866F004B0E72, - 4C92649E0534866F004B0E72, - 4C9264A10534866F004B0E72, - 4C9264A00534866F004B0E72, - 4C9264A30534866F004B0E72, - 4C9264A20534866F004B0E72, - 405845660663B2010083E58C, - 405845650663B2010083E58C, - 4C9264A50534866F004B0E72, - 4C9264A40534866F004B0E72, - ); - isa = PBXGroup; - name = Authorization; - refType = 4; - sourceTree = ""; - }; - C28AE81406CD7DA100BE0061 = { - children = ( - 4C9264AB0534866F004B0E72, - 4C9264AA0534866F004B0E72, - C2B8DBC805E6C3CE00E6E67C, - C2B8DBC705E6C3CE00E6E67C, - 4C9264B60534866F004B0E72, - 4C9264B50534866F004B0E72, - 4C9264BB0534866F004B0E72, - 4C9264BA0534866F004B0E72, - 4C9264BF0534866F004B0E72, - 4C9264BE0534866F004B0E72, - 4C9264C10534866F004B0E72, - 4C9264C00534866F004B0E72, - C28ACF9B05C9940B00447176, - C28ACF9A05C9940B00447176, - ); - isa = PBXGroup; - name = "Core Structure"; - refType = 4; - sourceTree = ""; - }; - C28AE81706CD7DC500BE0061 = { - children = ( - C28AE80406CD7D1D00BE0061, - C28AE80706CD7D2700BE0061, - C28AE80106CD7D0E00BE0061, - C28AE7FE06CD7CFF00BE0061, - ); - isa = PBXGroup; - name = "Database Types"; - path = ""; - refType = 4; - sourceTree = ""; - }; - C28AE81A06CD7DE200BE0061 = { - children = ( - C2FDCABE0663CD5B0013F64C, - C2FDCABD0663CD5B0013F64C, - C2FDCAC00663CD5B0013F64C, - C2FDCABF0663CD5B0013F64C, - C2FDCAC20663CD5B0013F64C, - C2FDCAC10663CD5B0013F64C, - C22A7F8D06AF06D9006087B7, - C22A7F8C06AF06D9006087B7, - C26EA9520688CF34007CE21D, - C26EA9510688CF34007CE21D, - ); - isa = PBXGroup; - name = Smartcards; - refType = 4; - sourceTree = ""; - }; - C28AE82006CD7DF500BE0061 = { - children = ( - 4C9264BC0534866F004B0E72, - ); - isa = PBXGroup; - name = "Build Stuff"; - path = src; - refType = 4; - sourceTree = ""; - }; - C28AE82306CD7E0F00BE0061 = { - children = ( - 4C9264C20534866F004B0E72, - 4C9264C40534866F004B0E72, - 4C9264C30534866F004B0E72, - C28AE80E06CD7D5300BE0061, - ); - isa = PBXGroup; - name = Transit; - refType = 4; - sourceTree = ""; - }; - C28AE82606CD7E4700BE0061 = { - children = ( - 4C92649B0534866F004B0E72, - 4C92649A0534866F004B0E72, - C28654B106DBC2A30021E6E5, - C28654B006DBC2A30021E6E5, - 4C9264990534866F004B0E72, - 4C9264980534866F004B0E72, - ); - isa = PBXGroup; - name = ACLs; - refType = 4; - sourceTree = ""; - }; - C28AE83906CD7EE900BE0061 = { - children = ( - 4C92649D0534866F004B0E72, - 4C92649C0534866F004B0E72, - 4CB5ACBA06680AE000F359A9, - 4CB5ACB906680AE000F359A9, - 4C9264AF0534866F004B0E72, - 4C9264AE0534866F004B0E72, - 4C9264B90534866F004B0E72, - 4C9264B80534866F004B0E72, - 4C9264A90534866F004B0E72, - 4C9264A80534866F004B0E72, - ); - isa = PBXGroup; - name = Support; - refType = 4; - sourceTree = ""; - }; - C2904F9606D116A3005FF97E = { - explicitFileType = "compiled.mach-o.executable"; - includeInIndex = 0; - isa = PBXFileReference; - path = flippers; - refType = 3; - sourceTree = BUILT_PRODUCTS_DIR; - }; - C2A7B20E079F3A90000DB673 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = text.xml; - path = "securityd-installCD.plist"; - refType = 4; - sourceTree = ""; - }; - C2A7B20F079F3A90000DB673 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = text.xml; - path = securityd.plist; - refType = 4; - sourceTree = ""; - }; - C2B8DBC705E6C3CE00E6E67C = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.cpp; - path = database.cpp; - refType = 4; - sourceTree = ""; - }; - C2B8DBC805E6C3CE00E6E67C = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - path = database.h; - refType = 4; - sourceTree = ""; - }; - C2B8DBC905E6C3CE00E6E67C = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.cpp; - path = kcdatabase.cpp; - refType = 4; - sourceTree = ""; - }; - C2B8DBCA05E6C3CE00E6E67C = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - path = kcdatabase.h; - refType = 4; - sourceTree = ""; - }; - C2B8DBCB05E6C3CE00E6E67C = { - fileRef = C2B8DBC705E6C3CE00E6E67C; - isa = PBXBuildFile; - settings = { - }; - }; - C2B8DBCC05E6C3CE00E6E67C = { - fileRef = C2B8DBC805E6C3CE00E6E67C; - isa = PBXBuildFile; - settings = { - }; - }; - C2B8DBCD05E6C3CE00E6E67C = { - fileRef = C2B8DBC905E6C3CE00E6E67C; - isa = PBXBuildFile; - settings = { - }; - }; - C2B8DBCE05E6C3CE00E6E67C = { - fileRef = C2B8DBCA05E6C3CE00E6E67C; - isa = PBXBuildFile; - settings = { - }; - }; - C2C8B29806F8A60F000EBDA2 = { - children = ( - 4C9264AD0534866F004B0E72, - 4C9264AC0534866F004B0E72, - ); - isa = PBXGroup; - name = Crypto; - refType = 4; - sourceTree = ""; - }; - C2D425F105F3C07400CB11F8 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.cpp; - path = tokendatabase.cpp; - refType = 4; - sourceTree = ""; - }; - C2D425F205F3C07400CB11F8 = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - path = tokendatabase.h; - refType = 4; - sourceTree = ""; - }; - C2D425F305F3C07400CB11F8 = { - fileRef = C2D425F105F3C07400CB11F8; - isa = PBXBuildFile; - settings = { - }; - }; - C2D425F405F3C07400CB11F8 = { - fileRef = C2D425F205F3C07400CB11F8; - isa = PBXBuildFile; - settings = { - }; - }; - C2FDCABD0663CD5B0013F64C = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.cpp; - path = pcscmonitor.cpp; - refType = 4; - sourceTree = ""; - }; - C2FDCABE0663CD5B0013F64C = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - path = pcscmonitor.h; - refType = 4; - sourceTree = ""; - }; - C2FDCABF0663CD5B0013F64C = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.cpp; - path = reader.cpp; - refType = 4; - sourceTree = ""; - }; - C2FDCAC00663CD5B0013F64C = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - path = reader.h; - refType = 4; - sourceTree = ""; - }; - C2FDCAC10663CD5B0013F64C = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.cpp.cpp; - path = token.cpp; - refType = 4; - sourceTree = ""; - }; - C2FDCAC20663CD5B0013F64C = { - fileEncoding = 30; - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - path = token.h; - refType = 4; - sourceTree = ""; - }; - C2FDCAC50663CD5B0013F64C = { - fileRef = C2FDCABD0663CD5B0013F64C; - isa = PBXBuildFile; - settings = { - }; - }; - C2FDCAC60663CD5B0013F64C = { - fileRef = C2FDCABE0663CD5B0013F64C; - isa = PBXBuildFile; - settings = { - }; - }; - C2FDCAC70663CD5B0013F64C = { - fileRef = C2FDCABF0663CD5B0013F64C; - isa = PBXBuildFile; - settings = { - }; - }; - C2FDCAC80663CD5B0013F64C = { - fileRef = C2FDCAC00663CD5B0013F64C; - isa = PBXBuildFile; - settings = { - }; - }; - C2FDCAC90663CD5B0013F64C = { - fileRef = C2FDCAC10663CD5B0013F64C; - isa = PBXBuildFile; - settings = { - }; - }; - C2FDCACA0663CD5B0013F64C = { - fileRef = C2FDCAC20663CD5B0013F64C; - isa = PBXBuildFile; - settings = { - }; - }; - }; - rootObject = 4CA1FEB0052A3C5800F22E42; -} diff --git a/securityd.xcodeproj/project.pbxproj b/securityd.xcodeproj/project.pbxproj new file mode 100644 index 0000000..1dcd18c --- /dev/null +++ b/securityd.xcodeproj/project.pbxproj @@ -0,0 +1,1213 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 42; + objects = { + +/* Begin PBXAggregateTarget section */ + C209B3A506ADBCAC007B9E6D /* mig */ = { + isa = PBXAggregateTarget; + buildConfigurationList = C27AD4990987FCF4001272E0 /* Build configuration list for PBXAggregateTarget "mig" */; + buildPhases = ( + C209B3A406ADBCAC007B9E6D /* ShellScript */, + ); + dependencies = ( + ); + name = mig; + productName = generate; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 405845670663B2010083E58C /* AuthorizationMechEval.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 405845650663B2010083E58C /* AuthorizationMechEval.cpp */; }; + 405845680663B2010083E58C /* AuthorizationMechEval.h in Headers */ = {isa = PBXBuildFile; fileRef = 405845660663B2010083E58C /* AuthorizationMechEval.h */; }; + 40689F860725DCE00021A502 /* authhost.h in Headers */ = {isa = PBXBuildFile; fileRef = 40689F840725DCE00021A502 /* authhost.h */; }; + 40689F870725DCE00021A502 /* authhost.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 40689F850725DCE00021A502 /* authhost.cpp */; }; + 407ACD080AE5B57700A9DA90 /* credential.h in Headers */ = {isa = PBXBuildFile; fileRef = 407ACD060AE5B57700A9DA90 /* credential.h */; }; + 407ACD090AE5B57700A9DA90 /* credential.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 407ACD070AE5B57700A9DA90 /* credential.cpp */; }; + 4C01B3DA06FFC640004B3A01 /* securityd.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4CE1878706FFC5D60079D235 /* securityd.1 */; }; + 4C9264C80534866F004B0E72 /* acl_keychain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C9264980534866F004B0E72 /* acl_keychain.cpp */; }; + 4C9264C90534866F004B0E72 /* acl_keychain.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C9264990534866F004B0E72 /* acl_keychain.h */; }; + 4C9264CA0534866F004B0E72 /* acls.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C92649A0534866F004B0E72 /* acls.cpp */; }; + 4C9264CB0534866F004B0E72 /* acls.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C92649B0534866F004B0E72 /* acls.h */; }; + 4C9264CC0534866F004B0E72 /* agentquery.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C92649C0534866F004B0E72 /* agentquery.cpp */; }; + 4C9264CD0534866F004B0E72 /* agentquery.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C92649D0534866F004B0E72 /* agentquery.h */; }; + 4C9264CE0534866F004B0E72 /* authority.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C92649E0534866F004B0E72 /* authority.cpp */; }; + 4C9264CF0534866F004B0E72 /* authority.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C92649F0534866F004B0E72 /* authority.h */; }; + 4C9264D00534866F004B0E72 /* AuthorizationDBPlist.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C9264A00534866F004B0E72 /* AuthorizationDBPlist.cpp */; }; + 4C9264D10534866F004B0E72 /* AuthorizationDBPlist.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C9264A10534866F004B0E72 /* AuthorizationDBPlist.h */; }; + 4C9264D20534866F004B0E72 /* AuthorizationEngine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C9264A20534866F004B0E72 /* AuthorizationEngine.cpp */; }; + 4C9264D30534866F004B0E72 /* AuthorizationEngine.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C9264A30534866F004B0E72 /* AuthorizationEngine.h */; }; + 4C9264D40534866F004B0E72 /* AuthorizationRule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C9264A40534866F004B0E72 /* AuthorizationRule.cpp */; }; + 4C9264D50534866F004B0E72 /* AuthorizationRule.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C9264A50534866F004B0E72 /* AuthorizationRule.h */; }; + 4C9264D80534866F004B0E72 /* codesigdb.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C9264A80534866F004B0E72 /* codesigdb.cpp */; }; + 4C9264D90534866F004B0E72 /* codesigdb.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C9264A90534866F004B0E72 /* codesigdb.h */; }; + 4C9264DA0534866F004B0E72 /* connection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C9264AA0534866F004B0E72 /* connection.cpp */; }; + 4C9264DB0534866F004B0E72 /* connection.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C9264AB0534866F004B0E72 /* connection.h */; }; + 4C9264DC0534866F004B0E72 /* dbcrypto.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C9264AC0534866F004B0E72 /* dbcrypto.cpp */; }; + 4C9264DD0534866F004B0E72 /* dbcrypto.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C9264AD0534866F004B0E72 /* dbcrypto.h */; }; + 4C9264DE0534866F004B0E72 /* entropy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C9264AE0534866F004B0E72 /* entropy.cpp */; }; + 4C9264DF0534866F004B0E72 /* entropy.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C9264AF0534866F004B0E72 /* entropy.h */; }; + 4C9264E20534866F004B0E72 /* key.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C9264B50534866F004B0E72 /* key.cpp */; }; + 4C9264E30534866F004B0E72 /* key.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C9264B60534866F004B0E72 /* key.h */; }; + 4C9264E40534866F004B0E72 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C9264B70534866F004B0E72 /* main.cpp */; }; + 4C9264E50534866F004B0E72 /* notifications.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C9264B80534866F004B0E72 /* notifications.cpp */; }; + 4C9264E60534866F004B0E72 /* notifications.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C9264B90534866F004B0E72 /* notifications.h */; }; + 4C9264E70534866F004B0E72 /* process.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C9264BA0534866F004B0E72 /* process.cpp */; }; + 4C9264E80534866F004B0E72 /* process.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C9264BB0534866F004B0E72 /* process.h */; }; + 4C9264EA0534866F004B0E72 /* server.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C9264BE0534866F004B0E72 /* server.cpp */; }; + 4C9264EB0534866F004B0E72 /* server.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C9264BF0534866F004B0E72 /* server.h */; }; + 4C9264EC0534866F004B0E72 /* session.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C9264C00534866F004B0E72 /* session.cpp */; }; + 4C9264ED0534866F004B0E72 /* session.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C9264C10534866F004B0E72 /* session.h */; }; + 4C9264EE0534866F004B0E72 /* transition.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C9264C20534866F004B0E72 /* transition.cpp */; }; + 4CB5ACBB06680AE000F359A9 /* child.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CB5ACB906680AE000F359A9 /* child.cpp */; }; + 4CB5ACBC06680AE000F359A9 /* child.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CB5ACBA06680AE000F359A9 /* child.h */; }; + C207646505EAD713004FEEDA /* kckey.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C207646305EAD713004FEEDA /* kckey.cpp */; }; + C207646605EAD713004FEEDA /* kckey.h in Headers */ = {isa = PBXBuildFile; fileRef = C207646405EAD713004FEEDA /* kckey.h */; }; + C20764E805ED250F004FEEDA /* localdatabase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C20764E405ED250F004FEEDA /* localdatabase.cpp */; }; + C20764E905ED250F004FEEDA /* localdatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = C20764E505ED250F004FEEDA /* localdatabase.h */; }; + C20764EA05ED250F004FEEDA /* localkey.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C20764E605ED250F004FEEDA /* localkey.cpp */; }; + C20764EB05ED250F004FEEDA /* localkey.h in Headers */ = {isa = PBXBuildFile; fileRef = C20764E705ED250F004FEEDA /* localkey.h */; }; + C209B3B506ADBE64007B9E6D /* self.h in Headers */ = {isa = PBXBuildFile; fileRef = C209B3B206ADBE64007B9E6D /* self.h */; }; + C209B3B606ADBE64007B9E6D /* selfServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C209B3B306ADBE64007B9E6D /* selfServer.cpp */; settings = {COMPILER_FLAGS = "-D__MigTypeCheck=1"; }; }; + C209B3B706ADBE64007B9E6D /* selfUser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C209B3B406ADBE64007B9E6D /* selfUser.cpp */; }; + C20AF37E05F689540055732C /* tempdatabase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C20AF37C05F689540055732C /* tempdatabase.cpp */; }; + C20AF37F05F689540055732C /* tempdatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = C20AF37D05F689540055732C /* tempdatabase.h */; }; + C22A7F8E06AF06D9006087B7 /* tokend.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C22A7F8C06AF06D9006087B7 /* tokend.cpp */; }; + C22A7F8F06AF06D9006087B7 /* tokend.h in Headers */ = {isa = PBXBuildFile; fileRef = C22A7F8D06AF06D9006087B7 /* tokend.h */; }; + C22C344E0B278E770009368E /* osxcodewrap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C22C344C0B278E770009368E /* osxcodewrap.cpp */; }; + C22C344F0B278E770009368E /* osxcodewrap.h in Headers */ = {isa = PBXBuildFile; fileRef = C22C344D0B278E770009368E /* osxcodewrap.h */; }; + C22C34540B278EB60009368E /* clientid.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C22C34520B278EB60009368E /* clientid.cpp */; }; + C22C34550B278EB60009368E /* clientid.h in Headers */ = {isa = PBXBuildFile; fileRef = C22C34530B278EB60009368E /* clientid.h */; }; + C26D533906C1E70A00062E1E /* tokenkey.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C26D533706C1E70A00062E1E /* tokenkey.cpp */; }; + C26D533A06C1E70A00062E1E /* tokenkey.h in Headers */ = {isa = PBXBuildFile; fileRef = C26D533806C1E70A00062E1E /* tokenkey.h */; }; + C26EA9530688CF34007CE21D /* tokencache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C26EA9510688CF34007CE21D /* tokencache.cpp */; }; + C26EA9540688CF34007CE21D /* tokencache.h in Headers */ = {isa = PBXBuildFile; fileRef = C26EA9520688CF34007CE21D /* tokencache.h */; }; + C2813C810730534A00E243E8 /* tokenaccess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2813C7F0730534A00E243E8 /* tokenaccess.cpp */; }; + C2813C820730534A00E243E8 /* tokenaccess.h in Headers */ = {isa = PBXBuildFile; fileRef = C2813C800730534A00E243E8 /* tokenaccess.h */; }; + C28654B206DBC2A30021E6E5 /* tokenacl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C28654B006DBC2A30021E6E5 /* tokenacl.cpp */; }; + C28654B306DBC2A30021E6E5 /* tokenacl.h in Headers */ = {isa = PBXBuildFile; fileRef = C28654B106DBC2A30021E6E5 /* tokenacl.h */; }; + C28ACF9C05C9940B00447176 /* structure.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C28ACF9A05C9940B00447176 /* structure.cpp */; }; + C28ACF9D05C9940B00447176 /* structure.h in Headers */ = {isa = PBXBuildFile; fileRef = C28ACF9B05C9940B00447176 /* structure.h */; }; + C2B8DBCB05E6C3CE00E6E67C /* database.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2B8DBC705E6C3CE00E6E67C /* database.cpp */; }; + C2B8DBCC05E6C3CE00E6E67C /* database.h in Headers */ = {isa = PBXBuildFile; fileRef = C2B8DBC805E6C3CE00E6E67C /* database.h */; }; + C2B8DBCD05E6C3CE00E6E67C /* kcdatabase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2B8DBC905E6C3CE00E6E67C /* kcdatabase.cpp */; }; + C2B8DBCE05E6C3CE00E6E67C /* kcdatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = C2B8DBCA05E6C3CE00E6E67C /* kcdatabase.h */; }; + C2BD5FDC0AC47E850057FD3D /* csproxy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2BD5FDA0AC47E850057FD3D /* csproxy.cpp */; }; + C2BD5FDD0AC47E850057FD3D /* csproxy.h in Headers */ = {isa = PBXBuildFile; fileRef = C2BD5FDB0AC47E850057FD3D /* csproxy.h */; }; + C2D425F305F3C07400CB11F8 /* tokendatabase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2D425F105F3C07400CB11F8 /* tokendatabase.cpp */; }; + C2D425F405F3C07400CB11F8 /* tokendatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = C2D425F205F3C07400CB11F8 /* tokendatabase.h */; }; + C2FDCAC50663CD5B0013F64C /* pcscmonitor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2FDCABD0663CD5B0013F64C /* pcscmonitor.cpp */; }; + C2FDCAC60663CD5B0013F64C /* pcscmonitor.h in Headers */ = {isa = PBXBuildFile; fileRef = C2FDCABE0663CD5B0013F64C /* pcscmonitor.h */; }; + C2FDCAC70663CD5B0013F64C /* reader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2FDCABF0663CD5B0013F64C /* reader.cpp */; }; + C2FDCAC80663CD5B0013F64C /* reader.h in Headers */ = {isa = PBXBuildFile; fileRef = C2FDCAC00663CD5B0013F64C /* reader.h */; }; + C2FDCAC90663CD5B0013F64C /* token.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2FDCAC10663CD5B0013F64C /* token.cpp */; }; + C2FDCACA0663CD5B0013F64C /* token.h in Headers */ = {isa = PBXBuildFile; fileRef = C2FDCAC20663CD5B0013F64C /* token.h */; }; + D6C887F00A55B6220044DFD2 /* SharedMemoryServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D6C887ED0A55B6220044DFD2 /* SharedMemoryServer.cpp */; }; + D6C887F10A55B6220044DFD2 /* SharedMemoryServer.h in Headers */ = {isa = PBXBuildFile; fileRef = D6C887EE0A55B6220044DFD2 /* SharedMemoryServer.h */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 4CD8CCB5055884BD006B3584 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4CA1FEB0052A3C5800F22E42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4CA4EB2C0558848900CF7791; + remoteInfo = startup; + }; + C209B3A906ADBD6D007B9E6D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4CA1FEB0052A3C5800F22E42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = C209B3A506ADBCAC007B9E6D; + remoteInfo = mig; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 4C01B3D706FFC621004B3A01 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + 4C01B3DA06FFC640004B3A01 /* securityd.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 405845650663B2010083E58C /* AuthorizationMechEval.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AuthorizationMechEval.cpp; sourceTree = ""; }; + 405845660663B2010083E58C /* AuthorizationMechEval.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AuthorizationMechEval.h; sourceTree = ""; }; + 40689F840725DCE00021A502 /* authhost.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = authhost.h; sourceTree = ""; }; + 40689F850725DCE00021A502 /* authhost.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = authhost.cpp; sourceTree = ""; }; + 407ACD060AE5B57700A9DA90 /* credential.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = credential.h; sourceTree = ""; }; + 407ACD070AE5B57700A9DA90 /* credential.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = credential.cpp; sourceTree = ""; }; + 4C9264980534866F004B0E72 /* acl_keychain.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = acl_keychain.cpp; sourceTree = ""; }; + 4C9264990534866F004B0E72 /* acl_keychain.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = acl_keychain.h; sourceTree = ""; }; + 4C92649A0534866F004B0E72 /* acls.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = acls.cpp; sourceTree = ""; }; + 4C92649B0534866F004B0E72 /* acls.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = acls.h; sourceTree = ""; }; + 4C92649C0534866F004B0E72 /* agentquery.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = agentquery.cpp; sourceTree = ""; }; + 4C92649D0534866F004B0E72 /* agentquery.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = agentquery.h; sourceTree = ""; }; + 4C92649E0534866F004B0E72 /* authority.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = authority.cpp; sourceTree = ""; }; + 4C92649F0534866F004B0E72 /* authority.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = authority.h; sourceTree = ""; }; + 4C9264A00534866F004B0E72 /* AuthorizationDBPlist.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AuthorizationDBPlist.cpp; sourceTree = ""; }; + 4C9264A10534866F004B0E72 /* AuthorizationDBPlist.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AuthorizationDBPlist.h; sourceTree = ""; }; + 4C9264A20534866F004B0E72 /* AuthorizationEngine.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AuthorizationEngine.cpp; sourceTree = ""; }; + 4C9264A30534866F004B0E72 /* AuthorizationEngine.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AuthorizationEngine.h; sourceTree = ""; }; + 4C9264A40534866F004B0E72 /* AuthorizationRule.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AuthorizationRule.cpp; sourceTree = ""; }; + 4C9264A50534866F004B0E72 /* AuthorizationRule.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AuthorizationRule.h; sourceTree = ""; }; + 4C9264A80534866F004B0E72 /* codesigdb.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = codesigdb.cpp; sourceTree = ""; }; + 4C9264A90534866F004B0E72 /* codesigdb.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = codesigdb.h; sourceTree = ""; }; + 4C9264AA0534866F004B0E72 /* connection.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = connection.cpp; sourceTree = ""; }; + 4C9264AB0534866F004B0E72 /* connection.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = connection.h; sourceTree = ""; }; + 4C9264AC0534866F004B0E72 /* dbcrypto.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = dbcrypto.cpp; sourceTree = ""; }; + 4C9264AD0534866F004B0E72 /* dbcrypto.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = dbcrypto.h; sourceTree = ""; }; + 4C9264AE0534866F004B0E72 /* entropy.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = entropy.cpp; sourceTree = ""; }; + 4C9264AF0534866F004B0E72 /* entropy.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = entropy.h; sourceTree = ""; }; + 4C9264B50534866F004B0E72 /* key.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = key.cpp; sourceTree = ""; }; + 4C9264B60534866F004B0E72 /* key.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = key.h; sourceTree = ""; }; + 4C9264B70534866F004B0E72 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 4C9264B80534866F004B0E72 /* notifications.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = notifications.cpp; sourceTree = ""; }; + 4C9264B90534866F004B0E72 /* notifications.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = notifications.h; sourceTree = ""; }; + 4C9264BA0534866F004B0E72 /* process.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = process.cpp; sourceTree = ""; }; + 4C9264BB0534866F004B0E72 /* process.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = process.h; sourceTree = ""; }; + 4C9264BC0534866F004B0E72 /* securityd.order */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = securityd.order; sourceTree = ""; }; + 4C9264BE0534866F004B0E72 /* server.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = server.cpp; sourceTree = ""; }; + 4C9264BF0534866F004B0E72 /* server.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = server.h; sourceTree = ""; }; + 4C9264C00534866F004B0E72 /* session.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = session.cpp; sourceTree = ""; }; + 4C9264C10534866F004B0E72 /* session.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = session.h; sourceTree = ""; }; + 4C9264C20534866F004B0E72 /* transition.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = transition.cpp; sourceTree = ""; }; + 4CA1FEB6052A3C6D00F22E42 /* securityd */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; path = securityd; sourceTree = BUILT_PRODUCTS_DIR; }; + 4CB5ACB906680AE000F359A9 /* child.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = child.cpp; sourceTree = ""; }; + 4CB5ACBA06680AE000F359A9 /* child.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = child.h; sourceTree = ""; }; + 4CD8CCBC055884E0006B3584 /* authorization.plist */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.plist; path = authorization.plist; sourceTree = ""; }; + 4CD8CCBD055884E0006B3584 /* CodeEquivalenceCandidates */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = CodeEquivalenceCandidates; sourceTree = ""; }; + 4CD8CCC0055884E0006B3584 /* startup.mk */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = startup.mk; sourceTree = ""; }; + 4CDD5018053765A900FEC36D /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = ""; }; + 4CDD5019053765A900FEC36D /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = /System/Library/Frameworks/Security.framework; sourceTree = ""; }; + 4CDD506B0537666500FEC36D /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = /System/Library/Frameworks/IOKit.framework; sourceTree = ""; }; + 4CE1878606FFC5D60079D235 /* BLOBFORMAT */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = BLOBFORMAT; sourceTree = ""; }; + 4CE1878706FFC5D60079D235 /* securityd.1 */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.man; path = securityd.1; sourceTree = ""; }; + C207646305EAD713004FEEDA /* kckey.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = kckey.cpp; sourceTree = ""; }; + C207646405EAD713004FEEDA /* kckey.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = kckey.h; sourceTree = ""; }; + C20764E405ED250F004FEEDA /* localdatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = localdatabase.cpp; sourceTree = ""; }; + C20764E505ED250F004FEEDA /* localdatabase.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = localdatabase.h; sourceTree = ""; }; + C20764E605ED250F004FEEDA /* localkey.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = localkey.cpp; sourceTree = ""; }; + C20764E705ED250F004FEEDA /* localkey.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = localkey.h; sourceTree = ""; }; + C209B3AD06ADBDB4007B9E6D /* mig.mk */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = mig.mk; sourceTree = ""; }; + C209B3AE06ADBDB4007B9E6D /* self.defs */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.mig; path = self.defs; sourceTree = ""; }; + C209B3B206ADBE64007B9E6D /* self.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = self.h; sourceTree = ""; }; + C209B3B306ADBE64007B9E6D /* selfServer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = selfServer.cpp; sourceTree = ""; }; + C209B3B406ADBE64007B9E6D /* selfUser.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = selfUser.cpp; sourceTree = ""; }; + C20AF37C05F689540055732C /* tempdatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = tempdatabase.cpp; sourceTree = ""; }; + C20AF37D05F689540055732C /* tempdatabase.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = tempdatabase.h; sourceTree = ""; }; + C22A7F8C06AF06D9006087B7 /* tokend.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = tokend.cpp; sourceTree = ""; }; + C22A7F8D06AF06D9006087B7 /* tokend.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = tokend.h; sourceTree = ""; }; + C22C344C0B278E770009368E /* osxcodewrap.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = osxcodewrap.cpp; sourceTree = ""; }; + C22C344D0B278E770009368E /* osxcodewrap.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = osxcodewrap.h; sourceTree = ""; }; + C22C34520B278EB60009368E /* clientid.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = clientid.cpp; sourceTree = ""; }; + C22C34530B278EB60009368E /* clientid.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = clientid.h; sourceTree = ""; }; + C26D533706C1E70A00062E1E /* tokenkey.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = tokenkey.cpp; sourceTree = ""; }; + C26D533806C1E70A00062E1E /* tokenkey.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = tokenkey.h; sourceTree = ""; }; + C26EA9510688CF34007CE21D /* tokencache.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = tokencache.cpp; sourceTree = ""; }; + C26EA9520688CF34007CE21D /* tokencache.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = tokencache.h; sourceTree = ""; }; + C26FB2650BC2C3A300D8EFC8 /* com.apple.securityd.plist */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.plist.xml; path = com.apple.securityd.plist; sourceTree = ""; }; + C276AAD60663E7A400B57276 /* PCSC.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PCSC.framework; path = /System/Library/Frameworks/PCSC.framework; sourceTree = ""; }; + C2813C7F0730534A00E243E8 /* tokenaccess.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = tokenaccess.cpp; sourceTree = ""; }; + C2813C800730534A00E243E8 /* tokenaccess.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = tokenaccess.h; sourceTree = ""; }; + C28654B006DBC2A30021E6E5 /* tokenacl.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = tokenacl.cpp; sourceTree = ""; }; + C28654B106DBC2A30021E6E5 /* tokenacl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = tokenacl.h; sourceTree = ""; }; + C28ACF9A05C9940B00447176 /* structure.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = structure.cpp; sourceTree = ""; }; + C28ACF9B05C9940B00447176 /* structure.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = structure.h; sourceTree = ""; }; + C2B8DBC705E6C3CE00E6E67C /* database.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = database.cpp; sourceTree = ""; }; + C2B8DBC805E6C3CE00E6E67C /* database.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = database.h; sourceTree = ""; }; + C2B8DBC905E6C3CE00E6E67C /* kcdatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = kcdatabase.cpp; sourceTree = ""; }; + C2B8DBCA05E6C3CE00E6E67C /* kcdatabase.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = kcdatabase.h; sourceTree = ""; }; + C2BD5FDA0AC47E850057FD3D /* csproxy.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = csproxy.cpp; sourceTree = ""; }; + C2BD5FDB0AC47E850057FD3D /* csproxy.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = csproxy.h; sourceTree = ""; }; + C2D425F105F3C07400CB11F8 /* tokendatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = tokendatabase.cpp; sourceTree = ""; }; + C2D425F205F3C07400CB11F8 /* tokendatabase.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = tokendatabase.h; sourceTree = ""; }; + C2FDCABD0663CD5B0013F64C /* pcscmonitor.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = pcscmonitor.cpp; sourceTree = ""; }; + C2FDCABE0663CD5B0013F64C /* pcscmonitor.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = pcscmonitor.h; sourceTree = ""; }; + C2FDCABF0663CD5B0013F64C /* reader.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = reader.cpp; sourceTree = ""; }; + C2FDCAC00663CD5B0013F64C /* reader.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = reader.h; sourceTree = ""; }; + C2FDCAC10663CD5B0013F64C /* token.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = token.cpp; sourceTree = ""; }; + C2FDCAC20663CD5B0013F64C /* token.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = token.h; sourceTree = ""; }; + D6C887ED0A55B6220044DFD2 /* SharedMemoryServer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SharedMemoryServer.cpp; sourceTree = ""; }; + D6C887EE0A55B6220044DFD2 /* SharedMemoryServer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SharedMemoryServer.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 4CA1FEB3052A3C6D00F22E42 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 4C9264970534866F004B0E72 /* src */ = { + isa = PBXGroup; + children = ( + 4C9264B70534866F004B0E72 /* main.cpp */, + C28AE81406CD7DA100BE0061 /* Core Structure */, + C2C8B29806F8A60F000EBDA2 /* Crypto */, + C28AE81706CD7DC500BE0061 /* Database Types */, + C28AE81A06CD7DE200BE0061 /* Smartcards */, + C28AE82306CD7E0F00BE0061 /* Transit */, + C28AE82606CD7E4700BE0061 /* ACLs */, + C28AE81106CD7D7800BE0061 /* Authorization */, + C22C34510B278E950009368E /* Client Identification */, + C28AE83906CD7EE900BE0061 /* Support */, + ); + path = src; + sourceTree = ""; + }; + 4CA1FEAC052A3C5800F22E42 = { + isa = PBXGroup; + children = ( + 4C9264970534866F004B0E72 /* src */, + C209B39106ADBB19007B9E6D /* mig */, + 4CE1878506FFC5D60079D235 /* doc */, + C209B39406ADBB2B007B9E6D /* derived_src */, + C28AE82006CD7DF500BE0061 /* Build Stuff */, + 4CDD50150537658500FEC36D /* Linked Frameworks */, + 4CA1FEB7052A3C6D00F22E42 /* Products */, + 4CD8CCBB055884E0006B3584 /* Other Installs */, + ); + sourceTree = ""; + }; + 4CA1FEB7052A3C6D00F22E42 /* Products */ = { + isa = PBXGroup; + children = ( + 4CA1FEB6052A3C6D00F22E42 /* securityd */, + ); + name = Products; + sourceTree = ""; + }; + 4CD8CCBB055884E0006B3584 /* Other Installs */ = { + isa = PBXGroup; + children = ( + C26FB2650BC2C3A300D8EFC8 /* com.apple.securityd.plist */, + 4CD8CCBC055884E0006B3584 /* authorization.plist */, + 4CD8CCBD055884E0006B3584 /* CodeEquivalenceCandidates */, + 4CD8CCC0055884E0006B3584 /* startup.mk */, + ); + name = "Other Installs"; + path = etc; + sourceTree = ""; + }; + 4CDD50150537658500FEC36D /* Linked Frameworks */ = { + isa = PBXGroup; + children = ( + 4CDD5018053765A900FEC36D /* CoreFoundation.framework */, + 4CDD506B0537666500FEC36D /* IOKit.framework */, + C276AAD60663E7A400B57276 /* PCSC.framework */, + 4CDD5019053765A900FEC36D /* Security.framework */, + ); + name = "Linked Frameworks"; + path = src; + sourceTree = ""; + }; + 4CE1878506FFC5D60079D235 /* doc */ = { + isa = PBXGroup; + children = ( + 4CE1878606FFC5D60079D235 /* BLOBFORMAT */, + 4CE1878706FFC5D60079D235 /* securityd.1 */, + ); + path = doc; + sourceTree = ""; + }; + C209B39106ADBB19007B9E6D /* mig */ = { + isa = PBXGroup; + children = ( + C209B3AD06ADBDB4007B9E6D /* mig.mk */, + C209B3AE06ADBDB4007B9E6D /* self.defs */, + ); + path = mig; + sourceTree = ""; + }; + C209B39406ADBB2B007B9E6D /* derived_src */ = { + isa = PBXGroup; + children = ( + C209B3B206ADBE64007B9E6D /* self.h */, + C209B3B306ADBE64007B9E6D /* selfServer.cpp */, + C209B3B406ADBE64007B9E6D /* selfUser.cpp */, + ); + path = derived_src; + sourceTree = BUILT_PRODUCTS_DIR; + }; + C22C34510B278E950009368E /* Client Identification */ = { + isa = PBXGroup; + children = ( + C22C34530B278EB60009368E /* clientid.h */, + C22C34520B278EB60009368E /* clientid.cpp */, + C2BD5FDB0AC47E850057FD3D /* csproxy.h */, + C2BD5FDA0AC47E850057FD3D /* csproxy.cpp */, + 4C9264A90534866F004B0E72 /* codesigdb.h */, + 4C9264A80534866F004B0E72 /* codesigdb.cpp */, + ); + name = "Client Identification"; + sourceTree = ""; + }; + C28AE7FE06CD7CFF00BE0061 /* Token */ = { + isa = PBXGroup; + children = ( + C2D425F205F3C07400CB11F8 /* tokendatabase.h */, + C2D425F105F3C07400CB11F8 /* tokendatabase.cpp */, + C26D533806C1E70A00062E1E /* tokenkey.h */, + C26D533706C1E70A00062E1E /* tokenkey.cpp */, + C2813C800730534A00E243E8 /* tokenaccess.h */, + C2813C7F0730534A00E243E8 /* tokenaccess.cpp */, + ); + name = Token; + sourceTree = ""; + }; + C28AE80106CD7D0E00BE0061 /* Temporary */ = { + isa = PBXGroup; + children = ( + C20AF37D05F689540055732C /* tempdatabase.h */, + C20AF37C05F689540055732C /* tempdatabase.cpp */, + ); + name = Temporary; + sourceTree = ""; + }; + C28AE80406CD7D1D00BE0061 /* Local */ = { + isa = PBXGroup; + children = ( + C20764E505ED250F004FEEDA /* localdatabase.h */, + C20764E405ED250F004FEEDA /* localdatabase.cpp */, + C20764E705ED250F004FEEDA /* localkey.h */, + C20764E605ED250F004FEEDA /* localkey.cpp */, + ); + name = Local; + sourceTree = ""; + }; + C28AE80706CD7D2700BE0061 /* Keychain */ = { + isa = PBXGroup; + children = ( + C2B8DBCA05E6C3CE00E6E67C /* kcdatabase.h */, + C2B8DBC905E6C3CE00E6E67C /* kcdatabase.cpp */, + C207646405EAD713004FEEDA /* kckey.h */, + C207646305EAD713004FEEDA /* kckey.cpp */, + ); + name = Keychain; + sourceTree = ""; + }; + C28AE81106CD7D7800BE0061 /* Authorization */ = { + isa = PBXGroup; + children = ( + 40689F840725DCE00021A502 /* authhost.h */, + 40689F850725DCE00021A502 /* authhost.cpp */, + 4C92649F0534866F004B0E72 /* authority.h */, + 4C92649E0534866F004B0E72 /* authority.cpp */, + 407ACD060AE5B57700A9DA90 /* credential.h */, + 407ACD070AE5B57700A9DA90 /* credential.cpp */, + 4C9264A10534866F004B0E72 /* AuthorizationDBPlist.h */, + 4C9264A00534866F004B0E72 /* AuthorizationDBPlist.cpp */, + 4C9264A30534866F004B0E72 /* AuthorizationEngine.h */, + 4C9264A20534866F004B0E72 /* AuthorizationEngine.cpp */, + 405845660663B2010083E58C /* AuthorizationMechEval.h */, + 405845650663B2010083E58C /* AuthorizationMechEval.cpp */, + 4C9264A50534866F004B0E72 /* AuthorizationRule.h */, + 4C9264A40534866F004B0E72 /* AuthorizationRule.cpp */, + ); + name = Authorization; + sourceTree = ""; + }; + C28AE81406CD7DA100BE0061 /* Core Structure */ = { + isa = PBXGroup; + children = ( + 4C9264AB0534866F004B0E72 /* connection.h */, + 4C9264AA0534866F004B0E72 /* connection.cpp */, + C2B8DBC805E6C3CE00E6E67C /* database.h */, + C2B8DBC705E6C3CE00E6E67C /* database.cpp */, + 4C9264B60534866F004B0E72 /* key.h */, + 4C9264B50534866F004B0E72 /* key.cpp */, + 4C9264BB0534866F004B0E72 /* process.h */, + 4C9264BA0534866F004B0E72 /* process.cpp */, + 4C9264BF0534866F004B0E72 /* server.h */, + 4C9264BE0534866F004B0E72 /* server.cpp */, + 4C9264C10534866F004B0E72 /* session.h */, + 4C9264C00534866F004B0E72 /* session.cpp */, + C28ACF9B05C9940B00447176 /* structure.h */, + C28ACF9A05C9940B00447176 /* structure.cpp */, + ); + name = "Core Structure"; + sourceTree = ""; + }; + C28AE81706CD7DC500BE0061 /* Database Types */ = { + isa = PBXGroup; + children = ( + C28AE80406CD7D1D00BE0061 /* Local */, + C28AE80706CD7D2700BE0061 /* Keychain */, + C28AE80106CD7D0E00BE0061 /* Temporary */, + C28AE7FE06CD7CFF00BE0061 /* Token */, + ); + name = "Database Types"; + sourceTree = ""; + }; + C28AE81A06CD7DE200BE0061 /* Smartcards */ = { + isa = PBXGroup; + children = ( + C2FDCABE0663CD5B0013F64C /* pcscmonitor.h */, + C2FDCABD0663CD5B0013F64C /* pcscmonitor.cpp */, + C2FDCAC00663CD5B0013F64C /* reader.h */, + C2FDCABF0663CD5B0013F64C /* reader.cpp */, + C2FDCAC20663CD5B0013F64C /* token.h */, + C2FDCAC10663CD5B0013F64C /* token.cpp */, + C22A7F8D06AF06D9006087B7 /* tokend.h */, + C22A7F8C06AF06D9006087B7 /* tokend.cpp */, + C26EA9520688CF34007CE21D /* tokencache.h */, + C26EA9510688CF34007CE21D /* tokencache.cpp */, + ); + name = Smartcards; + sourceTree = ""; + }; + C28AE82006CD7DF500BE0061 /* Build Stuff */ = { + isa = PBXGroup; + children = ( + 4C9264BC0534866F004B0E72 /* securityd.order */, + ); + name = "Build Stuff"; + path = src; + sourceTree = ""; + }; + C28AE82306CD7E0F00BE0061 /* Transit */ = { + isa = PBXGroup; + children = ( + 4C9264C20534866F004B0E72 /* transition.cpp */, + ); + name = Transit; + sourceTree = ""; + }; + C28AE82606CD7E4700BE0061 /* ACLs */ = { + isa = PBXGroup; + children = ( + 4C92649B0534866F004B0E72 /* acls.h */, + 4C92649A0534866F004B0E72 /* acls.cpp */, + C28654B106DBC2A30021E6E5 /* tokenacl.h */, + C28654B006DBC2A30021E6E5 /* tokenacl.cpp */, + 4C9264990534866F004B0E72 /* acl_keychain.h */, + 4C9264980534866F004B0E72 /* acl_keychain.cpp */, + ); + name = ACLs; + sourceTree = ""; + }; + C28AE83906CD7EE900BE0061 /* Support */ = { + isa = PBXGroup; + children = ( + 4C92649D0534866F004B0E72 /* agentquery.h */, + 4C92649C0534866F004B0E72 /* agentquery.cpp */, + 4CB5ACBA06680AE000F359A9 /* child.h */, + 4CB5ACB906680AE000F359A9 /* child.cpp */, + 4C9264AF0534866F004B0E72 /* entropy.h */, + 4C9264AE0534866F004B0E72 /* entropy.cpp */, + 4C9264B90534866F004B0E72 /* notifications.h */, + 4C9264B80534866F004B0E72 /* notifications.cpp */, + C22C344D0B278E770009368E /* osxcodewrap.h */, + C22C344C0B278E770009368E /* osxcodewrap.cpp */, + D6C887EE0A55B6220044DFD2 /* SharedMemoryServer.h */, + D6C887ED0A55B6220044DFD2 /* SharedMemoryServer.cpp */, + ); + name = Support; + sourceTree = ""; + }; + C2C8B29806F8A60F000EBDA2 /* Crypto */ = { + isa = PBXGroup; + children = ( + 4C9264AD0534866F004B0E72 /* dbcrypto.h */, + 4C9264AC0534866F004B0E72 /* dbcrypto.cpp */, + ); + name = Crypto; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 4CA1FEB1052A3C6D00F22E42 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 4C9264C90534866F004B0E72 /* acl_keychain.h in Headers */, + 4C9264CB0534866F004B0E72 /* acls.h in Headers */, + 4C9264CD0534866F004B0E72 /* agentquery.h in Headers */, + 4C9264CF0534866F004B0E72 /* authority.h in Headers */, + 4C9264D10534866F004B0E72 /* AuthorizationDBPlist.h in Headers */, + 4C9264D30534866F004B0E72 /* AuthorizationEngine.h in Headers */, + 405845680663B2010083E58C /* AuthorizationMechEval.h in Headers */, + 4C9264D50534866F004B0E72 /* AuthorizationRule.h in Headers */, + 4CB5ACBC06680AE000F359A9 /* child.h in Headers */, + 4C9264D90534866F004B0E72 /* codesigdb.h in Headers */, + 4C9264DB0534866F004B0E72 /* connection.h in Headers */, + C2B8DBCC05E6C3CE00E6E67C /* database.h in Headers */, + 4C9264DD0534866F004B0E72 /* dbcrypto.h in Headers */, + 4C9264DF0534866F004B0E72 /* entropy.h in Headers */, + C2B8DBCE05E6C3CE00E6E67C /* kcdatabase.h in Headers */, + C207646605EAD713004FEEDA /* kckey.h in Headers */, + 4C9264E30534866F004B0E72 /* key.h in Headers */, + C20764E905ED250F004FEEDA /* localdatabase.h in Headers */, + C20764EB05ED250F004FEEDA /* localkey.h in Headers */, + 4C9264E60534866F004B0E72 /* notifications.h in Headers */, + C2FDCAC60663CD5B0013F64C /* pcscmonitor.h in Headers */, + 4C9264E80534866F004B0E72 /* process.h in Headers */, + C2FDCAC80663CD5B0013F64C /* reader.h in Headers */, + 4C9264EB0534866F004B0E72 /* server.h in Headers */, + 4C9264ED0534866F004B0E72 /* session.h in Headers */, + C28ACF9D05C9940B00447176 /* structure.h in Headers */, + C20AF37F05F689540055732C /* tempdatabase.h in Headers */, + C2FDCACA0663CD5B0013F64C /* token.h in Headers */, + C2D425F405F3C07400CB11F8 /* tokendatabase.h in Headers */, + C26EA9540688CF34007CE21D /* tokencache.h in Headers */, + C209B3B506ADBE64007B9E6D /* self.h in Headers */, + C22A7F8F06AF06D9006087B7 /* tokend.h in Headers */, + C26D533A06C1E70A00062E1E /* tokenkey.h in Headers */, + C28654B306DBC2A30021E6E5 /* tokenacl.h in Headers */, + C2813C820730534A00E243E8 /* tokenaccess.h in Headers */, + 40689F860725DCE00021A502 /* authhost.h in Headers */, + D6C887F10A55B6220044DFD2 /* SharedMemoryServer.h in Headers */, + C2BD5FDD0AC47E850057FD3D /* csproxy.h in Headers */, + 407ACD080AE5B57700A9DA90 /* credential.h in Headers */, + C22C344F0B278E770009368E /* osxcodewrap.h in Headers */, + C22C34550B278EB60009368E /* clientid.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXLegacyTarget section */ + 4CA4EB2C0558848900CF7791 /* startup */ = { + isa = PBXLegacyTarget; + buildArgumentsString = "-f $(SRCROOT)/etc/startup.mk $(ACTION)"; + buildConfigurationList = C27AD4A30987FCF4001272E0 /* Build configuration list for PBXLegacyTarget "startup" */; + buildPhases = ( + ); + buildToolPath = /usr/bin/gnumake; + buildWorkingDirectory = ""; + dependencies = ( + ); + name = startup; + passBuildSettingsInEnvironment = 1; + productName = startup; + }; +/* End PBXLegacyTarget section */ + +/* Begin PBXProject section */ + 4CA1FEB0052A3C5800F22E42 /* Project object */ = { + isa = PBXProject; + buildConfigurationList = C27AD4AD0987FCF4001272E0 /* Build configuration list for PBXProject "securityd" */; + compatibilityVersion = "Xcode 2.4"; + hasScannedForEncodings = 1; + mainGroup = 4CA1FEAC052A3C5800F22E42; + productRefGroup = 4CA1FEB7052A3C6D00F22E42 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 4CA1FEB5052A3C6D00F22E42 /* securityd */, + 4CA4EB2C0558848900CF7791 /* startup */, + C209B3A506ADBCAC007B9E6D /* mig */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXShellScriptBuildPhase section */ + C209B3A406ADBCAC007B9E6D /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/bash; + shellScript = "make -f mig/mig.mk\n"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 4CA1FEB2052A3C6D00F22E42 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4C9264C80534866F004B0E72 /* acl_keychain.cpp in Sources */, + 4C9264CA0534866F004B0E72 /* acls.cpp in Sources */, + 4C9264CC0534866F004B0E72 /* agentquery.cpp in Sources */, + 4C9264CE0534866F004B0E72 /* authority.cpp in Sources */, + 4C9264D00534866F004B0E72 /* AuthorizationDBPlist.cpp in Sources */, + 4C9264D20534866F004B0E72 /* AuthorizationEngine.cpp in Sources */, + 405845670663B2010083E58C /* AuthorizationMechEval.cpp in Sources */, + 4C9264D40534866F004B0E72 /* AuthorizationRule.cpp in Sources */, + 4CB5ACBB06680AE000F359A9 /* child.cpp in Sources */, + 4C9264D80534866F004B0E72 /* codesigdb.cpp in Sources */, + 4C9264DA0534866F004B0E72 /* connection.cpp in Sources */, + C2B8DBCB05E6C3CE00E6E67C /* database.cpp in Sources */, + 4C9264DC0534866F004B0E72 /* dbcrypto.cpp in Sources */, + 4C9264DE0534866F004B0E72 /* entropy.cpp in Sources */, + C2B8DBCD05E6C3CE00E6E67C /* kcdatabase.cpp in Sources */, + C207646505EAD713004FEEDA /* kckey.cpp in Sources */, + 4C9264E20534866F004B0E72 /* key.cpp in Sources */, + C20764E805ED250F004FEEDA /* localdatabase.cpp in Sources */, + C20764EA05ED250F004FEEDA /* localkey.cpp in Sources */, + 4C9264E40534866F004B0E72 /* main.cpp in Sources */, + 4C9264E50534866F004B0E72 /* notifications.cpp in Sources */, + C2FDCAC50663CD5B0013F64C /* pcscmonitor.cpp in Sources */, + 4C9264E70534866F004B0E72 /* process.cpp in Sources */, + C2FDCAC70663CD5B0013F64C /* reader.cpp in Sources */, + 4C9264EA0534866F004B0E72 /* server.cpp in Sources */, + 4C9264EC0534866F004B0E72 /* session.cpp in Sources */, + C28ACF9C05C9940B00447176 /* structure.cpp in Sources */, + C20AF37E05F689540055732C /* tempdatabase.cpp in Sources */, + C2FDCAC90663CD5B0013F64C /* token.cpp in Sources */, + C2D425F305F3C07400CB11F8 /* tokendatabase.cpp in Sources */, + 4C9264EE0534866F004B0E72 /* transition.cpp in Sources */, + C26EA9530688CF34007CE21D /* tokencache.cpp in Sources */, + C209B3B606ADBE64007B9E6D /* selfServer.cpp in Sources */, + C209B3B706ADBE64007B9E6D /* selfUser.cpp in Sources */, + C22A7F8E06AF06D9006087B7 /* tokend.cpp in Sources */, + C26D533906C1E70A00062E1E /* tokenkey.cpp in Sources */, + C28654B206DBC2A30021E6E5 /* tokenacl.cpp in Sources */, + C2813C810730534A00E243E8 /* tokenaccess.cpp in Sources */, + 40689F870725DCE00021A502 /* authhost.cpp in Sources */, + D6C887F00A55B6220044DFD2 /* SharedMemoryServer.cpp in Sources */, + C2BD5FDC0AC47E850057FD3D /* csproxy.cpp in Sources */, + 407ACD090AE5B57700A9DA90 /* credential.cpp in Sources */, + C22C344E0B278E770009368E /* osxcodewrap.cpp in Sources */, + C22C34540B278EB60009368E /* clientid.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 4CD8CCB6055884BD006B3584 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4CA4EB2C0558848900CF7791 /* startup */; + targetProxy = 4CD8CCB5055884BD006B3584 /* PBXContainerItemProxy */; + }; + C209B3AA06ADBD6D007B9E6D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = C209B3A506ADBCAC007B9E6D /* mig */; + targetProxy = C209B3A906ADBD6D007B9E6D /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXToolTarget section */ + 4CA1FEB5052A3C6D00F22E42 /* securityd */ = { + isa = PBXToolTarget; + buildConfigurationList = C27AD4A80987FCF4001272E0 /* Build configuration list for PBXToolTarget "securityd" */; + buildPhases = ( + 4CA1FEB1052A3C6D00F22E42 /* Headers */, + 4CA1FEB2052A3C6D00F22E42 /* Sources */, + 4CA1FEB3052A3C6D00F22E42 /* Frameworks */, + 4C01B3D706FFC621004B3A01 /* CopyFiles */, + ); + dependencies = ( + C209B3AA06ADBD6D007B9E6D /* PBXTargetDependency */, + 4CD8CCB6055884BD006B3584 /* PBXTargetDependency */, + ); + name = securityd; + productInstallPath = /usr/sbin; + productName = securityd; + productReference = 4CA1FEB6052A3C6D00F22E42 /* securityd */; + }; +/* End PBXToolTarget section */ + +/* Begin XCBuildConfiguration section */ + C27AD49A0987FCF4001272E0 /* Development */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUILD_VARIANTS = debug; + COPY_PHASE_STRIP = NO; + CSSM_HEADERS = "$(BUILT_PRODUCTS_DIR)/Security.framework/Headers:$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Headers"; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ""; + OTHER_REZFLAGS = ""; + PRODUCT_NAME = generate; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = ( + "-Wmost", + "-Wno-four-char-constants", + "-Wno-unknown-pragmas", + ); + ZERO_LINK = YES; + }; + name = Development; + }; + C27AD49B0987FCF4001272E0 /* Deployment */ = { + isa = XCBuildConfiguration; + buildSettings = { + CSSM_HEADERS = "$(BUILT_PRODUCTS_DIR)/Security.framework/Headers:$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Headers"; + DEAD_CODE_STRIPPING = YES; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ""; + OTHER_REZFLAGS = ""; + PRODUCT_NAME = generate; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = ( + "-Wmost", + "-Wno-four-char-constants", + "-Wno-unknown-pragmas", + ); + ZERO_LINK = NO; + }; + name = Deployment; + }; + C27AD49C0987FCF4001272E0 /* normal with debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUILD_VARIANTS = normal; + COPY_PHASE_STRIP = NO; + OPT_LDFLAGS = ""; + OPT_LDXFLAGS = ""; + OPT_LDXNOPIC = ""; + OTHER_CFLAGS = ""; + OTHER_CFLAGS_normal = "$(OTHER_CFLAGS) -O1 -fno-inline"; + OTHER_CPLUSPLUSFLAGS_normal = "$(OTHER_CPLUSPLUSFLAGS) -O1 -fno-inline"; + OTHER_LDFLAGS = ""; + OTHER_REZFLAGS = ""; + PRODUCT_NAME = generate; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = ( + "-Wmost", + "-Wno-four-char-constants", + "-Wno-unknown-pragmas", + ); + }; + name = "normal with debug"; + }; + C27AD49D0987FCF4001272E0 /* Default */ = { + isa = XCBuildConfiguration; + buildSettings = { + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ""; + OTHER_REZFLAGS = ""; + PRODUCT_NAME = generate; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = ( + "-Wmost", + "-Wno-four-char-constants", + "-Wno-unknown-pragmas", + ); + }; + name = Default; + }; + C27AD4A40987FCF4001272E0 /* Development */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUILD_VARIANTS = debug; + COPY_PHASE_STRIP = NO; + CSSM_HEADERS = "$(BUILT_PRODUCTS_DIR)/Security.framework/Headers:$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Headers"; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ""; + OTHER_REZFLAGS = ""; + PRODUCT_NAME = startup; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = ( + "-Wmost", + "-Wno-four-char-constants", + "-Wno-unknown-pragmas", + ); + ZERO_LINK = YES; + }; + name = Development; + }; + C27AD4A50987FCF4001272E0 /* Deployment */ = { + isa = XCBuildConfiguration; + buildSettings = { + CSSM_HEADERS = "$(BUILT_PRODUCTS_DIR)/Security.framework/Headers:$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Headers"; + DEAD_CODE_STRIPPING = YES; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ""; + OTHER_REZFLAGS = ""; + PRODUCT_NAME = startup; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = ( + "-Wmost", + "-Wno-four-char-constants", + "-Wno-unknown-pragmas", + ); + ZERO_LINK = NO; + }; + name = Deployment; + }; + C27AD4A60987FCF4001272E0 /* normal with debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUILD_VARIANTS = normal; + COPY_PHASE_STRIP = NO; + OPT_LDFLAGS = ""; + OPT_LDXFLAGS = ""; + OPT_LDXNOPIC = ""; + OTHER_CFLAGS = ""; + OTHER_CFLAGS_normal = "$(OTHER_CFLAGS) -O1 -fno-inline"; + OTHER_CPLUSPLUSFLAGS_normal = "$(OTHER_CPLUSPLUSFLAGS) -O1 -fno-inline"; + OTHER_LDFLAGS = ""; + OTHER_REZFLAGS = ""; + PRODUCT_NAME = startup; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = ( + "-Wmost", + "-Wno-four-char-constants", + "-Wno-unknown-pragmas", + ); + }; + name = "normal with debug"; + }; + C27AD4A70987FCF4001272E0 /* Default */ = { + isa = XCBuildConfiguration; + buildSettings = { + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ""; + OTHER_REZFLAGS = ""; + PRODUCT_NAME = startup; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = ( + "-Wmost", + "-Wno-four-char-constants", + "-Wno-unknown-pragmas", + ); + }; + name = Default; + }; + C27AD4A90987FCF4001272E0 /* Development */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUILD_VARIANTS = debug; + COPY_PHASE_STRIP = NO; + CSSM_HEADERS = "$(BUILT_PRODUCTS_DIR)/Security.framework/Headers:$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Headers"; + CURRENT_PROJECT_VERSION = 32661; + FRAMEWORK_SEARCH_PATHS = ( + /usr/local/SecurityPieces/Frameworks, + /usr/local/SecurityPieces/Components/securityd, + /usr/local/SecurityPieces/Components/Security, + "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + INSTALL_PATH = /usr/sbin; + OPTIMIZATION_CFLAGS = "-O0"; + OPT_CPPXFLAGS = "$(OPT_CXFLAGS)"; + OPT_CXFLAGS = "-DNDEBUG $(OPT_INLINEXFLAGS)"; + OPT_INLINEXFLAGS = "-finline-functions"; + OPT_LDXFLAGS = "-dead_strip"; + OPT_LDXNOPIC = ",_nopic"; + OTHER_ASFLAGS_debug = "$(OTHER_CFLAGS)"; + OTHER_ASFLAGS_normal = "-DNDEBUG $(OTHER_CFLAGS)"; + OTHER_ASFLAGS_profile = "-DNDEBUG $(OTHER_CFLAGS) -pg"; + OTHER_CFLAGS_debug = "$(OTHER_CFLAGS) -fno-inline"; + OTHER_CFLAGS_normal = "$(OPT_CXFLAGS) $(OTHER_CFLAGS)"; + OTHER_CFLAGS_profile = "$(OPT_CXFLAGS) $(OTHER_CFLAGS) -pg"; + OTHER_CPLUSPLUSFLAGS_debug = "$(OTHER_CPLUSPLUSFLAGS) -fno-inline"; + OTHER_CPLUSPLUSFLAGS_normal = "$(OPT_CPPXFLAGS) $(OTHER_CPLUSPLUSFLAGS)"; + OTHER_CPLUSPLUSFLAGS_profile = "$(OPT_CPPXFLAGS) $(OTHER_CPLUSPLUSFLAGS) -pg"; + OTHER_LDFLAGS = ( + "-lbsm", + "-exported_symbols_list", + "$(SRCROOT)/src/securityd.exp", + ); + OTHER_LDFLAGS_debug = "$(OTHER_LDFLAGS) \"-framework\" \"Security,_debug\" \"-framework\" \"PCSC,_debug\" \"-framework\" \"IOKit\" \"-framework\" \"CoreFoundation\" \"-framework\" \"security_agent_client,_debug\" \"-framework\" \"security_tokend_client,_debug\" \"-framework\" \"security_cdsa_client,_debug\" \"-framework\" \"securityd_server,_debug\" \"-framework\" \"securityd_client,_debug\" \"-framework\" \"security_cdsa_utilities,_debug\" \"-framework\" \"security_utilities,_debug\" \"-framework\" \"security_codesigning,_debug\""; + OTHER_LDFLAGS_normal = "$(OPT_LDXFLAGS) $(OTHER_LDFLAGS) \"-framework\" \"Security\" \"-framework\" \"PCSC\" \"-framework\" \"IOKit\" \"-framework\" \"CoreFoundation\" \"-framework\" \"security_agent_client$(OPT_LDXNOPIC)\" \"-framework\" \"security_tokend_client$(OPT_LDXNOPIC)\" \"-framework\" \"security_cdsa_client$(OPT_LDXNOPIC)\" \"-framework\" \"securityd_server$(OPT_LDXNOPIC)\" \"-framework\" \"securityd_client$(OPT_LDXNOPIC)\" \"-framework\" \"security_cdsa_utilities$(OPT_LDXNOPIC)\" \"-framework\" \"security_utilities$(OPT_LDXNOPIC)\""; + OTHER_LDFLAGS_profile = "$(OPT_LDXFLAGS) $(OTHER_LDFLAGS) -pg \"-framework\" \"Security,_profile\" \"-framework\" \"PCSC,_profile\" \"-framework\" \"IOKit\" \"-framework\" \"CoreFoundation\" \"-framework\" \"security_agent_client,_profile\" \"-framework\" \"security_tokend_client,_profile\" \"-framework\" \"security_cdsa_client,_profile\" \"-framework\" \"securityd_server,_profile\" \"-framework\" \"securityd_client,_profile\" \"-framework\" \"security_cdsa_utilities,_profile\" \"-framework\" \"security_utilities,_profile\""; + PRODUCT_NAME = securityd; + SECTORDER_FLAGS = ( + "-sectorder", + __TEXT, + __text, + src/securityd.order, + "-e", + start, + ); + VERSIONING_SYSTEM = "apple-generic"; + WARNING_CFLAGS = ( + "-Wmost", + "-Wno-four-char-constants", + "-Wno-unknown-pragmas", + ); + ZERO_LINK = YES; + }; + name = Development; + }; + C27AD4AA0987FCF4001272E0 /* Deployment */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUILD_VARIANTS = ( + normal, + debug, + ); + CSSM_HEADERS = "$(BUILT_PRODUCTS_DIR)/Security.framework/Headers:$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Headers"; + CURRENT_PROJECT_VERSION = 32661; + DEAD_CODE_STRIPPING = YES; + EXPORTED_SYMBOLS_FILE = "$(SRCROOT)/src/securityd.exp"; + FRAMEWORK_SEARCH_PATHS = ( + /usr/local/SecurityPieces/Frameworks, + /usr/local/SecurityPieces/Components/securityd, + /usr/local/SecurityPieces/Components/Security, + "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + INSTALL_PATH = /usr/sbin; + OPT_CPPXFLAGS = "$(OPT_CXFLAGS)"; + OPT_CXFLAGS = "-DNDEBUG $(OPT_INLINEXFLAGS)"; + OPT_INLINEXFLAGS = "-finline-functions"; + OPT_LDXFLAGS = "-dead_strip"; + OPT_LDXNOPIC = ",_nopic"; + OTHER_ASFLAGS_debug = "$(OTHER_CFLAGS)"; + OTHER_ASFLAGS_normal = "-DNDEBUG $(OTHER_CFLAGS)"; + OTHER_ASFLAGS_profile = "-DNDEBUG $(OTHER_CFLAGS) -pg"; + OTHER_CFLAGS_debug = "$(OTHER_CFLAGS) -O1 -fno-inline"; + OTHER_CFLAGS_normal = "$(OPT_CXFLAGS) $(OTHER_CFLAGS)"; + OTHER_CFLAGS_profile = "$(OPT_CXFLAGS) $(OTHER_CFLAGS) -pg"; + OTHER_CPLUSPLUSFLAGS_debug = "$(OTHER_CPLUSPLUSFLAGS) -O1 -fno-inline"; + OTHER_CPLUSPLUSFLAGS_normal = "$(OPT_CPPXFLAGS) $(OTHER_CPLUSPLUSFLAGS)"; + OTHER_CPLUSPLUSFLAGS_profile = "$(OPT_CPPXFLAGS) $(OTHER_CPLUSPLUSFLAGS) -pg"; + OTHER_LDFLAGS = ( + "-lbsm", + "-exported_symbols_list", + "$(SRCROOT)/src/securityd.exp", + ); + OTHER_LDFLAGS_debug = "$(OTHER_LDFLAGS) \"-framework\" \"Security,_debug\" \"-framework\" \"PCSC,_debug\" \"-framework\" \"IOKit\" \"-framework\" \"CoreFoundation\" \"-framework\" \"security_agent_client,_debug\" \"-framework\" \"security_tokend_client,_debug\" \"-framework\" \"security_cdsa_client,_debug\" \"-framework\" \"securityd_server,_debug\" \"-framework\" \"securityd_client,_debug\" \"-framework\" \"security_cdsa_utilities,_debug\" \"-framework\" \"security_utilities,_debug\" \"-framework\" \"security_codesigning,_debug\""; + OTHER_LDFLAGS_normal = "$(OPT_LDXFLAGS) $(OTHER_LDFLAGS) \"-framework\" \"Security\" \"-framework\" \"PCSC\" \"-framework\" \"IOKit\" \"-framework\" \"CoreFoundation\" \"-framework\" \"security_agent_client$(OPT_LDXNOPIC)\" \"-framework\" \"security_tokend_client$(OPT_LDXNOPIC)\" \"-framework\" \"security_cdsa_client$(OPT_LDXNOPIC)\" \"-framework\" \"securityd_server$(OPT_LDXNOPIC)\" \"-framework\" \"securityd_client$(OPT_LDXNOPIC)\" \"-framework\" \"security_cdsa_utilities$(OPT_LDXNOPIC)\" \"-framework\" \"security_utilities$(OPT_LDXNOPIC)\""; + OTHER_LDFLAGS_profile = "$(OPT_LDXFLAGS) $(OTHER_LDFLAGS) -pg \"-framework\" \"Security,_profile\" \"-framework\" \"PCSC,_profile\" \"-framework\" \"IOKit\" \"-framework\" \"CoreFoundation\" \"-framework\" \"security_agent_client,_profile\" \"-framework\" \"security_tokend_client,_profile\" \"-framework\" \"security_cdsa_client,_profile\" \"-framework\" \"securityd_server,_profile\" \"-framework\" \"securityd_client,_profile\" \"-framework\" \"security_cdsa_utilities,_profile\" \"-framework\" \"security_utilities,_profile\""; + PRODUCT_NAME = securityd; + SECTORDER_FLAGS = ( + "-sectorder", + __TEXT, + __text, + src/securityd.order, + "-e", + start, + ); + VERSIONING_SYSTEM = "apple-generic"; + WARNING_CFLAGS = ( + "-Wmost", + "-Wno-four-char-constants", + "-Wno-unknown-pragmas", + ); + ZERO_LINK = NO; + }; + name = Deployment; + }; + C27AD4AB0987FCF4001272E0 /* normal with debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUILD_VARIANTS = normal; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 32661; + EXPORTED_SYMBOLS_FILE = "$(SRCROOT)/src/securityd.exp"; + FRAMEWORK_SEARCH_PATHS = ( + /usr/local/SecurityPieces/Frameworks, + /usr/local/SecurityPieces/Components/securityd, + /usr/local/SecurityPieces/Components/Security, + "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); + INSTALL_PATH = /usr/sbin; + OPT_CPPXFLAGS = "$(OPT_CXFLAGS)"; + OPT_CXFLAGS = "-DNDEBUG $(OPT_INLINEXFLAGS)"; + OPT_INLINEXFLAGS = "-finline-functions"; + OPT_LDFLAGS = ""; + OPT_LDXFLAGS = ""; + OPT_LDXNOPIC = ""; + OTHER_ASFLAGS_debug = "$(OTHER_CFLAGS)"; + OTHER_ASFLAGS_normal = "-DNDEBUG $(OTHER_CFLAGS)"; + OTHER_ASFLAGS_profile = "-DNDEBUG $(OTHER_CFLAGS) -pg"; + OTHER_CFLAGS_debug = "$(OTHER_CFLAGS) -O1 -fno-inline"; + OTHER_CFLAGS_normal = "$(OTHER_CFLAGS) -O1 -fno-inline"; + OTHER_CFLAGS_profile = "$(OPT_CXFLAGS) $(OTHER_CFLAGS) -pg"; + OTHER_CPLUSPLUSFLAGS_debug = "$(OTHER_CPLUSPLUSFLAGS) -O1 -fno-inline"; + OTHER_CPLUSPLUSFLAGS_normal = "$(OTHER_CPLUSPLUSFLAGS) -O1 -fno-inline"; + OTHER_CPLUSPLUSFLAGS_profile = "$(OPT_CPPXFLAGS) $(OTHER_CPLUSPLUSFLAGS) -pg"; + OTHER_LDFLAGS = ( + "-lbsm", + "-exported_symbols_list", + "$(SRCROOT)/src/securityd.exp", + ); + OTHER_LDFLAGS_debug = "$(OTHER_LDFLAGS) \"-framework\" \"Security,_debug\" \"-framework\" \"PCSC,_debug\" \"-framework\" \"IOKit\" \"-framework\" \"CoreFoundation\" \"-framework\" \"security_agent_client,_debug\" \"-framework\" \"security_tokend_client,_debug\" \"-framework\" \"security_cdsa_client,_debug\" \"-framework\" \"securityd_server,_debug\" \"-framework\" \"securityd_client,_debug\" \"-framework\" \"security_cdsa_utilities,_debug\" \"-framework\" \"security_utilities,_debug\" \"-framework\" \"security_codesigning,_debug\""; + OTHER_LDFLAGS_normal = "$(OPT_LDXFLAGS) $(OTHER_LDFLAGS) \"-framework\" \"Security\" \"-framework\" \"PCSC\" \"-framework\" \"IOKit\" \"-framework\" \"CoreFoundation\" \"-framework\" \"security_agent_client$(OPT_LDXNOPIC)\" \"-framework\" \"security_tokend_client$(OPT_LDXNOPIC)\" \"-framework\" \"security_cdsa_client$(OPT_LDXNOPIC)\" \"-framework\" \"securityd_server$(OPT_LDXNOPIC)\" \"-framework\" \"securityd_client$(OPT_LDXNOPIC)\" \"-framework\" \"security_cdsa_utilities$(OPT_LDXNOPIC)\" \"-framework\" \"security_utilities$(OPT_LDXNOPIC)\""; + OTHER_LDFLAGS_profile = "$(OPT_LDXFLAGS) $(OTHER_LDFLAGS) -pg \"-framework\" \"Security,_profile\" \"-framework\" \"PCSC,_profile\" \"-framework\" \"IOKit\" \"-framework\" \"CoreFoundation\" \"-framework\" \"security_agent_client,_profile\" \"-framework\" \"security_tokend_client,_profile\" \"-framework\" \"security_cdsa_client,_profile\" \"-framework\" \"securityd_server,_profile\" \"-framework\" \"securityd_client,_profile\" \"-framework\" \"security_cdsa_utilities,_profile\" \"-framework\" \"security_utilities,_profile\""; + PRODUCT_NAME = securityd; + SECTORDER_FLAGS = ( + "-sectorder", + __TEXT, + __text, + src/securityd.order, + "-e", + start, + ); + VERSIONING_SYSTEM = "apple-generic"; + WARNING_CFLAGS = ( + "-Wmost", + "-Wno-four-char-constants", + "-Wno-unknown-pragmas", + ); + }; + name = "normal with debug"; + }; + C27AD4AC0987FCF4001272E0 /* Default */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUILD_VARIANTS = ( + normal, + debug, + ); + CURRENT_PROJECT_VERSION = 32661; + EXPORTED_SYMBOLS_FILE = "$(SRCROOT)/src/securityd.exp"; + FRAMEWORK_SEARCH_PATHS = ( + /usr/local/SecurityPieces/Frameworks, + /usr/local/SecurityPieces/Components/securityd, + /usr/local/SecurityPieces/Components/Security, + "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); + INSTALL_PATH = /usr/sbin; + OPT_CPPXFLAGS = "$(OPT_CXFLAGS)"; + OPT_CXFLAGS = "-DNDEBUG $(OPT_INLINEXFLAGS)"; + OPT_INLINEXFLAGS = "-finline-functions"; + OPT_LDXFLAGS = "-dead_strip"; + OPT_LDXNOPIC = ",_nopic"; + OTHER_ASFLAGS_debug = "$(OTHER_CFLAGS)"; + OTHER_ASFLAGS_normal = "-DNDEBUG $(OTHER_CFLAGS)"; + OTHER_ASFLAGS_profile = "-DNDEBUG $(OTHER_CFLAGS) -pg"; + OTHER_CFLAGS_debug = "$(OTHER_CFLAGS) -O1 -fno-inline"; + OTHER_CFLAGS_normal = "$(OPT_CXFLAGS) $(OTHER_CFLAGS)"; + OTHER_CFLAGS_profile = "$(OPT_CXFLAGS) $(OTHER_CFLAGS) -pg"; + OTHER_CPLUSPLUSFLAGS_debug = "$(OTHER_CPLUSPLUSFLAGS) -O1 -fno-inline"; + OTHER_CPLUSPLUSFLAGS_normal = "$(OPT_CPPXFLAGS) $(OTHER_CPLUSPLUSFLAGS)"; + OTHER_CPLUSPLUSFLAGS_profile = "$(OPT_CPPXFLAGS) $(OTHER_CPLUSPLUSFLAGS) -pg"; + OTHER_LDFLAGS = ( + "-lbsm", + "-exported_symbols_list", + "$(SRCROOT)/src/securityd.exp", + ); + OTHER_LDFLAGS_debug = "$(OTHER_LDFLAGS) \"-framework\" \"Security,_debug\" \"-framework\" \"PCSC,_debug\" \"-framework\" \"IOKit\" \"-framework\" \"CoreFoundation\" \"-framework\" \"security_agent_client,_debug\" \"-framework\" \"security_tokend_client,_debug\" \"-framework\" \"security_cdsa_client,_debug\" \"-framework\" \"securityd_server,_debug\" \"-framework\" \"securityd_client,_debug\" \"-framework\" \"security_cdsa_utilities,_debug\" \"-framework\" \"security_utilities,_debug\" \"-framework\" \"security_codesigning,_debug\""; + OTHER_LDFLAGS_normal = "$(OPT_LDXFLAGS) $(OTHER_LDFLAGS) \"-framework\" \"Security\" \"-framework\" \"PCSC\" \"-framework\" \"IOKit\" \"-framework\" \"CoreFoundation\" \"-framework\" \"security_agent_client$(OPT_LDXNOPIC)\" \"-framework\" \"security_tokend_client$(OPT_LDXNOPIC)\" \"-framework\" \"security_cdsa_client$(OPT_LDXNOPIC)\" \"-framework\" \"securityd_server$(OPT_LDXNOPIC)\" \"-framework\" \"securityd_client$(OPT_LDXNOPIC)\" \"-framework\" \"security_cdsa_utilities$(OPT_LDXNOPIC)\" \"-framework\" \"security_utilities$(OPT_LDXNOPIC)\""; + OTHER_LDFLAGS_profile = "$(OPT_LDXFLAGS) $(OTHER_LDFLAGS) -pg \"-framework\" \"Security,_profile\" \"-framework\" \"PCSC,_profile\" \"-framework\" \"IOKit\" \"-framework\" \"CoreFoundation\" \"-framework\" \"security_agent_client,_profile\" \"-framework\" \"security_tokend_client,_profile\" \"-framework\" \"security_cdsa_client,_profile\" \"-framework\" \"securityd_server,_profile\" \"-framework\" \"securityd_client,_profile\" \"-framework\" \"security_cdsa_utilities,_profile\" \"-framework\" \"security_utilities,_profile\""; + PRODUCT_NAME = securityd; + SECTORDER_FLAGS = ( + "-sectorder", + __TEXT, + __text, + src/securityd.order, + "-e", + start, + ); + VERSIONING_SYSTEM = "apple-generic"; + WARNING_CFLAGS = ( + "-Wmost", + "-Wno-four-char-constants", + "-Wno-unknown-pragmas", + ); + }; + name = Default; + }; + C27AD4AE0987FCF4001272E0 /* Development */ = { + isa = XCBuildConfiguration; + buildSettings = { + CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)"; + CONFIGURATION_TEMP_DIR = "$(PROJECT_TEMP_DIR)"; + HEADER_SEARCH_PATHS = ( + "$(BUILT_PRODUCTS_DIR)/SecurityPieces/Headers", + "$(BUILT_PRODUCTS_DIR)/SecurityPieces/PrivateHeaders", + ); + }; + name = Development; + }; + C27AD4AF0987FCF4001272E0 /* Deployment */ = { + isa = XCBuildConfiguration; + buildSettings = { + CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)"; + CONFIGURATION_TEMP_DIR = "$(PROJECT_TEMP_DIR)"; + }; + name = Deployment; + }; + C27AD4B00987FCF4001272E0 /* normal with debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)"; + CONFIGURATION_TEMP_DIR = "$(PROJECT_TEMP_DIR)"; + }; + name = "normal with debug"; + }; + C27AD4B10987FCF4001272E0 /* Default */ = { + isa = XCBuildConfiguration; + buildSettings = { + CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)"; + CONFIGURATION_TEMP_DIR = "$(PROJECT_TEMP_DIR)"; + }; + name = Default; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + C27AD4990987FCF4001272E0 /* Build configuration list for PBXAggregateTarget "mig" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD49A0987FCF4001272E0 /* Development */, + C27AD49B0987FCF4001272E0 /* Deployment */, + C27AD49C0987FCF4001272E0 /* normal with debug */, + C27AD49D0987FCF4001272E0 /* Default */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Default; + }; + C27AD4A30987FCF4001272E0 /* Build configuration list for PBXLegacyTarget "startup" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD4A40987FCF4001272E0 /* Development */, + C27AD4A50987FCF4001272E0 /* Deployment */, + C27AD4A60987FCF4001272E0 /* normal with debug */, + C27AD4A70987FCF4001272E0 /* Default */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Default; + }; + C27AD4A80987FCF4001272E0 /* Build configuration list for PBXToolTarget "securityd" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD4A90987FCF4001272E0 /* Development */, + C27AD4AA0987FCF4001272E0 /* Deployment */, + C27AD4AB0987FCF4001272E0 /* normal with debug */, + C27AD4AC0987FCF4001272E0 /* Default */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Default; + }; + C27AD4AD0987FCF4001272E0 /* Build configuration list for PBXProject "securityd" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD4AE0987FCF4001272E0 /* Development */, + C27AD4AF0987FCF4001272E0 /* Deployment */, + C27AD4B00987FCF4001272E0 /* normal with debug */, + C27AD4B10987FCF4001272E0 /* Default */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Default; + }; +/* End XCConfigurationList section */ + }; + rootObject = 4CA1FEB0052A3C5800F22E42 /* Project object */; +} diff --git a/src/AuthorizationDBPlist.cpp b/src/AuthorizationDBPlist.cpp index 29ae2cb..5d0bc6f 100644 --- a/src/AuthorizationDBPlist.cpp +++ b/src/AuthorizationDBPlist.cpp @@ -28,62 +28,65 @@ #include "AuthorizationDBPlist.h" #include +// mLock is held when the database is changed +// mReadWriteLock is held when the file on disk is changed +// during load(), save() and parseConfig() mLock is assumed -namespace Authorization -{ +namespace Authorization { -AuthorizationDBPlist::AuthorizationDBPlist(const char *configFile) : mFileName(configFile), mLastChecked(DBL_MIN) +AuthorizationDBPlist::AuthorizationDBPlist(const char *configFile) : + mFileName(configFile), mLastChecked(DBL_MIN) { memset(&mRulesFileMtimespec, 0, sizeof(mRulesFileMtimespec)); } void AuthorizationDBPlist::sync(CFAbsoluteTime now) { - if (mRules.empty()) - load(now); - else - { + if (mRules.empty()) { + StLock _(mLock); + load(); + } else { // Don't do anything if we checked the timestamp less than 5 seconds ago - if (mLastChecked > now - 5.0) + if (mLastChecked > now - 5.0) { + secdebug("authdb", "no sync: last reload %.0f + 5 > %.0f", + mLastChecked, now); return; - - struct stat st; - if (stat(mFileName.c_str(), &st)) - { - Syslog::error("Stating rules file \"%s\": %s", mFileName.c_str(), strerror(errno)); - /* @@@ No rules file found, use defaults: admin group for everything. */ - //UnixError::throwMe(errno); } - else + { - // @@@ Make sure this is the right way to compare 2 struct timespec thingies - // Technically we should check st_dev and st_ino as well since if either of those change - // we are looking at a different file too. - if (memcmp(&st.st_mtimespec, &mRulesFileMtimespec, sizeof(mRulesFileMtimespec))) - load(now); + struct stat st; + { + StLock _(mReadWriteLock); + if (stat(mFileName.c_str(), &st)) { + Syslog::error("Stating rules file \"%s\": %s", mFileName.c_str(), + strerror(errno)); + return; + } + } + + if (memcmp(&st.st_mtimespec, &mRulesFileMtimespec, sizeof(mRulesFileMtimespec))) { + StLock _(mLock); + load(); + } } } - - mLastChecked = now; } -void AuthorizationDBPlist::save() const +void AuthorizationDBPlist::save() { if (!mConfig) return; StLock _(mReadWriteLock); - + + secdebug("authdb", "policy db changed, saving to disk."); int fd = -1; string tempFile = mFileName + ","; - for (;;) - { + for (;;) { fd = open(tempFile.c_str(), O_WRONLY|O_CREAT|O_EXCL, 0644); - if (fd == -1) - { - if (errno == EEXIST) - { + if (fd == -1) { + if (errno == EEXIST) { unlink(tempFile.c_str()); continue; } @@ -91,35 +94,32 @@ void AuthorizationDBPlist::save() const continue; else break; - } - else + } else break; } - if (fd == -1) - { - Syslog::error("Saving rules file \"%s\": %s", tempFile.c_str(), strerror(errno)); + if (fd == -1) { + Syslog::error("Saving rules file \"%s\": %s", tempFile.c_str(), + strerror(errno)); return; } - // convert config to plist CFDataRef configXML = CFPropertyListCreateXMLData(NULL, mConfig); - if (!configXML) return; - // write out data - SInt32 configSize = CFDataGetLength(configXML); + CFIndex configSize = CFDataGetLength(configXML); size_t bytesWritten = write(fd, CFDataGetBytePtr(configXML), configSize); CFRelease(configXML); - if (bytesWritten != uint32_t(configSize)) - { + if (bytesWritten != configSize) { if (bytesWritten == static_cast(-1)) - Syslog::error("Writing rules file \"%s\": %s", tempFile.c_str(), strerror(errno)); + Syslog::error("Problem writing rules file \"%s\": (errno=%s)", + tempFile.c_str(), strerror(errno)); else - Syslog::error("Could only write %lu out of %ld bytes from rules file \"%s\"", - bytesWritten, configSize, tempFile.c_str()); + Syslog::error("Problem writing rules file \"%s\": " + "only wrote %lu out of %ld bytes", + tempFile.c_str(), bytesWritten, configSize); close(fd); unlink(tempFile.c_str()); @@ -129,49 +129,46 @@ void AuthorizationDBPlist::save() const close(fd); if (rename(tempFile.c_str(), mFileName.c_str())) unlink(tempFile.c_str()); + else + mLastChecked = CFAbsoluteTimeGetCurrent(); // we have the copy that's on disk now, so don't go loading it right away } - return; } -void AuthorizationDBPlist::load(CFTimeInterval now) +void AuthorizationDBPlist::load() { StLock _(mReadWriteLock); - + + secdebug("authdb", "(re)loading policy db from disk."); int fd = open(mFileName.c_str(), O_RDONLY, 0); - if (fd == -1) - { - Syslog::error("Opening rules file \"%s\": %s", mFileName.c_str(), strerror(errno)); + if (fd == -1) { + Syslog::error("Problem opening rules file \"%s\": %s", + mFileName.c_str(), strerror(errno)); return; } struct stat st; - if (fstat(fd, &st)) - { + if (fstat(fd, &st)) { int error = errno; close(fd); UnixError::throwMe(error); } - mRulesFileMtimespec = st.st_mtimespec; - off_t fileSize = st.st_size; - CFMutableDataRef xmlData = CFDataCreateMutable(NULL, fileSize); CFDataSetLength(xmlData, fileSize); void *buffer = CFDataGetMutableBytePtr(xmlData); size_t bytesRead = read(fd, buffer, fileSize); - if (bytesRead != fileSize) - { - if (bytesRead == static_cast(-1)) - { - Syslog::error("Reading rules file \"%s\": %s", mFileName.c_str(), strerror(errno)); + if (bytesRead != fileSize) { + if (bytesRead == static_cast(-1)) { + Syslog::error("Problem reading rules file \"%s\": %s", + mFileName.c_str(), strerror(errno)); CFRelease(xmlData); return; } - - Syslog::error("Could only read %ul out of %ul bytes from rules file \"%s\"", - bytesRead, fileSize, mFileName.c_str()); + Syslog::error("Problem reading rules file \"%s\": " + "only read %ul out of %ul bytes", + bytesRead, fileSize, mFileName.c_str()); CFRelease(xmlData); return; } @@ -179,17 +176,18 @@ void AuthorizationDBPlist::load(CFTimeInterval now) CFStringRef errorString; CFDictionaryRef configPlist = reinterpret_cast(CFPropertyListCreateFromXMLData(NULL, xmlData, kCFPropertyListMutableContainersAndLeaves, &errorString)); - if (!configPlist) - { + if (!configPlist) { char buffer[512]; - const char *error = CFStringGetCStringPtr(errorString, kCFStringEncodingUTF8); - if (error == NULL) - { - if (CFStringGetCString(errorString, buffer, 512, kCFStringEncodingUTF8)) + const char *error = CFStringGetCStringPtr(errorString, + kCFStringEncodingUTF8); + if (error == NULL) { + if (CFStringGetCString(errorString, buffer, 512, + kCFStringEncodingUTF8)) error = buffer; } - Syslog::error("Parsing rules file \"%s\": %s", mFileName.c_str(), error); + Syslog::error("Parsing rules file \"%s\": %s", + mFileName.c_str(), error); if (errorString) CFRelease(errorString); @@ -197,70 +195,58 @@ void AuthorizationDBPlist::load(CFTimeInterval now) return; } - if (CFGetTypeID(configPlist) != CFDictionaryGetTypeID()) - { + if (CFGetTypeID(configPlist) != CFDictionaryGetTypeID()) { - Syslog::error("Rules file \"%s\": is not a dictionary", mFileName.c_str()); + Syslog::error("Rules file \"%s\": is not a dictionary", + mFileName.c_str()); CFRelease(xmlData); CFRelease(configPlist); return; } - { - StLock _(mLock); - parseConfig(configPlist); - mLastChecked = now; - } + parseConfig(configPlist); + CFRelease(xmlData); CFRelease(configPlist); close(fd); -} - + // If all went well, we have the copy that's on disk now, so don't go loading it right away + mLastChecked = CFAbsoluteTimeGetCurrent(); +} -void -AuthorizationDBPlist::parseConfig(CFDictionaryRef config) +void AuthorizationDBPlist::parseConfig(CFDictionaryRef config) { - // grab items from top-level dictionary that we care about CFStringRef rightsKey = CFSTR("rights"); CFStringRef rulesKey = CFSTR("rules"); CFMutableDictionaryRef newRights = NULL; CFMutableDictionaryRef newRules = NULL; if (!config) - MacOSError::throwMe(errAuthorizationInternal); // XXX/cs invalid rule file + MacOSError::throwMe(errAuthorizationInternal); if (CFDictionaryContainsKey(config, rulesKey)) - { newRules = reinterpret_cast(const_cast(CFDictionaryGetValue(config, rulesKey))); - } if (CFDictionaryContainsKey(config, rightsKey)) - { newRights = reinterpret_cast(const_cast(CFDictionaryGetValue(config, rightsKey))); - } - if (newRules - && newRights + if (newRules && newRights && (CFDictionaryGetTypeID() == CFGetTypeID(newRules)) - && (CFDictionaryGetTypeID() == CFGetTypeID(newRights))) - { - mConfig = config; - mConfigRights = static_cast(newRights); - mConfigRules = static_cast(newRules); + && (CFDictionaryGetTypeID() == CFGetTypeID(newRights))) + { + mConfigRights = static_cast(newRights); + mConfigRules = static_cast(newRules); mRules.clear(); - try - { + try { CFDictionaryApplyFunction(newRights, parseRule, this); - } - catch (...) - { + } catch (...) { MacOSError::throwMe(errAuthorizationInternal); // XXX/cs invalid rule file } + mConfig = config; } - else + else MacOSError::throwMe(errAuthorizationInternal); // XXX/cs invalid rule file } @@ -282,10 +268,9 @@ AuthorizationDBPlist::validateRule(string inRightName, CFDictionaryRef inRightDe Rule newRule(inRightName, inRightDefinition, mConfigRules); if (newRule->name() == inRightName) return true; - } - catch (...) - { - secdebug("authrule", "invalid definition for rule %s.\n", inRightName.c_str()); + } catch (...) { + secdebug("authrule", "invalid definition for rule %s.\n", + inRightName.c_str()); } return false; } @@ -295,14 +280,11 @@ AuthorizationDBPlist::getRuleDefinition(string &key) { CFStringRef cfKey = makeCFString(key); StLock _(mLock); - if (CFDictionaryContainsKey(mConfigRights, cfKey)) - { + if (CFDictionaryContainsKey(mConfigRights, cfKey)) { CFDictionaryRef definition = reinterpret_cast(const_cast(CFDictionaryGetValue(mConfigRights, cfKey))); CFRelease(cfKey); return CFDictionaryCreateCopy(NULL, definition); - } - else - { + } else { CFRelease(cfKey); return NULL; } @@ -328,11 +310,11 @@ AuthorizationDBPlist::getRule(const AuthItemRef &inRight) const // Lock the rulemap StLock _(mLock); + secdebug("authdb", "looking up rule %s.", inRight->name()); if (mRules.empty()) return Rule(); - for (;;) - { + for (;;) { map::const_iterator rule = mRules.find(key); if (rule != mRules.end()) @@ -355,39 +337,42 @@ AuthorizationDBPlist::getRule(const AuthItemRef &inRight) const void AuthorizationDBPlist::setRule(const char *inRightName, CFDictionaryRef inRuleDefinition) { + // if mConfig is now a reasonable guard if (!inRuleDefinition || !mConfigRights) MacOSError::throwMe(errAuthorizationDenied); // errInvalidRule - CFRef keyRef(CFStringCreateWithCString(NULL, inRightName, kCFStringEncodingASCII)); + CFRef keyRef(CFStringCreateWithCString(NULL, inRightName, + kCFStringEncodingASCII)); if (!keyRef) return; - StLock _(mLock); - - CFDictionarySetValue(mConfigRights, keyRef, inRuleDefinition); - // release modification lock here already? - save(); - mLastChecked = 0.0; + { + StLock _(mLock); + secdebug("authdb", "setting up rule %s.", inRightName); + CFDictionarySetValue(mConfigRights, keyRef, inRuleDefinition); + save(); + parseConfig(mConfig); + } } void AuthorizationDBPlist::removeRule(const char *inRightName) { + // if mConfig is now a reasonable guard if (!mConfigRights) MacOSError::throwMe(errAuthorizationDenied); - CFRef keyRef(CFStringCreateWithCString(NULL, inRightName, kCFStringEncodingASCII)); + CFRef keyRef(CFStringCreateWithCString(NULL, inRightName, + kCFStringEncodingASCII)); if (!keyRef) return; - StLock _(mLock); - - if (CFDictionaryContainsKey(mConfigRights, keyRef)) { + StLock _(mLock); + secdebug("authdb", "removing rule %s.", inRightName); CFDictionaryRemoveValue(mConfigRights, keyRef); - // release modification lock here already? save(); - mLastChecked = 0.0; + parseConfig(mConfig); } } diff --git a/src/AuthorizationDBPlist.h b/src/AuthorizationDBPlist.h index 1a365c8..2c2a134 100644 --- a/src/AuthorizationDBPlist.h +++ b/src/AuthorizationDBPlist.h @@ -41,7 +41,7 @@ namespace Authorization class AuthorizationDBPlist /* : public AuthorizationDB */ { public: - AuthorizationDBPlist(const char *configFile = "/etc/authorization"); + AuthorizationDBPlist(const char *configFile); void sync(CFAbsoluteTime now); bool validateRule(string inRightName, CFDictionaryRef inRightDefinition) const; @@ -54,8 +54,8 @@ public: void removeRule(const char *inRightName); protected: - void load(CFTimeInterval now); - void save() const; + void load(); + void save(); private: string mFileName; diff --git a/src/AuthorizationEngine.cpp b/src/AuthorizationEngine.cpp index 0a41fd1..cd05764 100644 --- a/src/AuthorizationEngine.cpp +++ b/src/AuthorizationEngine.cpp @@ -21,14 +21,6 @@ * @APPLE_LICENSE_HEADER_END@ */ - -/* - * AuthorizationEngine.cpp - * Authorization - * - * Created by Michael Brouwer on Thu Oct 12 2000. - * - */ #include "AuthorizationEngine.h" #include #include @@ -53,6 +45,8 @@ #include #include +#include + namespace Authorization { @@ -131,8 +125,6 @@ Engine::authorize(const AuthItemSet &inRights, const AuthItemSet &environment, if (username.length()) { - // Call to checkpw in DS - Server::active().longTermActivity(); // Let's create a credential from the passed in username and password. Credential newCredential(username, password, shared); // If it's valid insert it into the credentials list. Normally this is @@ -155,15 +147,26 @@ Engine::authorize(const AuthItemSet &inRights, const AuthItemSet &environment, secdebug("autheval", "evaluate rule %s for right %s returned %ld.", toplevelRule->name().c_str(), (*it)->name(), result); { - RefPointer processCode = Server::process().clientCode(); - string processName = processCode ? processCode->canonicalPath() : "unknown"; - RefPointer authCreatorCode = auth.creatorCode(); - string authCreatorName = authCreatorCode ? authCreatorCode->canonicalPath() : "unknown"; - - if (result == errAuthorizationSuccess) - Syslog::info("Succeeded authorizing right %s by process %s for authorization created by %s.", (*it)->name(), processName.c_str(), authCreatorName.c_str()); - else if (result == errAuthorizationDenied) - Syslog::notice("Failed to authorize right %s by process %s for authorization created by %s.", (*it)->name(), processName.c_str(), authCreatorName.c_str()); + string processName = "unknown"; + if (SecCodeRef code = Server::process().currentGuest()) { + CFRef path; + if (!SecCodeCopyPath(code, kSecCSDefaultFlags, &path.aref())) + processName = cfString(path); + } + string authCreatorName = "unknown"; + if (SecStaticCodeRef code = auth.creatorCode()) { + CFRef path; + if (!SecCodeCopyPath(code, kSecCSDefaultFlags, &path.aref())) + authCreatorName = cfString(path); + } + + if (result == errAuthorizationSuccess) { + Syslog::info("Succeeded authorizing right %s by client %s for authorization created by %s.", (*it)->name(), processName.c_str(), authCreatorName.c_str()); + CommonCriteria::AuditRecord auditrec(auth.creatorAuditToken()); + auditrec.submit(AUE_ssauthorize, CommonCriteria::errNone, (*it)->name()); + } else if (result == errAuthorizationDenied) { + Syslog::notice("Failed to authorize right %s by client %s for authorization created by %s.", (*it)->name(), processName.c_str(), authCreatorName.c_str()); + } } if (result == errAuthorizationSuccess) @@ -287,12 +290,6 @@ Engine::getRule(string &inRightName, CFDictionaryRef *outRuleDefinition) OSStatus Engine::setRule(const char *inRightName, CFDictionaryRef inRuleDefinition, const CredentialSet *inCredentials, CredentialSet *outCredentials, AuthorizationToken &auth) { - // Get current time of day. - CFAbsoluteTime now = CFAbsoluteTimeGetCurrent(); - - // Update rules from database if needed - mAuthdb.sync(now); - // Validate rule by constructing it from the passed dictionary if (!mAuthdb.validateRule(inRightName, inRuleDefinition)) return errAuthorizationDenied; // @@@ separate error for this? diff --git a/src/AuthorizationMechEval.cpp b/src/AuthorizationMechEval.cpp index 571cff7..307a149 100644 --- a/src/AuthorizationMechEval.cpp +++ b/src/AuthorizationMechEval.cpp @@ -54,6 +54,8 @@ AgentMechanismEvaluator::run(const AuthValueVector &inArguments, const AuthItemS AuthItemSet hints = inHints; AuthItemSet context = inContext; + // add saved-off sticky context values to context for evaluation + context.insert(mStickyContext.begin(), mStickyContext.end()); while ( (result == kAuthorizationResultAllow) && (currentMechanism != mMechanisms.end()) ) // iterate mechanisms @@ -178,7 +180,25 @@ AgentMechanismEvaluator::run(const AuthValueVector &inArguments, const AuthItemS (result == kAuthorizationResultAllow)) { mHints = hints; - mContext = context; + mContext.clear(); + // only make non-sticky context values available externally + AuthItemSet::const_iterator end = context.end(); + for (AuthItemSet::const_iterator it = context.begin(); it != end; ++it) { + const AuthItemRef &item = *it; + if (item->flags() != kAuthorizationContextFlagSticky) + mContext.insert(item); + } + } + else if (result == kAuthorizationResultDeny) + { + // save off sticky values in context + mStickyContext.clear(); + AuthItemSet::const_iterator end = context.end(); + for (AuthItemSet::const_iterator it = context.begin(); it != end; ++it) { + const AuthItemRef &item = *it; + if (item->flags() == kAuthorizationContextFlagSticky) + mStickyContext.insert(item); + } } // convert AuthorizationResult to OSStatus @@ -210,17 +230,9 @@ AuthorizationResult AgentMechanismEvaluator::authinternal(AuthItemSet &context) string password(static_cast((*found)->value().data), (*found)->value().length); secdebug("AuthEvalMech", "found password"); - // Call to checkpw in DS - Server::active().longTermActivity(); Credential newCredential(username, password, true); // create a new shared credential - if (newCredential->isValid()) - { - Syslog::info("authinternal authenticated user %s (uid %lu).", newCredential->username().c_str(), newCredential->uid()); return kAuthorizationResultAllow; - } - - Syslog::error("authinternal failed to authenticate user %s.", newCredential->username().c_str()); } while (0); diff --git a/src/AuthorizationMechEval.h b/src/AuthorizationMechEval.h index dc6d5ea..da8ef57 100644 --- a/src/AuthorizationMechEval.h +++ b/src/AuthorizationMechEval.h @@ -63,6 +63,7 @@ private: AuthItemSet mHints; AuthItemSet mContext; + AuthItemSet mStickyContext; }; } /* namespace Authorization */ diff --git a/src/AuthorizationRule.cpp b/src/AuthorizationRule.cpp index c1a1b21..1fc8290 100644 --- a/src/AuthorizationRule.cpp +++ b/src/AuthorizationRule.cpp @@ -250,12 +250,12 @@ RuleImpl::RuleImpl(const string &inRightName, CFDictionaryRef cfRight, CFDiction mSessionOwner = Attribute::getBool(cfRight, kSessionOwnerID); // authorization tags can have eval now too mEvalDef = Attribute::getVector(cfRight, kMechanismsID); - if (mEvalDef.size() == 0 && cfRules /*only rights default see appserver-admin*/) - { - CFDictionaryRef cfRuleDef = reinterpret_cast(CFDictionaryGetValue(cfRules, CFSTR("authenticate"))); + if (mEvalDef.size() == 0 && cfRules /*only rights default see appserver-admin*/) + { + CFDictionaryRef cfRuleDef = reinterpret_cast(CFDictionaryGetValue(cfRules, CFSTR("authenticate"))); if (cfRuleDef && CFGetTypeID(cfRuleDef) == CFDictionaryGetTypeID()) - mEvalDef = Attribute::getVector(cfRuleDef, kMechanismsID); - } + mEvalDef = Attribute::getVector(cfRuleDef, kMechanismsID); + } mTries = int(Attribute::getDouble(cfRight, kTriesID, false, 3.0)); // XXX/cs double(kAuthorizationMaxTries) mAuthenticateUser = Attribute::getBool(cfRight, kRuleAuthenticateUserID, false, true); @@ -276,7 +276,7 @@ RuleImpl::RuleImpl(const string &inRightName, CFDictionaryRef cfRight, CFDiction } else if (classTag == kAuthorizationRightRule) { - assert(cfRules); // rules can't delegate to other rules + assert(cfRules); // rules can't delegate to other rules secdebug("authrule", "%s : rule delegate rule", inRightName.c_str()); mType = kRuleDelegation; @@ -349,36 +349,24 @@ void RuleImpl::setAgentHints(const AuthItemRef &inRight, const Rule &inTopLevelRule, AuthItemSet &environmentToClient, AuthorizationToken &auth) const { string authorizeString(inRight->name()); - environmentToClient.erase(AuthItemRef(AGENT_HINT_AUTHORIZE_RIGHT)); + environmentToClient.erase(AuthItemRef(AGENT_HINT_AUTHORIZE_RIGHT)); environmentToClient.insert(AuthItemRef(AGENT_HINT_AUTHORIZE_RIGHT, AuthValueOverlay(authorizeString))); pid_t creatorPid = auth.creatorPid(); - environmentToClient.erase(AuthItemRef(AGENT_HINT_CREATOR_PID)); + environmentToClient.erase(AuthItemRef(AGENT_HINT_CREATOR_PID)); environmentToClient.insert(AuthItemRef(AGENT_HINT_CREATOR_PID, AuthValueOverlay(sizeof(pid_t), &creatorPid))); Process &thisProcess = Server::process(); - RefPointer clientCode = auth.creatorCode(); - SecurityAgent::RequestorType requestorType = SecurityAgent::unknown; string bundlePath; - - if (clientCode) - { - string encodedBundle = clientCode->encode(); - char bundleType = (encodedBundle.c_str())[0]; // yay, no accessor - switch(bundleType) - { - case 'b': requestorType = SecurityAgent::bundle; break; - case 't': requestorType = SecurityAgent::tool; break; - } - bundlePath = clientCode->canonicalPath(); - } - - AuthItemSet processHints = SecurityAgent::Client::clientHints(requestorType, bundlePath, thisProcess.pid(), thisProcess.uid()); - environmentToClient.erase(AuthItemRef(AGENT_HINT_CLIENT_TYPE)); - environmentToClient.erase(AuthItemRef(AGENT_HINT_CLIENT_PATH)); - environmentToClient.erase(AuthItemRef(AGENT_HINT_CLIENT_PID)); - environmentToClient.erase(AuthItemRef(AGENT_HINT_CLIENT_UID)); - environmentToClient.insert(processHints.begin(), processHints.end()); + if (SecStaticCodeRef clientCode = auth.creatorCode()) + bundlePath = codePath(clientCode); + AuthItemSet processHints = SecurityAgent::Client::clientHints( + SecurityAgent::bundle, bundlePath, thisProcess.pid(), thisProcess.uid()); + environmentToClient.erase(AuthItemRef(AGENT_HINT_CLIENT_TYPE)); + environmentToClient.erase(AuthItemRef(AGENT_HINT_CLIENT_PATH)); + environmentToClient.erase(AuthItemRef(AGENT_HINT_CLIENT_PID)); + environmentToClient.erase(AuthItemRef(AGENT_HINT_CLIENT_UID)); + environmentToClient.insert(processHints.begin(), processHints.end()); map defaultPrompts = inTopLevelRule->localizedPrompts(); @@ -402,127 +390,143 @@ RuleImpl::setAgentHints(const AuthItemRef &inRight, const Rule &inTopLevelRule, environmentToClient.insert(AuthItemRef(AGENT_HINT_AUTHORIZE_RULE, AuthValueOverlay(ruleName))); } +// If a different evaluation for getting a credential is prescribed, +// we'll run that and validate the credentials from there. +// we fall back on a default configuration from the authenticate rule OSStatus -RuleImpl::evaluateAuthorization(const AuthItemRef &inRight, const Rule &inRule, - AuthItemSet &environmentToClient, - AuthorizationFlags flags, CFAbsoluteTime now, - const CredentialSet *inCredentials, - CredentialSet &credentials, AuthorizationToken &auth) const +RuleImpl::evaluateAuthentication(const AuthItemRef &inRight, const Rule &inRule,AuthItemSet &environmentToClient, AuthorizationFlags flags, CFAbsoluteTime now, const CredentialSet *inCredentials, CredentialSet &credentials, AuthorizationToken &auth) const { - OSStatus status = errAuthorizationDenied; - - string usernamehint; - evaluateSessionOwner(inRight, inRule, environmentToClient, now, auth, usernamehint); - if (usernamehint.length()) - environmentToClient.insert(AuthItemRef(AGENT_HINT_SUGGESTED_USER, AuthValueOverlay(usernamehint))); + OSStatus status = errAuthorizationDenied; + + Credential hintCredential; + if (errAuthorizationSuccess == evaluateSessionOwner(inRight, inRule, environmentToClient, now, auth, hintCredential)) { + if (hintCredential->name().length()) + environmentToClient.insert(AuthItemRef(AGENT_HINT_SUGGESTED_USER, AuthValueOverlay(hintCredential->name()))); + if (hintCredential->realname().length()) + environmentToClient.insert(AuthItemRef(AGENT_HINT_SUGGESTED_USER_LONG, AuthValueOverlay(hintCredential->realname()))); + } - if ((mType == kUser) && (mGroupName.length())) - environmentToClient.insert(AuthItemRef(AGENT_HINT_REQUIRE_USER_IN_GROUP, AuthValueOverlay(mGroupName))); + if ((mType == kUser) && (mGroupName.length())) + environmentToClient.insert(AuthItemRef(AGENT_HINT_REQUIRE_USER_IN_GROUP, AuthValueOverlay(mGroupName))); - uint32 tries; - SecurityAgent::Reason reason = SecurityAgent::noReason; + uint32 tries; + SecurityAgent::Reason reason = SecurityAgent::noReason; Process &cltProc = Server::process(); - // Authorization preserves creator's UID in setuid processes - uid_t cltUid = (cltProc.uid() != 0) ? cltProc.uid() : auth.creatorUid(); - secdebug("AuthEvalMech", "Mechanism invocation by process %d (UID %d)", cltProc.pid(), cltUid); + // Authorization preserves creator's UID in setuid processes + uid_t cltUid = (cltProc.uid() != 0) ? cltProc.uid() : auth.creatorUid(); + secdebug("AuthEvalMech", "Mechanism invocation by process %d (UID %d)", cltProc.pid(), cltUid); - AgentMechanismEvaluator eval(cltUid, auth.session(), mEvalDef); - - for (tries = 0; tries < mTries; tries++) - { + AgentMechanismEvaluator eval(cltUid, auth.session(), mEvalDef); + + for (tries = 0; tries < mTries; tries++) + { AuthItemRef retryHint(AGENT_HINT_RETRY_REASON, AuthValueOverlay(sizeof(reason), &reason)); environmentToClient.erase(retryHint); environmentToClient.insert(retryHint); // replace AuthItemRef triesHint(AGENT_HINT_TRIES, AuthValueOverlay(sizeof(tries), &tries)); environmentToClient.erase(triesHint); environmentToClient.insert(triesHint); // replace - status = eval.run(AuthValueVector(), environmentToClient, auth); - - if ((status == errAuthorizationSuccess) || - (status == errAuthorizationCanceled)) // @@@ can only pass back sideband through context - { - secdebug("AuthEvalMech", "storing new context for authorization"); - auth.setInfoSet(eval.context()); - } - - // successfully ran mechanisms to obtain credential - if (status == errAuthorizationSuccess) - { - // deny is the default - status = errAuthorizationDenied; - - CredentialSet newCredentials = makeCredentials(auth); - // clear context after extracting credentials - auth.scrubInfoSet(); - - for (CredentialSet::const_iterator it = newCredentials.begin(); it != newCredentials.end(); ++it) - { - const Credential& newCredential = *it; + status = eval.run(AuthValueVector(), environmentToClient, auth); + + if ((status == errAuthorizationSuccess) || + (status == errAuthorizationCanceled)) // @@@ can only pass back sideband through context + { + secdebug("AuthEvalMech", "storing new context for authorization"); + auth.setInfoSet(eval.context()); + } + + // successfully ran mechanisms to obtain credential + if (status == errAuthorizationSuccess) + { + // deny is the default + status = errAuthorizationDenied; + + CredentialSet newCredentials = makeCredentials(auth); + // clear context after extracting credentials + auth.scrubInfoSet(); + + CommonCriteria::AuditRecord auditrec(auth.creatorAuditToken()); + for (CredentialSet::const_iterator it = newCredentials.begin(); it != newCredentials.end(); ++it) + { + const Credential& newCredential = *it; // @@@ we log the uid a process was running under when it created the authref, which is misleading in the case of loginwindow - if (newCredential->isValid()) - Syslog::info("uid %lu succeeded authenticating as user %s (uid %lu) for right %s.", auth.creatorUid(), newCredential->username().c_str(), newCredential->uid(), inRight->name()); - else + if (newCredential->isValid()) { + Syslog::info("uid %lu succeeded authenticating as user %s (uid %lu) for right %s.", auth.creatorUid(), newCredential->name().c_str(), newCredential->uid(), inRight->name()); + auditrec.submit(AUE_ssauthint, CommonCriteria::errNone, inRight->name()); + } else { // we can't be sure that the user actually exists so inhibit logging of uid - Syslog::error("uid %lu failed to authenticate as user %s for right %s.", auth.creatorUid(), newCredential->username().c_str(), inRight->name()); - - if (!newCredential->isValid()) - { - reason = SecurityAgent::invalidPassphrase; //invalidPassphrase; - continue; - } - - // verify that this credential authorizes right - status = evaluateCredentialForRight(auth, inRight, inRule, environmentToClient, now, newCredential, true); - - if (status == errAuthorizationSuccess) - { - // whack an equivalent credential, so it gets updated to a later achieved credential which must have been more stringent - credentials.erase(newCredential); credentials.insert(newCredential); - // use valid credential to set context info + Syslog::error("uid %lu failed to authenticate as user %s for right %s.", auth.creatorUid(), newCredential->name().c_str(), inRight->name()); + auditrec.submit(AUE_ssauthint, CommonCriteria::errInvalidCredential, inRight->name()); + } + + if (!newCredential->isValid()) + { + reason = SecurityAgent::invalidPassphrase; //invalidPassphrase; + continue; + } + + // verify that this credential authorizes right + status = evaluateUserCredentialForRight(auth, inRight, inRule, environmentToClient, now, newCredential, true); + + if (status == errAuthorizationSuccess) + { + if (auth.operatesAsLeastPrivileged()) { + Credential rightCredential(inRight->name(), mShared); + credentials.erase(rightCredential); credentials.insert(rightCredential); + if (mShared) + credentials.insert(Credential(inRight->name(), false)); + } else { + // whack an equivalent credential, so it gets updated to a later achieved credential which must have been more stringent + credentials.erase(newCredential); credentials.insert(newCredential); + // just got a new credential - if it's shared also add a non-shared one that to stick in the authorizationref local cache + if (mShared) + credentials.insert(Credential(newCredential->uid(), newCredential->name(), newCredential->realname(), false)); + } + + // use valid credential to set context info // XXX/cs keeping this for now, such that the uid is passed back - auth.setCredentialInfo(newCredential); - secdebug("SSevalMech", "added valid credential for user %s", newCredential->username().c_str()); - status = errAuthorizationSuccess; - break; - } - else - reason = SecurityAgent::userNotInGroup; //unacceptableUser; // userNotInGroup - } - - if (status == errAuthorizationSuccess) - break; - } - else - if ((status == errAuthorizationCanceled) || + auth.setCredentialInfo(newCredential); + secdebug("SSevalMech", "added valid credential for user %s", newCredential->name().c_str()); + status = errAuthorizationSuccess; + break; + } + else + reason = SecurityAgent::userNotInGroup; //unacceptableUser; // userNotInGroup + } + + if (status == errAuthorizationSuccess) + break; + } + else + if ((status == errAuthorizationCanceled) || (status == errAuthorizationInternal)) - { - auth.scrubInfoSet(); - break; - } - else // last mechanism is now authentication - fail - if (status == errAuthorizationDenied) - reason = SecurityAgent::invalidPassphrase; - - } - - // If we fell out of the loop because of too many tries, notify user - if (tries == mTries) - { - reason = SecurityAgent::tooManyTries; + { + auth.scrubInfoSet(); + break; + } + else // last mechanism is now authentication - fail + if (status == errAuthorizationDenied) + reason = SecurityAgent::invalidPassphrase; +} + + // If we fell out of the loop because of too many tries, notify user + if (tries == mTries) + { + reason = SecurityAgent::tooManyTries; AuthItemRef retryHint (AGENT_HINT_RETRY_REASON, AuthValueOverlay(sizeof(reason), &reason)); environmentToClient.erase(retryHint); environmentToClient.insert(retryHint); // replace AuthItemRef triesHint(AGENT_HINT_TRIES, AuthValueOverlay(sizeof(tries), &tries)); environmentToClient.erase(triesHint); environmentToClient.insert(triesHint); // replace - eval.run(AuthValueVector(), environmentToClient, auth); - // XXX/cs is this still necessary? - auth.scrubInfoSet(); + eval.run(AuthValueVector(), environmentToClient, auth); + // XXX/cs is this still necessary? + auth.scrubInfoSet(); CommonCriteria::AuditRecord auditrec(auth.creatorAuditToken()); auditrec.submit(AUE_ssauthorize, CommonCriteria::errTooManyTries, inRight->name()); - } + } - return status; + return status; } // create externally verified credentials on the basis of @@ -530,114 +534,95 @@ RuleImpl::evaluateAuthorization(const AuthItemRef &inRight, const Rule &inRule, CredentialSet RuleImpl::makeCredentials(const AuthorizationToken &auth) const { - // fetch context and construct a credential to be tested - const AuthItemSet &context = const_cast(auth).infoSet(); - CredentialSet newCredentials; - - do { - AuthItemSet::const_iterator found = find_if(context.begin(), context.end(), FindAuthItemByRightName(kAuthorizationEnvironmentUsername) ); - if (found == context.end()) - break; - string username = (**found).stringValue(); - secdebug("AuthEvalMech", "found username"); - - const uid_t *uid = NULL; - found = find_if(context.begin(), context.end(), FindAuthItemByRightName("uid") ); - if (found != context.end()) - { - uid = static_cast((**found).value().data); - secdebug("AuthEvalMech", "found uid"); - } - - const gid_t *gid = NULL; - found = find_if(context.begin(), context.end(), FindAuthItemByRightName("gid") ); - if (found != context.end()) - { - gid = static_cast((**found).value().data); - secdebug("AuthEvalMech", "found gid"); - } - - if (username.length() && uid && gid) - { - // credential is valid because mechanism says so - newCredentials.insert(Credential(username, *uid, *gid, mShared)); - } - else - { - found = find_if(context.begin(), context.end(), FindAuthItemByRightName(kAuthorizationEnvironmentPassword) ); - if (found != context.end()) - { - secdebug("AuthEvalMech", "found password"); - string password = (**found).stringValue(); - secdebug("AuthEvalMech", "falling back on username/password credential if valid"); - // Call to checkpw in DS - Server::active().longTermActivity(); - Credential newCred(username, password, mShared); - newCredentials.insert(newCred); - CommonCriteria::AuditRecord auditrec(auth.creatorAuditToken()); - if (newCred->isValid()) - auditrec.submit(AUE_ssauthorize, CommonCriteria::errNone, name().c_str()); - else - auditrec.submit(AUE_ssauthorize, CommonCriteria::errInvalidCredential, name().c_str()); - } - } - } while(0); + // fetch context and construct a credential to be tested + const AuthItemSet &context = const_cast(auth).infoSet(); + CredentialSet newCredentials; + + do { + AuthItemSet::const_iterator found = find_if(context.begin(), context.end(), FindAuthItemByRightName(kAuthorizationEnvironmentUsername) ); + if (found == context.end()) + break; + string username = (**found).stringValue(); + secdebug("AuthEvalMech", "found username"); + + const uid_t *uid = NULL; + found = find_if(context.begin(), context.end(), FindAuthItemByRightName("uid") ); + if (found != context.end()) + { + uid = static_cast((**found).value().data); + secdebug("AuthEvalMech", "found uid"); + } + + if (username.length() && uid) + { + // credential is valid because mechanism says so + newCredentials.insert(Credential(*uid, username, "", mShared)); + } + } while(0); - return newCredentials; + return newCredentials; } // evaluate whether a good credential of the current session owner would authorize a right OSStatus -RuleImpl::evaluateSessionOwner(const AuthItemRef &inRight, const Rule &inRule, - const AuthItemSet &environment, - const CFAbsoluteTime now, - const AuthorizationToken &auth, - string& usernamehint) const +RuleImpl::evaluateSessionOwner(const AuthItemRef &inRight, const Rule &inRule, const AuthItemSet &environment, const CFAbsoluteTime now, const AuthorizationToken &auth, Credential &credential) const { - // username hint is taken from the user who created the authorization, unless it's clearly ineligible - OSStatus status = noErr; + // username hint is taken from the user who created the authorization, unless it's clearly ineligible // @@@ we have no access to current requester uid here and the process uid is only taken when the authorization is created // meaning that a process like loginwindow that drops privs later is screwed. uid_t uid; Session &session = auth.session(); - - if (session.haveOriginatorUid()) - uid = session.originatorUid(); - else + Credential sessionCredential; + if (session.haveOriginatorUid()) { + // preflight session credential as if it were a fresh copy + const Credential &cred = session.originatorCredential(); + sessionCredential = Credential(cred->uid(), cred->name(), cred->realname(), mShared/*ignored*/); + } else { uid = auth.creatorUid(); - - Server::active().longTermActivity(); - struct passwd *pw = getpwuid(uid); - if (pw != NULL) - { - // avoid hinting a locked account - if ( (pw->pw_passwd == NULL) || + Server::active().longTermActivity(); + struct passwd *pw = getpwuid(uid); + if (pw != NULL) { + // avoid hinting a locked account + if ( (pw->pw_passwd == NULL) || strcmp(pw->pw_passwd, "*") ) { - // Check if username will authorize the request and set username to - // be used as a hint to the user if so - secdebug("AuthEvalMech", "preflight credential from current user, result follows:"); - status = evaluateCredentialForRight(auth, inRight, inRule, environment, now, Credential(pw->pw_name, pw->pw_uid, pw->pw_gid, mShared), true); - - if (status == errAuthorizationSuccess) - usernamehint = pw->pw_name; - } //fi - endpwent(); + // Check if username will authorize the request and set username to + // be used as a hint to the user if so + secdebug("AuthEvalMech", "preflight credential from current user, result follows:"); + sessionCredential = Credential(pw->pw_uid, pw->pw_name, pw->pw_gecos, mShared/*ignored*/); + } //fi + endpwent(); + } } + OSStatus status = evaluateUserCredentialForRight(auth, inRight, inRule, environment, now, sessionCredential, true); + if (errAuthorizationSuccess == status) + credential = sessionCredential; + return status; } +OSStatus +RuleImpl::evaluateCredentialForRight(const AuthorizationToken &auth, const AuthItemRef &inRight, const Rule &inRule, const AuthItemSet &environment, CFAbsoluteTime now, const Credential &credential, bool ignoreShared) const +{ + if (auth.operatesAsLeastPrivileged()) { + if (credential->isRight() && credential->isValid() && (inRight->name() == credential->name())) + return errAuthorizationSuccess; + else + return errAuthorizationDenied; + } else + return evaluateUserCredentialForRight(auth, inRight, inRule, environment, now, credential, false); +} // Return errAuthorizationSuccess if this rule allows access based on the specified credential, // return errAuthorizationDenied otherwise. OSStatus -RuleImpl::evaluateCredentialForRight(const AuthorizationToken &auth, const AuthItemRef &inRight, const Rule &inRule, const AuthItemSet &environment, CFAbsoluteTime now, const Credential &credential, bool ignoreShared) const +RuleImpl::evaluateUserCredentialForRight(const AuthorizationToken &auth, const AuthItemRef &inRight, const Rule &inRule, const AuthItemSet &environment, CFAbsoluteTime now, const Credential &credential, bool ignoreShared) const { assert(mType == kUser); // Get the username from the credential - const char *user = credential->username().c_str(); + const char *user = credential->name().c_str(); // If the credential is not valid or it's age is more than the allowed maximum age // for a credential, deny. @@ -666,22 +651,22 @@ RuleImpl::evaluateCredentialForRight(const AuthorizationToken &auth, const AuthI return errAuthorizationSuccess; } - if (mSessionOwner) - { + if (mSessionOwner) + { Session &session = auth.session(); if (session.haveOriginatorUid()) { uid_t console_user = session.originatorUid(); - if (credential->uid() == console_user) - { - secdebug("autheval", "user %s is session-owner(uid: %d), granting right %s", user, console_user, inRight->name()); - return errAuthorizationSuccess; - } - } - else - secdebug("autheval", "session-owner check failed."); - } + if (credential->uid() == console_user) + { + secdebug("autheval", "user %s is session-owner(uid: %d), granting right %s", user, console_user, inRight->name()); + return errAuthorizationSuccess; + } + } + else + secdebug("autheval", "session-owner check failed."); + } if (mGroupName.length()) { @@ -725,10 +710,7 @@ RuleImpl::evaluateCredentialForRight(const AuthorizationToken &auth, const AuthI OSStatus -RuleImpl::evaluateUser(const AuthItemRef &inRight, const Rule &inRule, - AuthItemSet &environmentToClient, AuthorizationFlags flags, - CFAbsoluteTime now, const CredentialSet *inCredentials, CredentialSet &credentials, - AuthorizationToken &auth) const +RuleImpl::evaluateUser(const AuthItemRef &inRight, const Rule &inRule, AuthItemSet &environmentToClient, AuthorizationFlags flags, CFAbsoluteTime now, const CredentialSet *inCredentials, CredentialSet &credentials, AuthorizationToken &auth) const { // If we got here, this is a kUser type rule, let's start looking for a // credential that is satisfactory @@ -745,8 +727,8 @@ RuleImpl::evaluateUser(const AuthItemRef &inRight, const Rule &inRule, // if we're not supposed to authenticate evaluate the session-owner against the group if (!mAuthenticateUser) { - string username; - OSStatus status = evaluateSessionOwner(inRight, inRule, environmentToClient, now, auth, username); + Credential hintCredential; + OSStatus status = evaluateSessionOwner(inRight, inRule, environmentToClient, now, auth, hintCredential); if (!status) return errAuthorizationSuccess; @@ -757,13 +739,28 @@ RuleImpl::evaluateUser(const AuthItemRef &inRight, const Rule &inRule, // First -- go though the credentials we either already used or obtained during this authorize operation. for (CredentialSet::const_iterator it = credentials.begin(); it != credentials.end(); ++it) { - OSStatus status = evaluateCredentialForRight(auth, inRight, inRule, environmentToClient, now, *it, true); - if (status != errAuthorizationDenied) + // Passed in user credentials are allowed for least privileged mode + if (auth.operatesAsLeastPrivileged() && !(*it)->isRight() && (*it)->isValid()) { + OSStatus status = evaluateUserCredentialForRight(auth, inRight, inRule, environmentToClient, now, *it, false); + if (errAuthorizationSuccess == status) { + Credential rightCredential(inRight->name(), mShared); + credentials.erase(rightCredential); credentials.insert(rightCredential); + if (mShared) + credentials.insert(Credential(inRight->name(), false)); + return status; + } + } + + // if this is least privileged, this will function differently: match credential to requested right + OSStatus status = evaluateCredentialForRight(auth, inRight, inRule, environmentToClient, now, *it, false); + + if (status != errAuthorizationDenied) { // add credential to authinfo auth.setCredentialInfo(*it); return status; } + } // Second -- go though the credentials passed in to this authorize operation by the state management layer. @@ -771,14 +768,16 @@ RuleImpl::evaluateUser(const AuthItemRef &inRight, const Rule &inRule, { for (CredentialSet::const_iterator it = inCredentials->begin(); it != inCredentials->end(); ++it) { + // if this is least privileged, this will function differently: match credential to requested right OSStatus status = evaluateCredentialForRight(auth, inRight, inRule, environmentToClient, now, *it, false); + if (status == errAuthorizationSuccess) { // Add the credential we used to the output set. // whack an equivalent credential, so it gets updated to a later achieved credential which must have been more stringent credentials.erase(*it); credentials.insert(*it); - // add credential to authinfo - auth.setCredentialInfo(*it); + // add credential to authinfo + auth.setCredentialInfo(*it); return status; } @@ -787,8 +786,7 @@ RuleImpl::evaluateUser(const AuthItemRef &inRight, const Rule &inRule, } } - // Finally -- We didn't find the credential in our passed in credential lists. Obtain a new credential if - // our flags let us do so. + // Finally -- We didn't find the credential in our passed in credential lists. Obtain a new credential if our flags let us do so. if (!(flags & kAuthorizationFlagExtendRights)) return errAuthorizationDenied; @@ -805,10 +803,7 @@ RuleImpl::evaluateUser(const AuthItemRef &inRight, const Rule &inRule, setAgentHints(inRight, inRule, environmentToClient, auth); - // If a different evaluation is prescribed, - // we'll run that and validate the credentials from there - // we fall back on a default configuration - return evaluateAuthorization(inRight, inRule, environmentToClient, flags, now, inCredentials, credentials, auth); + return evaluateAuthentication(inRight, inRule, environmentToClient, flags, now, inCredentials, credentials, auth); } OSStatus @@ -818,57 +813,57 @@ RuleImpl::evaluateMechanismOnly(const AuthItemRef &inRight, const Rule &inRule, OSStatus status; Process &cltProc = Server::process(); - // Authorization preserves creator's UID in setuid processes - uid_t cltUid = (cltProc.uid() != 0) ? cltProc.uid() : auth.creatorUid(); - secdebug("AuthEvalMech", "Mechanism invocation by process %d (UID %d)", cltProc.pid(), cltUid); - - { - AgentMechanismEvaluator eval(cltUid, auth.session(), mEvalDef); - - do - { - setAgentHints(inRight, inRule, environmentToClient, auth); - AuthItemRef triesHint(AGENT_HINT_TRIES, AuthValueOverlay(sizeof(tries), &tries)); - environmentToClient.erase(triesHint); environmentToClient.insert(triesHint); // replace - - status = eval.run(AuthValueVector(), environmentToClient, auth); - - if ((status == errAuthorizationSuccess) || - (status == errAuthorizationCanceled)) // @@@ can only pass back sideband through context - { - secdebug("AuthEvalMech", "storing new context for authorization"); - auth.setInfoSet(eval.context()); - if (status == errAuthorizationSuccess) - { - outCredentials = makeCredentials(auth); - } - } - - tries++; - } - while ((status == errAuthorizationDenied) // only if we have an expected failure we continue - && ((mTries == 0) // mTries == 0 means we try forever - || ((mTries > 0) // mTries > 0 means we try up to mTries times - && (tries < mTries)))); - } + // Authorization preserves creator's UID in setuid processes + uid_t cltUid = (cltProc.uid() != 0) ? cltProc.uid() : auth.creatorUid(); + secdebug("AuthEvalMech", "Mechanism invocation by process %d (UID %d)", cltProc.pid(), cltUid); + + { + AgentMechanismEvaluator eval(cltUid, auth.session(), mEvalDef); + + do + { + setAgentHints(inRight, inRule, environmentToClient, auth); + AuthItemRef triesHint(AGENT_HINT_TRIES, AuthValueOverlay(sizeof(tries), &tries)); + environmentToClient.erase(triesHint); environmentToClient.insert(triesHint); // replace + + status = eval.run(AuthValueVector(), environmentToClient, auth); + + if ((status == errAuthorizationSuccess) || + (status == errAuthorizationCanceled)) // @@@ can only pass back sideband through context + { + secdebug("AuthEvalMech", "storing new context for authorization"); + auth.setInfoSet(eval.context()); + if (status == errAuthorizationSuccess) + { + if (auth.operatesAsLeastPrivileged()) + outCredentials.insert(Credential(inRight->name(), mShared)); + else + outCredentials = makeCredentials(auth); + } + } + + tries++; + } + while ((status == errAuthorizationDenied) // only if we have an expected failure we continue + && ((mTries == 0) // mTries == 0 means we try forever + || ((mTries > 0) // mTries > 0 means we try up to mTries times + && (tries < mTries)))); + } - // HACK kill all hosts to free pages for low memory systems - if (name() == "system.login.console") + // HACK kill all hosts to free pages for low memory systems + if (name() == "system.login.done") { QueryInvokeMechanism query(securityAgent, auth.session()); query.terminateAgent(); QueryInvokeMechanism query2(privilegedAuthHost, auth.session()); query2.terminateAgent(); } - + return status; } OSStatus -RuleImpl::evaluateRules(const AuthItemRef &inRight, const Rule &inRule, - AuthItemSet &environmentToClient, AuthorizationFlags flags, - CFAbsoluteTime now, const CredentialSet *inCredentials, CredentialSet &credentials, - AuthorizationToken &auth) const +RuleImpl::evaluateRules(const AuthItemRef &inRight, const Rule &inRule, AuthItemSet &environmentToClient, AuthorizationFlags flags, CFAbsoluteTime now, const CredentialSet *inCredentials, CredentialSet &credentials, AuthorizationToken &auth) const { // line up the rules to try if (!mRuleDef.size()) @@ -908,10 +903,7 @@ RuleImpl::evaluateRules(const AuthItemRef &inRight, const Rule &inRule, OSStatus -RuleImpl::evaluate(const AuthItemRef &inRight, const Rule &inRule, - AuthItemSet &environmentToClient, AuthorizationFlags flags, - CFAbsoluteTime now, const CredentialSet *inCredentials, CredentialSet &credentials, - AuthorizationToken &auth) const +RuleImpl::evaluate(const AuthItemRef &inRight, const Rule &inRule, AuthItemSet &environmentToClient, AuthorizationFlags flags, CFAbsoluteTime now, const CredentialSet *inCredentials, CredentialSet &credentials, AuthorizationToken &auth) const { switch (mType) { @@ -925,15 +917,15 @@ RuleImpl::evaluate(const AuthItemRef &inRight, const Rule &inRule, secdebug("autheval", "rule is user"); return evaluateUser(inRight, inRule, environmentToClient, flags, now, inCredentials, credentials, auth); case kRuleDelegation: - secdebug("autheval", "rule evaluates rules"); + secdebug("autheval", "rule evaluates rules"); return evaluateRules(inRight, inRule, environmentToClient, flags, now, inCredentials, credentials, auth); case kKofN: - secdebug("autheval", "rule evaluates k-of-n rules"); + secdebug("autheval", "rule evaluates k-of-n rules"); return evaluateRules(inRight, inRule, environmentToClient, flags, now, inCredentials, credentials, auth); - case kEvaluateMechanisms: - secdebug("autheval", "rule evaluates mechanisms"); - return evaluateMechanismOnly(inRight, inRule, environmentToClient, auth, credentials); - default: + case kEvaluateMechanisms: + secdebug("autheval", "rule evaluates mechanisms"); + return evaluateMechanismOnly(inRight, inRule, environmentToClient, auth, credentials); + default: MacOSError::throwMe(errAuthorizationInternal); // XXX/cs invalid rule } } diff --git a/src/AuthorizationRule.h b/src/AuthorizationRule.h index d83c5a4..95cf139 100644 --- a/src/AuthorizationRule.h +++ b/src/AuthorizationRule.h @@ -23,7 +23,6 @@ * AuthorizationRule.h * Security * - * Created by Conrad Sauerwald on Wed Mar 19 2003. */ #ifndef _H_AUTHORIZATIONRULE @@ -57,6 +56,8 @@ private: // evaluate credential for right OSStatus evaluateCredentialForRight(const AuthorizationToken &auth, const AuthItemRef &inRight, const Rule &inRule, const AuthItemSet &environment, CFAbsoluteTime now, const Credential &credential, bool ignoreShared) const; + // evaluate user credential (authentication) for right + OSStatus evaluateUserCredentialForRight(const AuthorizationToken &auth, const AuthItemRef &inRight, const Rule &inRule, const AuthItemSet &environment, CFAbsoluteTime now, const Credential &credential, bool ignoreShared) const; OSStatus evaluateRules(const AuthItemRef &inRight, const Rule &inRule, AuthItemSet &environmentToClient, AuthorizationFlags flags, @@ -66,7 +67,7 @@ private: void setAgentHints(const AuthItemRef &inRight, const Rule &inTopLevelRule, AuthItemSet &environmentToClient, AuthorizationToken &auth) const; // perform authorization based on running specified mechanisms (see evaluateMechanism) - OSStatus evaluateAuthorization(const AuthItemRef &inRight, const Rule &inRule, AuthItemSet &environmentToClient, AuthorizationFlags flags, CFAbsoluteTime now, const CredentialSet *inCredentials, CredentialSet &credentials, AuthorizationToken &auth) const; + OSStatus evaluateAuthentication(const AuthItemRef &inRight, const Rule &inRule, AuthItemSet &environmentToClient, AuthorizationFlags flags, CFAbsoluteTime now, const CredentialSet *inCredentials, CredentialSet &credentials, AuthorizationToken &auth) const; OSStatus evaluateUser(const AuthItemRef &inRight, const Rule &inRule, AuthItemSet &environmentToClient, AuthorizationFlags flags, @@ -76,7 +77,7 @@ private: OSStatus evaluateMechanismOnly(const AuthItemRef &inRight, const Rule &inRule, AuthItemSet &environmentToClient, AuthorizationToken &auth, CredentialSet &outCredentials) const; // find username hint based on session owner - OSStatus evaluateSessionOwner(const AuthItemRef &inRight, const Rule &inRule, const AuthItemSet &environment, const CFAbsoluteTime now, const AuthorizationToken &auth, string& usernamehint) const; + OSStatus evaluateSessionOwner(const AuthItemRef &inRight, const Rule &inRule, const AuthItemSet &environment, const CFAbsoluteTime now, const AuthorizationToken &auth, Credential &credential) const; CredentialSet makeCredentials(const AuthorizationToken &auth) const; diff --git a/src/SharedMemoryServer.cpp b/src/SharedMemoryServer.cpp new file mode 100644 index 0000000..46bc1dc --- /dev/null +++ b/src/SharedMemoryServer.cpp @@ -0,0 +1,150 @@ +#include "SharedMemoryServer.h" +#include +#include +#include +#include + + +SharedMemoryServer::SharedMemoryServer (const char* segmentName, SegmentOffsetType segmentSize) : + mSegmentName (segmentName), mSegmentSize (segmentSize) +{ + // open the file + int segmentDescriptor = shm_open (segmentName, O_RDWR | O_CREAT, S_IRWXU | S_IRGRP | S_IROTH); + if (segmentDescriptor < 0) + { + return; + } + + // set the segment size + ftruncate (segmentDescriptor, segmentSize); + + // map it into memory + mSegment = (u_int8_t*) mmap (NULL, mSegmentSize, PROT_READ | PROT_WRITE, MAP_SHARED, segmentDescriptor, 0); + close (segmentDescriptor); + + if (mSegment == (u_int8_t*) -1) // can't map the memory? + { + mSegment = NULL; + shm_unlink (segmentName); + } + + SetProducerCount (0); +} + + + +SharedMemoryServer::~SharedMemoryServer () +{ + // go away + if (mSegment == NULL) + { + return; + } + + // get out of memory + munmap (mSegment, mSegmentSize); + + // mark the segment for deletion + shm_unlink (mSegmentName.c_str ()); +} + + + +const SegmentOffsetType + kSegmentLength = 0, + kDomainOffset = kSegmentLength + sizeof (SegmentOffsetType), + kEventTypeOffset = kDomainOffset + sizeof (SegmentOffsetType), + kHeaderLength = kEventTypeOffset + sizeof (SegmentOffsetType); + +void SharedMemoryServer::WriteMessage (SegmentOffsetType domain, SegmentOffsetType event, const void *message, SegmentOffsetType messageLength) +{ + // get the current producer count + SegmentOffsetType pCount = GetProducerCount (); + + SegmentOffsetType actualLength = messageLength + kHeaderLength; + + // for now, write a 0 for the length -- this will give clients the opportunity to not process an + // incomplete message + WriteOffsetAtOffset (pCount, 0); + + // extend the overall write count by enough data to hold the message length and message + SetProducerCount (pCount + actualLength); + + // write the data + WriteDataAtOffset (pCount + kHeaderLength, message, messageLength); + + // write the domain + WriteOffsetAtOffset (pCount + kDomainOffset, domain); + + // write the event type + WriteOffsetAtOffset (pCount + kEventTypeOffset, event); + + // write the data count + WriteOffsetAtOffset (pCount, actualLength); +} + + + +const char* SharedMemoryServer::GetSegmentName () +{ + return mSegmentName.c_str (); +} + + + +size_t SharedMemoryServer::GetSegmentSize () +{ + return mSegmentSize; +} + + + +SegmentOffsetType SharedMemoryServer::GetProducerCount () +{ + // the data is stored in the buffer in network byte order + u_int32_t pCount = *(u_int32_t*) mSegment; + return OSSwapHostToBigInt32 (pCount); +} + + + +void SharedMemoryServer::SetProducerCount (SegmentOffsetType producerCount) +{ + *((u_int32_t*) mSegment) = OSSwapHostToBigInt32 (producerCount); +} + + + +void SharedMemoryServer::WriteOffsetAtOffset (SegmentOffsetType offset, SegmentOffsetType data) +{ + // convert data to network byte order + u_int8_t buffer[4]; + *((u_int32_t*) buffer) = OSSwapHostToBigInt32 (data); + + WriteDataAtOffset (offset, buffer, sizeof (buffer)); +} + + + +void SharedMemoryServer::WriteDataAtOffset (SegmentOffsetType offset, const void* data, SegmentOffsetType length) +{ + // figure out where in the buffer we actually need to write the data + SegmentOffsetType realOffset = offset % kPoolAvailableForData; + + // figure out how many bytes we can write without overflowing the buffer + SegmentOffsetType bytesToEnd = kPoolAvailableForData - realOffset; + + // figure out how many bytes we can write + SegmentOffsetType bytesToWrite = bytesToEnd < length ? bytesToEnd : length; + + // move the first part of the data, making sure to skip the producer pointer + memmove (mSegment + sizeof (SegmentOffsetType) + realOffset, data, bytesToWrite); + + // deduct the bytes just written + length -= bytesToWrite; + + if (length != 0) // did we wrap around? + { + memmove (mSegment + sizeof (SegmentOffsetType), ((u_int8_t*) data) + bytesToWrite, length); + } +} diff --git a/src/SharedMemoryServer.h b/src/SharedMemoryServer.h new file mode 100644 index 0000000..27958a4 --- /dev/null +++ b/src/SharedMemoryServer.h @@ -0,0 +1,36 @@ +#ifndef __SHARED_MEMORY_SERVER__ +#define __SHARED_MEMORY_SERVER__ + + + +#include +#include +#include + +class SharedMemoryServer +{ +protected: + std::string mSegmentName; + size_t mSegmentSize; + + u_int8_t* mSegment; + + void WriteOffsetAtOffset (SegmentOffsetType offset, SegmentOffsetType data); + void WriteDataAtOffset (SegmentOffsetType offset, const void* data, SegmentOffsetType length); + +public: + SharedMemoryServer (const char* segmentName, SegmentOffsetType segmentSize); + virtual ~SharedMemoryServer (); + + void WriteMessage (SegmentOffsetType domain, SegmentOffsetType event, const void *message, SegmentOffsetType messageLength); + + const char* GetSegmentName (); + size_t GetSegmentSize (); + + SegmentOffsetType GetProducerCount (); + void SetProducerCount (SegmentOffsetType producerCount); +}; + + + +#endif diff --git a/src/acl_keychain.cpp b/src/acl_keychain.cpp index 6ac8eb7..aa7b18b 100644 --- a/src/acl_keychain.cpp +++ b/src/acl_keychain.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2007 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -37,28 +37,9 @@ // On-disk (flattened) representation: // In order to accommodate legacy formats nicely, we use the binary-versioning feature // of the ACL machinery. Version 0 is the legacy format (storing only the description -// string), while Version 1 contains both selector and description. To allow for -// maximum backward compatibility, legacy-compatible forms are written out as version 0. -// See isLegacyCompatible(). -// -// Some notes on Acl Update Triggers: -// When the user checks the "don't ask me again" checkbox in the access confirmation -// dialog, we respond by returning the informational error code -// CSSMERR_CSP_APPLE_ADD_APPLICATION_ACL_SUBJECT, and setting a count-down trigger -// in the connection. The caller is entitled to bypass our dialog (it succeeds -// automatically) within the next few (Connection::aclUpdateTriggerLimit == 3) -// requests, in order to update the object's ACL as requested. It must then retry -// the original access operation (which will presumably pass because of that edit). -// These are the rules: for the trigger to apply, the access must be to the same -// object, from the same connection, and within the next aclUpdateTriggerLimit accesses. -// (Currently, these are for a "get acl", "get owner", and the "change acl" calls.) -// Damage Control Department: The worst this mechanism could do, if subverted, is -// to bypass our confirmation dialog (making it appear to succeed to the ACL validation). -// But that is exactly what the "don't ask me again" checkbox is meant to do, so any -// subversion would be based on a (perhaps intentional) miscommunication between user -// and client process as to what the user consents not to be asked about (any more). -// The user can always examine the resulting ACL (in Keychain Access or elsewhere), and -// edit it to suit her needs. +// string), while Version 1 contains both selector and description. We are now always +// writing version-1 data, but will continue to recognize version-0 data indefinitely +// for really, really old keychain items. // #include "acl_keychain.h" #include "agentquery.h" @@ -66,12 +47,14 @@ #include "connection.h" #include "database.h" #include "server.h" +#include "osxcodewrap.h" #include +#include +#include #include #define ACCEPT_LEGACY_FORM 1 -#define FECKLESS_KEYCHAIN_ACCESS_EXCEPTION 1 // @@ -90,42 +73,76 @@ bool KeychainPromptAclSubject::validate(const AclValidationContext &context, const TypedList &sample) const { if (SecurityServerEnvironment *env = context.environment()) { - // check for special ACL-update override - if (context.authorization() == CSSM_ACL_AUTHORIZATION_CHANGE_ACL - && Server::connection().aclWasSetForUpdateTrigger(env->acl)) { - secdebug("kcacl", "honoring acl update trigger for %p(%s)", - &env->acl, description.c_str()); - return true; + Process &process = Server::process(); + secdebug("kcacl", "Keychain query for process %d (UID %d)", process.pid(), process.uid()); + + // assemble the effective validity mode mask + uint32_t mode = Maker::defaultMode; + const uint16_t &flags = selector.flags; + if (flags & CSSM_ACL_KEYCHAIN_PROMPT_UNSIGNED_ACT) + mode = (mode & ~CSSM_ACL_KEYCHAIN_PROMPT_UNSIGNED) | (flags & CSSM_ACL_KEYCHAIN_PROMPT_UNSIGNED); + if (flags & CSSM_ACL_KEYCHAIN_PROMPT_INVALID_ACT) + mode = (mode & ~CSSM_ACL_KEYCHAIN_PROMPT_INVALID) | (flags & CSSM_ACL_KEYCHAIN_PROMPT_INVALID); + + // determine signed/validity status of client, without reference to any particular Code Requirement + SecCodeRef clientCode = process.currentGuest(); + Server::active().longTermActivity(); + OSStatus validation = clientCode ? SecCodeCheckValidity(clientCode, kSecCSDefaultFlags, NULL) : errSecCSStaticCodeNotFound; + switch (validation) { + case noErr: // client is signed and valid + secdebug("kcacl", "client is valid, proceeding"); + break; + case errSecCSUnsigned: // client is not signed + if (!(mode & CSSM_ACL_KEYCHAIN_PROMPT_UNSIGNED)) { + secdebug("kcacl", "client is unsigned, suppressing prompt"); + return false; + } + break; + case errSecCSSignatureFailed: // client signed but signature is broken + case errSecCSGuestInvalid: // client signed but dynamically invalid + case errSecCSStaticCodeNotFound: // client not on disk (or unreadable) + if (!(mode & CSSM_ACL_KEYCHAIN_PROMPT_INVALID)) { + secdebug("kcacl", "client is invalid, suppressing prompt"); + Syslog::info("suppressing keychain prompt for invalidly signed client %s(%d)", + process.getPath().c_str(), process.pid()); + return false; + } + Syslog::info("attempting keychain prompt for invalidly signed client %s(%d)", + process.getPath().c_str(), process.pid()); + break; + default: // something else went wrong + secdebug("kcacl", "client validation failed rc=%ld, suppressing prompt", validation); + return false; } + // At this point, we're committed to try to Pop The Question. Now, how? + // does the user need to type in the passphrase? const Database *db = env->database; bool needPassphrase = db && (selector.flags & CSSM_ACL_KEYCHAIN_PROMPT_REQUIRE_PASSPHRASE); - // ask the user -#if FECKLESS_KEYCHAIN_ACCESS_EXCEPTION - Process &process = Server::process(); - secdebug("kcacl", "Keychain query from process %d (UID %d)", process.pid(), process.uid()); - if (process.clientCode()) - needPassphrase |= - process.clientCode()->canonicalPath() == "/Applications/Utilities/Keychain Access.app"; -#endif + // an application (i.e. Keychain Access.app :-) can force this option + if (clientCode) { + CFRef dict; + if (!SecCodeCopySigningInformation(clientCode, kSecCSDefaultFlags, &dict.aref())) + if (CFDictionaryRef info = CFDictionaryRef(CFDictionaryGetValue(dict, kSecCodeInfoPList))) + needPassphrase |= + (CFDictionaryGetValue(info, CFSTR("SecForcePassphrasePrompt")) != NULL); + } + + // pop The Question QueryKeychainUse query(needPassphrase, db); query.inferHints(Server::process()); - + query.addHint(AGENT_HINT_CLIENT_VALIDITY, &validation, sizeof(validation)); if (query.queryUser(db ? db->dbName() : NULL, - description.c_str(), context.authorization()) - != SecurityAgent::noReason) - return false; + description.c_str(), context.authorization()) != SecurityAgent::noReason) + return false; - // process "always allow..." response - if (query.remember) { - // mark for special ACL-update override (really soon) later - Server::connection().setAclUpdateTrigger(env->acl); - secdebug("kcacl", "setting acl update trigger for %p(%s)", - &env->acl, description.c_str()); - // fail with prejudice (caller will retry) - CssmError::throwMe(CSSMERR_CSP_APPLE_ADD_APPLICATION_ACL_SUBJECT); + // process an "always allow..." response + if (query.remember && clientCode) { + RefPointer clientXCode = new OSXCodeWrap(clientCode); + RefPointer subject = new CodeSignatureAclSubject(OSXVerifier(clientXCode)); + SecurityServerAcl::addToStandardACL(context, subject); } // finally, return the actual user response @@ -150,6 +167,8 @@ CssmList KeychainPromptAclSubject::toList(Allocator &alloc) const // // Create a KeychainPromptAclSubject // +uint32_t KeychainPromptAclSubject::Maker::defaultMode; + KeychainPromptAclSubject *KeychainPromptAclSubject::Maker::make(const TypedList &list) const { switch (list.length()) { @@ -189,6 +208,8 @@ KeychainPromptAclSubject *KeychainPromptAclSubject::Maker::make(Version version, selector.flags = n2h(selector.flags); pub(description); break; + default: + CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE); } return new KeychainPromptAclSubject(description, selector); } @@ -202,11 +223,8 @@ KeychainPromptAclSubject::KeychainPromptAclSubject(string descr, if (selector.version != CSSM_ACL_KEYCHAIN_PROMPT_CURRENT_VERSION) CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE); - // determine binary compatibility version - if (selector.flags == 0) // compatible with old form - version(pumaVersion); - else - version(jaguarVersion); + // always use the latest binary version + version(currentVersion); } @@ -235,16 +253,6 @@ void KeychainPromptAclSubject::exportBlob(Writer &pub, Writer &priv) } -// -// Determine whether this ACL subject is in "legacy compatible" form. -// Legacy (<10.2) form contained no selector. -// -bool KeychainPromptAclSubject::isLegacyCompatible() const -{ - return selector.flags == 0; -} - - #ifdef DEBUGDUMP void KeychainPromptAclSubject::debugDump() const diff --git a/src/acl_keychain.h b/src/acl_keychain.h index bbdec1a..bfca5ef 100644 --- a/src/acl_keychain.h +++ b/src/acl_keychain.h @@ -40,6 +40,7 @@ class KeychainPromptAclSubject : public SimpleAclSubject { static const Version pumaVersion = 0; // 10.0, 10.1 -> default selector (not stored) static const Version jaguarVersion = 1; // 10.2 et al -> first version selector + static const Version currentVersion = jaguarVersion; // what we write today public: bool validate(const AclValidationContext &baseCtx, const TypedList &sample) const; CssmList toList(Allocator &alloc) const; @@ -49,14 +50,22 @@ public: void exportBlob(Writer::Counter &pub, Writer::Counter &priv); void exportBlob(Writer &pub, Writer &priv); + uint32_t selectorFlags() const { return selector.flags; } + bool selectorFlag(uint32_t flag) const { return selectorFlags() & flag; } + IFDUMP(void debugDump() const); +public: class Maker : public AclSubject::Maker { + friend class KeychainPromptAclSubject; public: - Maker(CSSM_ACL_SUBJECT_TYPE type = CSSM_ACL_SUBJECT_TYPE_KEYCHAIN_PROMPT) - : AclSubject::Maker(type) { } + Maker(uint32_t mode) + : AclSubject::Maker(CSSM_ACL_SUBJECT_TYPE_KEYCHAIN_PROMPT) { defaultMode = mode; } KeychainPromptAclSubject *make(const TypedList &list) const; KeychainPromptAclSubject *make(Version version, Reader &pub, Reader &priv) const; + + private: + static uint32_t defaultMode; }; private: @@ -65,11 +74,6 @@ private: private: static CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR defaultSelector; - - typedef uint32 VersionMarker; - static const VersionMarker currentVersion = 0x3BD5910D; - - bool isLegacyCompatible() const; }; diff --git a/src/acls.cpp b/src/acls.cpp index aa2524a..a366b9d 100644 --- a/src/acls.cpp +++ b/src/acls.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2007 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -30,6 +30,7 @@ #include "server.h" #include "agentquery.h" #include "tokendatabase.h" +#include "acl_keychain.h" // ACL subjects whose Environments we implement #include @@ -53,17 +54,20 @@ SecurityServerAcl::~SecurityServerAcl() // void SecurityServerAcl::getOwner(AclOwnerPrototype &owner) { + StLock _(aclSequence); ObjectAcl::cssmGetOwner(owner); } void SecurityServerAcl::getAcl(const char *tag, uint32 &count, AclEntryInfo *&acls) { + StLock _(aclSequence); ObjectAcl::cssmGetAcl(tag, count, acls); } void SecurityServerAcl::changeAcl(const AclEdit &edit, const AccessCredentials *cred, Database *db) { + StLock _(aclSequence); SecurityServerEnvironment env(*this, db); ObjectAcl::cssmChangeAcl(edit, cred, &env); } @@ -71,6 +75,7 @@ void SecurityServerAcl::changeAcl(const AclEdit &edit, const AccessCredentials * void SecurityServerAcl::changeOwner(const AclOwnerPrototype &newOwner, const AccessCredentials *cred, Database *db) { + StLock _(aclSequence); SecurityServerEnvironment env(*this, db); ObjectAcl::cssmChangeOwner(newOwner, cred, &env); } @@ -94,6 +99,91 @@ void SecurityServerAcl::validate(AclAuthorization auth, const Context &context, } +// +// This helper tries to add the (new) subject given to the ACL +// whose validation is currently proceeding through context. +// This will succeed if the ACL is in standard form, which means +// a ThresholdAclSubject. +// The new subject will be added at the front (so it is checked first +// from now on), and as a side effect we'll notify the client side to +// re-encode the object. +// Returns true if the edit could be done, or false if the ACL wasn't +// standard enough. May throw if the ACL is malformed or otherwise messed up. +// +// This is a self-contained helper that is here merely because it's "about" +// ACLs and has no better home. +// +bool SecurityServerAcl::addToStandardACL(const AclValidationContext &context, AclSubject *subject) +{ + if (SecurityServerEnvironment *env = context.environment()) + if (ThresholdAclSubject *threshold = env->standardSubject(context)) { + unsigned size = threshold->count(); + if (dynamic_cast(threshold->subject(size-1))) { + // looks standard enough + secdebug("acl", "adding new subject %p to from of threshold ACL", subject); + threshold->add(subject, 0); + + // tell the ACL it's been modified + context.acl()->changedAcl(); + + // trigger a special notification code on (otherwise successful) return + Server::connection().overrideReturn(CSSMERR_CSP_APPLE_ADD_APPLICATION_ACL_SUBJECT); + return true; + } + } + secdebug("acl", "ACL is not standard form; cannot edit"); + return false; +} + + +// +// Look at the ACL whose validation is currently proceeding through context. +// If it LOOKS like a plausible version of a legacy "dot mac item" ACL. +// We don't have access to the database attributes of the item up here in the +// securityd sky, so we have to apply a heuristic based on which applications (by path) +// are given access to the item. +// So this is strictly a heuristic. The potential downside is that we may inadvertently +// give access to new .Mac authorized Apple (only) applications when the user only intended +// a limited set of extremely popular Apple (only) applications that just happen to all be +// .Mac authorized today. We can live with that. +// +bool SecurityServerAcl::looksLikeLegacyDotMac(const AclValidationContext &context) +{ + static const char * const prototypicalDotMacPath[] = { + "/Applications/Mail.app", + "/Applications/Safari.app", + "/Applications/iSync.app", + "/Applications/System Preferences.app", + "/Applications/iCal.app", + "/Applications/iChat.app", + "/Applications/iTunes.app", + "/Applications/Address Book.app", + "/Applications/iSync.app", + NULL // sentinel + }; + + static const unsigned threshold = 6; + + if (SecurityServerEnvironment *env = context.environment()) { + if (ThresholdAclSubject *list = env->standardSubject(context)) { + unsigned count = list->count(); + unsigned matches = 0; + for (unsigned n = 0; n < count; ++n) { + if (CodeSignatureAclSubject *app = dynamic_cast(list->subject(n))) { + for (const char * const *p = prototypicalDotMacPath; *p; p++) + if (app->path() == *p) + matches++; + } + } + secdebug("codesign", "matched %d of %zd candididates (threshold=%d)", + matches, sizeof(prototypicalDotMacPath) / sizeof(char *) - 1, threshold); + return matches >= threshold; + } + } + return false; +} + + // // External storage interface // @@ -135,10 +225,10 @@ pid_t SecurityServerEnvironment::getpid() const // // CodeSignatureAclSubject personality: take code signature from active Process object // -bool SecurityServerEnvironment::verifyCodeSignature(const CodeSigning::Signature *signature, - const CssmData *comment) +bool SecurityServerEnvironment::verifyCodeSignature(const OSXVerifier &verifier, + const AclValidationContext &context) { - return Server::codeSignatures().verify(Server::process(), signature, comment); + return Server::codeSignatures().verify(Server::process(), verifier, context); } @@ -184,6 +274,15 @@ ObjectAcl *SecurityServerEnvironment::preAuthSource() } +// +// Autonomous ACL editing support +// +ThresholdAclSubject *SecurityServerEnvironment::standardSubject(const AclValidationContext &context) +{ + return dynamic_cast(context.subject()); +} + + // // The default AclSource denies having an ACL at all // diff --git a/src/acls.h b/src/acls.h index ed8338b..20f9270 100644 --- a/src/acls.h +++ b/src/acls.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2007 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -45,6 +45,7 @@ #include #include #include +#include using namespace SecurityServer; @@ -58,11 +59,11 @@ class Database; // class SecurityServerAcl : public ObjectAcl { public: - SecurityServerAcl() : ObjectAcl(Allocator::standard()) { } + SecurityServerAcl() : ObjectAcl(Allocator::standard()), aclSequence(Mutex::recursive) { } virtual ~SecurityServerAcl(); // validation calls restated - virtual void validate(AclAuthorization auth, const AccessCredentials *cred, Database *relatedDatabase); + virtual void validate(AclAuthorization auth, const AccessCredentials *cred, Database *relatedDatabase); void validate(AclAuthorization auth, const Context &context, Database *relatedDatabase); // CSSM layer ACL calls @@ -76,6 +77,10 @@ public: // to be provided by implementations virtual AclKind aclKind() const = 0; + // a helper to (try to) add an ACL to a "standard form" item ACL + static bool addToStandardACL(const AclValidationContext &context, AclSubject *subject); + static bool looksLikeLegacyDotMac(const AclValidationContext &context); + // aclSequence is taken to serialize ACL validations to pick up mutual changes Mutex aclSequence; }; @@ -83,9 +88,8 @@ public: // // Our implementation of an ACL validation environment uses information -// derived from a Connection object. It implements context for -// -- ProcessAclSubjects (getuid/getgid) -// -- KeychainPromptAclSubjects (connection link) +// derived from a Connection object. It implements context for a fair number +// of subject types (see the inheritance list below). // class SecurityServerEnvironment : public virtual AclValidationEnvironment, public virtual ProcessAclSubject::Environment, @@ -100,14 +104,18 @@ public: SecurityServerAcl &acl; Database * const database; + // personalities uid_t getuid() const; gid_t getgid() const; pid_t getpid() const; - bool verifyCodeSignature(const CodeSigning::Signature *signature, const CssmData *comment); + bool verifyCodeSignature(const OSXVerifier &verifier, const AclValidationContext &context); bool validateSecret(const SecretAclSubject *me, const AccessCredentials *cred); bool getSecret(CssmOwnedData &secret, const CssmData &prompt) const; ObjectAcl *preAuthSource(); Adornable &store(const AclSubject *subject); + + // subject editing + ThresholdAclSubject *standardSubject(const AclValidationContext &context); }; @@ -124,19 +132,22 @@ public: virtual SecurityServerAcl &acl(); // defaults to "no ACL; throw exception" virtual Database *relatedDatabase(); // optionally, a Database related to me - // forward ACL calls, passing some locally obtained stuff along - - void getOwner(AclOwnerPrototype &owner) + // + // Forward ACL calls, passing some locally obtained stuff along. + // These are virtual so an AclSource can override them. Such overrides + // should enhance/post-process rather than replace functionality. + // + virtual void getOwner(AclOwnerPrototype &owner) { return acl().getOwner(owner); } - void getAcl(const char *tag, uint32 &count, AclEntryInfo *&acls) + virtual void getAcl(const char *tag, uint32 &count, AclEntryInfo *&acls) { return acl().getAcl(tag, count, acls); } - void changeAcl(const AclEdit &edit, const AccessCredentials *cred) + virtual void changeAcl(const AclEdit &edit, const AccessCredentials *cred) { return acl().changeAcl(edit, cred, relatedDatabase()); } - void changeOwner(const AclOwnerPrototype &newOwner, const AccessCredentials *cred) + virtual void changeOwner(const AclOwnerPrototype &newOwner, const AccessCredentials *cred) { return acl().changeOwner(newOwner, cred, relatedDatabase()); } - void validate(AclAuthorization auth, const AccessCredentials *cred) + virtual void validate(AclAuthorization auth, const AccessCredentials *cred) { acl().validate(auth, cred, relatedDatabase()); } - void validate(AclAuthorization auth, const Context &context) + virtual void validate(AclAuthorization auth, const Context &context) { acl().validate(auth, context, relatedDatabase()); } }; diff --git a/src/agentquery.cpp b/src/agentquery.cpp index 9878249..55a2129 100644 --- a/src/agentquery.cpp +++ b/src/agentquery.cpp @@ -109,26 +109,21 @@ SecurityAgentQuery::activate() void SecurityAgentQuery::inferHints(Process &thisProcess) { - RefPointer clientCode = thisProcess.clientCode(); - SecurityAgent::RequestorType requestorType = SecurityAgent::unknown; - string bundlePath; - - if (clientCode) - { - string encodedBundle = clientCode->encode(); - char bundleType = (encodedBundle.c_str())[0]; // yay, no accessor - switch(bundleType) - { - case 'b': requestorType = SecurityAgent::bundle; break; - case 't': requestorType = SecurityAgent::tool; break; - } - bundlePath = clientCode->canonicalPath(); - } + string guestPath; + if (SecCodeRef clientCode = thisProcess.currentGuest()) + guestPath = codePath(clientCode); + AuthItemSet processHints = clientHints(SecurityAgent::bundle, guestPath, + thisProcess.pid(), thisProcess.uid()); + mClientHints.insert(processHints.begin(), processHints.end()); +} - AuthItemSet processHints = clientHints(requestorType, bundlePath, thisProcess.pid(), thisProcess.uid()); - mClientHints.insert(processHints.begin(), processHints.end()); +void SecurityAgentQuery::addHint(const char *name, const void *value, UInt32 valueLen, UInt32 flags) +{ + AuthorizationItem item = { name, valueLen, const_cast(value), flags }; + mClientHints.insert(AuthItemRef(item)); } + void SecurityAgentQuery::readChoice() { @@ -230,7 +225,7 @@ Reason QueryKeychainUse::queryUser (const char *database, const char *descriptio hints.insert(mClientHints.begin(), mClientHints.end()); // put action/operation (sint32) into hints - hints.insert(AuthItemRef(AGENT_HINT_ACL_TAG, AuthValueOverlay(sizeof(action), static_cast(&action)))); + hints.insert(AuthItemRef(AGENT_HINT_ACL_TAG, AuthValueOverlay(sizeof(action), static_cast(&action)))); // item name into hints @@ -623,13 +618,6 @@ Reason QueryGenericPassphrase::query(const char *prompt, bool verify, // // Get a DB blob's passphrase--keychain synchronization // - -void QueryDBBlobSecret::addHint(const char *name, const void *value, UInt32 valueLen, UInt32 flags) -{ - AuthorizationItem item = { name, valueLen, const_cast(value), flags }; - mClientHints.insert(AuthItemRef(item)); -} - Reason QueryDBBlobSecret::operator () (DatabaseCryptoCore &dbCore, const DbBlob *secretsBlob) { return query(dbCore, secretsBlob); diff --git a/src/agentquery.h b/src/agentquery.h index 63d244d..f92a15f 100644 --- a/src/agentquery.h +++ b/src/agentquery.h @@ -48,6 +48,7 @@ public: SecurityAgentQuery(const AuthHostType type = securityAgent, Session &session = Server::session()); void inferHints(Process &thisProcess); + void addHint(const char *name, const void *value = NULL, UInt32 valueLen = 0, UInt32 flags = 0); virtual ~SecurityAgentQuery(); @@ -186,8 +187,6 @@ public: QueryDBBlobSecret() { } Reason operator () (DatabaseCryptoCore &dbCore, const DbBlob *secretsBlob); - void addHint(const char *name, const void *value = NULL, UInt32 valueLen = 0, UInt32 flags = 0); - protected: Reason query(DatabaseCryptoCore &dbCore, const DbBlob *secretsBlob); Reason accept(CssmManagedData &passphrase, DatabaseCryptoCore &dbCore, const DbBlob *secretsBlob); diff --git a/src/authhost.cpp b/src/authhost.cpp index a35edf1..bc3f245 100644 --- a/src/authhost.cpp +++ b/src/authhost.cpp @@ -28,22 +28,39 @@ #include #include +#include +#include +#include +#include +static pthread_once_t agent_cred_init = PTHREAD_ONCE_INIT; +static gid_t agent_gid = 92; +static uid_t agent_uid = 92; +void initialize_agent_creds() +{ + struct passwd *agentUser = getpwnam("securityagent"); + if (agentUser) + { + agent_uid = agentUser->pw_uid; + agent_gid = agentUser->pw_gid; + endpwent(); + } +} + AuthHostInstance::AuthHostInstance(Session &session, AuthHostType host) : mHostType(host) { secdebug("authhost", "authhost born (%p)", this); referent(session); session.addReference(*this); + if (host == securityAgent) + pthread_once(&agent_cred_init, initialize_agent_creds); } AuthHostInstance::~AuthHostInstance() { secdebug("authhost", "authhost died (%p)", this); - - // clean up - servicePort ().destroy (); } Session &AuthHostInstance::session() const @@ -83,7 +100,6 @@ AuthHostInstance::childAction() if ((mHostType == userAuthHost) || (mHostType == privilegedAuthHost)) { snprintf(agentExecutable, sizeof(agentExecutable), "%s/Contents/Resources/authorizationhost", path); - secdebug("AuthHostInstance", "execl(%s)", agentExecutable); execl(agentExecutable, agentExecutable, NULL); } @@ -91,25 +107,15 @@ AuthHostInstance::childAction() { snprintf(agentExecutable, sizeof(agentExecutable), "%s/Contents/MacOS/SecurityAgent", path); - struct group *agentGroup = getgrnam("securityagent"); - gid_t agentGID = static_cast(-2); - if (agentGroup) - { - agentGID = agentGroup->gr_gid; - endgrent(); - } + pid_t pid = getpid(); + if ((pid <= 0) || + sysctlbyname("vfs.generic.noremotehang", NULL, NULL, &pid, sizeof(pid))) + syslog(LOG_ERR, "Failed to set vfs.generic.noremotehang for pid(%d)", pid); - struct passwd *agentUser = getpwnam("securityagent"); - uid_t agentUID = static_cast(-2); - if (agentUser) - { - agentUID = agentUser->pw_uid; - endpwent(); - } + setgroups(1, &agent_gid); + setgid(agent_gid); + setuid(agent_uid); - setuid(agentUID); - setgid(agentGID); - CFRef userPrefs(session().copyUserPrefs()); FILE *mbox = tmpfile(); @@ -127,7 +133,7 @@ AuthHostInstance::childAction() } } - secdebug("AuthHostInstance", "execl(%s) as user (%d,%d)", agentExecutable, agentUID, agentGID); + secdebug("AuthHostInstance", "execl(%s) as user (%d,%d)", agentExecutable, agent_uid, agent_gid); execl(agentExecutable, agentExecutable, NULL); } @@ -150,7 +156,8 @@ AuthHostInstance::activate() StLock _(*this); if (state() != alive) { - if (!(session().attributes() & sessionHasGraphicAccess)) + if ((mHostType == securityAgent) && + !(session().attributes() & sessionHasGraphicAccess)) CssmError::throwMe(CSSM_ERRCODE_NO_USER_INTERACTION); Security::MachPlusPlus::StBootstrap bootSaver(session().bootstrapPort()); diff --git a/src/authority.cpp b/src/authority.cpp index 8e328cb..dd48354 100644 --- a/src/authority.cpp +++ b/src/authority.cpp @@ -54,14 +54,17 @@ Mutex AuthorizationToken::authMapLock; // lock for mAuthorizations (only) // Create an authorization token. // AuthorizationToken::AuthorizationToken(Session &ssn, const CredentialSet &base, -const audit_token_t &auditToken) +const audit_token_t &auditToken, bool operateAsLeastPrivileged) : mBaseCreds(base), mTransferCount(INT_MAX), - mCreatorCode(Server::process().clientCode()), mCreatorPid(Server::process().pid()), - mCreatorAuditToken(auditToken) + mCreatorAuditToken(auditToken), + mOperatesAsLeastPrivileged(operateAsLeastPrivileged) { mCreatorUid = mCreatorAuditToken.euid(); mCreatorGid = mCreatorAuditToken.egid(); + + if (SecCodeRef code = Server::process().currentGuest()) + MacOSError::check(SecCodeCopyStaticCode(code, kSecCSDefaultFlags, &mCreatorCode.aref())); // link to session referent(ssn); @@ -74,9 +77,8 @@ const audit_token_t &auditToken) authMap[mHandle] = this; // all ready - secdebug("SSauth", "Authorization %p created using %d credentials; owner=%s", - this, int(mBaseCreds.size()), - mCreatorCode ? mCreatorCode->encode().c_str() : "unknown"); + secdebug("SSauth", "Authorization %p created using %d credentials; owner=%p", + this, int(mBaseCreds.size()), mCreatorCode.get()); } AuthorizationToken::~AuthorizationToken() @@ -254,7 +256,7 @@ AuthorizationToken::setCredentialInfo(const Credential &inCred) AuthItemRef uidHint("uid", AuthValueOverlay(uid_string ? strlen(uid_string) + 1 : 0, uid_string), 0); dstInfoSet.insert(uidHint); - AuthItemRef userHint("username", AuthValueOverlay(inCred->username()), 0); + AuthItemRef userHint("username", AuthValueOverlay(inCred->name()), 0); dstInfoSet.insert(userHint); setInfoSet(dstInfoSet); diff --git a/src/authority.h b/src/authority.h index 7c70d98..044ffee 100644 --- a/src/authority.h +++ b/src/authority.h @@ -28,14 +28,15 @@ #ifndef _H_AUTHORITY #define _H_AUTHORITY -#include #include #include #include "database.h" +#include "credential.h" +#include +using Authorization::AuthItemSet; using Authorization::Credential; using Authorization::CredentialSet; -using Authorization::AuthItemSet; using Security::CommonCriteria::AuditToken; class Process; @@ -43,7 +44,7 @@ class Session; class AuthorizationToken : public PerSession { public: - AuthorizationToken(Session &ssn, const CredentialSet &base, const audit_token_t &auditToken); + AuthorizationToken(Session &ssn, const CredentialSet &base, const audit_token_t &auditToken, bool operateAsLeastPrivileged = false); ~AuthorizationToken(); Session &session() const; @@ -69,7 +70,7 @@ public: uid_t creatorUid() const { return mCreatorUid; } gid_t creatorGid() const { return mCreatorGid; } - OSXCode *creatorCode() const { return mCreatorCode; } + SecStaticCodeRef creatorCode() const { return mCreatorCode; } pid_t creatorPid() const { return mCreatorPid; } const AuditToken &creatorAuditToken() const { return mCreatorAuditToken; } @@ -79,6 +80,7 @@ public: void setCredentialInfo(const Credential &inCred); void clearInfoSet(); void scrubInfoSet(); + bool operatesAsLeastPrivileged() const { return mOperatesAsLeastPrivileged; } public: static AuthorizationToken &find(const AuthorizationBlob &blob); @@ -107,20 +109,19 @@ private: uid_t mCreatorUid; // Uid of process that created this authorization gid_t mCreatorGid; // Gid of process that created this authorization - RefPointer mCreatorCode; // code id of creator + CFCopyRef mCreatorCode; // code reference to creator pid_t mCreatorPid; // Pid of processs that created this authorization AuditToken mCreatorAuditToken; // Audit token of the process that created this authorization AuthItemSet mInfoSet; // Side band info gathered from evaluations in this session + bool mOperatesAsLeastPrivileged; + private: typedef map > AuthMap; static AuthMap &authMap; // set of extant authorizations static Mutex authMapLock; // lock for mAuthorizations (only) }; - - - #endif //_H_AUTHORITY diff --git a/src/child.cpp b/src/child.cpp index 2a5db79..a8cd2b0 100644 --- a/src/child.cpp +++ b/src/child.cpp @@ -56,6 +56,8 @@ ServerChild::ServerChild() // ServerChild::~ServerChild() { + mServicePort.destroy(); + if (state() == alive) { this->kill(SIGTERM); // shoot it once checkChildren(); // check for quick death diff --git a/src/clientid.cpp b/src/clientid.cpp new file mode 100644 index 0000000..b04b7c6 --- /dev/null +++ b/src/clientid.cpp @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2006-2007 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +// +// clientid - track and manage identity of securityd clients +// +#include "clientid.h" +#include "server.h" +#include "osxcodewrap.h" + + +// +// Constructing a ClientIdentification doesn't do much. +// We're waiting for setup(), which should be called by the child class's +// constructor. +// +ClientIdentification::ClientIdentification() +{ +} + + +// +// Initialize the ClientIdentification. +// This creates a process-level code object for the client. +// +void ClientIdentification::setup(pid_t pid) +{ + if (IFDEBUG(OSStatus rc =)SecCodeCreateWithPID(pid, kSecCSDefaultFlags, + &mClientProcess.aref())) + secdebug("clientid", "could not get code for process %d: OSStatus=%ld", + pid, rc); +} + + +// +// Return a SecCodeRef for the client process itself, regardless of +// which guest within it is currently active. +// Think twice before using this. +// +SecCodeRef ClientIdentification::processCode() const +{ + return mClientProcess; +} + + +// +// Return a SecCodeRef for the currently active guest within the client +// process. +// +// We make a fair effort to cache client guest identities without over-growing +// the cache. Note that there's currently no protocol for being notified of +// a guest's death or disappearance (independent from the host process's death), +// so we couldn't track guests live even if we tried. +// +// Note that this consults Server::connection for the currently serviced +// Connection object, so this is not entirely a function of ClientIdentification state. +// +SecCodeRef ClientIdentification::currentGuest() const +{ + if (GuestState *guest = current()) + return guest->code; + else + return mClientProcess; +} + +ClientIdentification::GuestState *ClientIdentification::current() const +{ + // if we have no client identification, we can't find a current guest either + if (!processCode()) + return NULL; + + SecGuestRef guestRef = Server::connection().guestRef(); + + // try to deliver an already-cached entry + { + StLock _(mLock); + GuestMap::iterator it = mGuests.find(guestRef); + if (it != mGuests.end()) + return &it->second; + } + + // okay, make a new one (this may take a while) + CFRef attributes = (guestRef == kSecNoGuest) + ? NULL + : makeCFDictionary(1, kSecGuestAttributeCanonical, CFTempNumber(guestRef).get()); + Server::active().longTermActivity(); + CFRef code; + switch (OSStatus rc = SecCodeCopyGuestWithAttributes(processCode(), + attributes, kSecCSDefaultFlags, &code.aref())) { + case noErr: + break; + case errSecCSUnsigned: // not signed; clearly not a host + case errSecCSNotAHost: // signed but not marked as a (potential) host + code = mClientProcess; + break; + case errSecCSNoSuchCode: // potential host, but... + if (guestRef == kSecNoGuest) { // ... no guests (yet), so return the process + code = mClientProcess; + break; + } + // else fall through // ... the guest we expected to be there isn't + default: + MacOSError::throwMe(rc); + } + StLock _(mLock); + GuestState &slot = mGuests[guestRef]; + if (!slot.code) // if another thread didn't get here first... + slot.code = code; + return &slot; +} + + +// +// Support for the legacy hash identification mechanism. +// The legacy machinery deals exclusively in terms of processes. +// It knows nothing about guests and their identities. +// +string ClientIdentification::getPath() const +{ + assert(mClientProcess); + return codePath(currentGuest()); +} + +const CssmData ClientIdentification::getHash() const +{ + if (GuestState *guest = current()) { + if (!guest->gotHash) { + RefPointer clientCode = new OSXCodeWrap(guest->code); + OSXVerifier::makeLegacyHash(clientCode, guest->legacyHash); + guest->gotHash = true; + } + return CssmData::wrap(guest->legacyHash, SHA1::digestLength); + } else + return CssmData(); +} + + +// +// Bonus function: get the path out of a SecCodeRef +// +std::string codePath(SecStaticCodeRef code) +{ + CFRef path; + MacOSError::check(SecCodeCopyPath(code, kSecCSDefaultFlags, &path.aref())); + return cfString(path); +} + + +// +// Debug dump support +// +#if defined(DEBUGDUMP) + +static void dumpCode(SecCodeRef code) +{ + CFRef path; + if (OSStatus rc = SecCodeCopyPath(code, kSecCSDefaultFlags, &path.aref())) + Debug::dump("unknown(rc=%ld)", rc); + else + Debug::dump("%s", cfString(path).c_str()); +} + +void ClientIdentification::dump() +{ + Debug::dump(" client="); + dumpCode(mClientProcess); + for (GuestMap::const_iterator it = mGuests.begin(); it != mGuests.end(); ++it) { + Debug::dump(" guest(0x%x)=", it->first); + dumpCode(it->second.code); + if (it->second.gotHash) + Debug::dump(" [got hash]"); + } +} + +#endif //DEBUGDUMP diff --git a/src/clientid.h b/src/clientid.h new file mode 100644 index 0000000..c961284 --- /dev/null +++ b/src/clientid.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +// +// clientid - track and manage identity of securityd clients +// +#ifndef _H_CLIENTID +#define _H_CLIENTID + +#include "codesigdb.h" +#include +#include +#include + + +// +// A ClientIdentification object is a mix-in class that tracks +// the identity of associated client processes and their sub-entities +// (aka Code Signing Guest objects). +// +class ClientIdentification : public CodeSignatures::Identity { +public: + ClientIdentification(); + + SecCodeRef processCode() const; + SecCodeRef currentGuest() const; + + // CodeSignatures::Identity personality + string getPath() const; + const CssmData getHash() const; + +protected: + void setup(pid_t pid); + +public: + IFDUMP(void dump()); + +private: + CFRef mClientProcess; // process-level client object + + mutable Mutex mLock; // protects everything below + + struct GuestState { + GuestState() : gotHash(false) { } + CFRef code; + mutable bool gotHash; + mutable SHA1::Digest legacyHash; + }; + typedef std::map GuestMap; + mutable GuestMap mGuests; + + GuestState *current() const; +}; + + +// +// Bonus function +// +std::string codePath(SecStaticCodeRef code); + + +#endif //_H_CLIENTID diff --git a/src/codesigdb.cpp b/src/codesigdb.cpp index 4ff3d64..411f8ec 100644 --- a/src/codesigdb.cpp +++ b/src/codesigdb.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003-2007 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -28,6 +28,7 @@ #include "codesigdb.h" #include "process.h" #include "server.h" +#include "osxcodewrap.h" #include "agentquery.h" #include #include @@ -65,20 +66,15 @@ DbKey::DbKey(char type, const CssmData &key, bool perUser, uid_t user) // // A subclass of Identity made of whole cloth (from a raw CodeSignature ACL information) // -class AclIdentity : public CodeSignatures::Identity { -public: - AclIdentity(const CodeSigning::Signature *sig, const char *comment) - : mHash(*sig), mPath(comment ? comment : "") { } - AclIdentity(const CssmData &hash, const char *comment) - : mHash(hash), mPath(comment ? comment : "") { } +struct AclIdentity : public CodeSignatures::Identity { + AclIdentity(const CssmData hash, string path) : mHash(hash), mPath(path) { } -protected: - std::string getPath() const { return mPath; } - const CssmData getHash(CodeSigning::OSXSigner &) const { return mHash; } - + string getPath() const { return mPath; } + const CssmData getHash() const { return mHash; } + private: const CssmData mHash; - std::string mPath; + const string mPath; }; @@ -116,8 +112,7 @@ CodeSignatures::~CodeSignatures() void CodeSignatures::open(const char *path) { mDb.open(path, O_RDWR | O_CREAT, 0644); - if (mDb) - mDb.flush(); + mDb.flush(); IFDUMPING("equiv", debugDump("reopen")); } @@ -145,12 +140,10 @@ string CodeSignatures::Identity::canonicalName(const string &path) // bool CodeSignatures::find(Identity &id, uid_t user) { - if (!mDb) - return false; if (id.mState != Identity::untried) return id.mState == Identity::valid; try { - DbKey userKey('H', id.getHash(mSigner), true, user); + DbKey userKey('H', id.getHash(), true, user); CssmData linkValue; if (mDb.get(userKey, linkValue)) { id.mName = string(linkValue.interpretedAs(), linkValue.length()); @@ -158,7 +151,7 @@ bool CodeSignatures::find(Identity &id, uid_t user) id.mState = Identity::valid; return true; } - DbKey sysKey('H', id.getHash(mSigner)); + DbKey sysKey('H', id.getHash()); if (mDb.get(sysKey, linkValue)) { id.mName = string(linkValue.interpretedAs(), linkValue.length()); IFDUMPING("equiv", id.debugDump("found/system")); @@ -174,18 +167,11 @@ bool CodeSignatures::find(Identity &id, uid_t user) void CodeSignatures::makeLink(Identity &id, const string &ident, bool forUser, uid_t user) { - if (!mDb) - UnixError::throwMe(ENOENT); - DbKey key('H', id.getHash(mSigner), forUser, user); + DbKey key('H', id.getHash(), forUser, user); if (!mDb.put(key, StringData(ident))) UnixError::throwMe(); } -void CodeSignatures::makeApplication(const std::string &name, const std::string &path) -{ - //@@@ create app record and fill (later) -} - // // Administrative manipulation calls @@ -199,8 +185,8 @@ void CodeSignatures::addLink(const CssmData &oldHash, const CssmData &newHash, UnixError::throwMe(EACCES); if (!forSystem) // in fact, for now we don't allow per-user calls at all UnixError::throwMe(EACCES); - AclIdentity oldCode(oldHash, name.c_str()); - AclIdentity newCode(newHash, name.c_str()); + AclIdentity oldCode(oldHash, name); + AclIdentity newCode(newHash, name); secdebug("codesign", "addlink for name %s", name.c_str()); StLock _(mDatabaseLock); if (oldCode) { @@ -219,8 +205,6 @@ void CodeSignatures::addLink(const CssmData &oldHash, const CssmData &newHash, void CodeSignatures::removeLink(const CssmData &hash, const char *name, bool forSystem) { - if (!mDb) - UnixError::throwMe(ENOENT); AclIdentity code(hash, name); uid_t user = Server::process().uid(); if (forSystem && user) // only root user can remove forSystem links @@ -233,24 +217,189 @@ void CodeSignatures::removeLink(const CssmData &hash, const char *name, bool for // -// Verify signature matches +// Verify signature matches. +// This ends up getting called when a CodeSignatureAclSubject is validated. +// The OSXVerifier describes what we require of the client code; the process represents +// the requesting client; and the context gives us access to the ACL and its environment +// in case we want to, well, creatively rewrite it for some reason. // bool CodeSignatures::verify(Process &process, - const CodeSigning::Signature *trustedSignature, const CssmData *comment) + const OSXVerifier &verifier, const AclValidationContext &context) { secdebug("codesign", "start verify"); // if we have no client code, we cannot possibly match this - if (!process.clientCode()) { + SecCodeRef code = process.currentGuest(); + if (!code) { secdebug("codesign", "no code base: fail"); return false; } + + if (SecRequirementRef requirement = verifier.requirement()) { + // If the ACL contains a code signature (requirement), we won't match against unsigned code at all. + // The legacy hash is ignored (it's for use by pre-Leopard systems). + secdebug("codesign", "CS requirement present; ignoring legacy hashes"); + Server::active().longTermActivity(); + switch (IFDEBUG(OSStatus rc =) SecCodeCheckValidity(code, kSecCSDefaultFlags, requirement)) { + case noErr: + secdebug("codesign", "CS verify passed"); + return true; + case errSecCSUnsigned: + secdebug("codesign", "CS verify against unsigned binary failed"); + return false; + default: + secdebug("codesign", "CS verify failed OSStatus=%ld", rc); + return false; + } + } + switch (matchSignedClientToLegacyACL(process, code, verifier, context)) { + case noErr: // handled, allow access + return true; + case errSecCSUnsigned: // unsigned client, complete legacy case + secdebug("codesign", "no CS requirement - using legacy hash"); + return verifyLegacy(process, + CssmData::wrap(verifier.legacyHash(), SHA1::digestLength), + verifier.path()); + default: // client unsuitable, reject this match + return false; + } +} + + +// +// See if we can rewrite the ACL from legacy to Code Signing form without losing too much security. +// Returns true if the present validation should succeed (we probably rewrote the ACL). +// Returns false if the present validation shouldn't succeed based on what we did here (we may still +// have rewritten the ACL, in principle). +// +// Note that these checks add nontrivial overhead to ACL processing. We want to eventually phase +// this out, or at least make it an option that doesn't run all the time - perhaps an "extra legacy +// effort" per-client mode bit. +// +static string trim(string s, char delimiter) +{ + string::size_type p = s.rfind(delimiter); + if (p != string::npos) + s = s.substr(p + 1); + return s; +} + +static string trim(string s, char delimiter, string suffix) +{ + s = trim(s, delimiter); + int preLength = s.length() - suffix.length(); + if (preLength > 0 && s.substr(preLength) == suffix) + s = s.substr(0, preLength); + return s; +} + +OSStatus CodeSignatures::matchSignedClientToLegacyACL(Process &process, + SecCodeRef code, const OSXVerifier &verifier, const AclValidationContext &context) +{ + // + // Check whether we seem to be matching a legacy .Mac ACL against a member of the .Mac group + // + if (SecurityServerAcl::looksLikeLegacyDotMac(context)) { + Server::active().longTermActivity(); + CFRef dotmac; + MacOSError::check(SecRequirementCreateGroup(CFSTR("dot-mac"), NULL, kSecCSDefaultFlags, &dotmac.aref())); + if (SecCodeCheckValidity(code, kSecCSDefaultFlags, dotmac) == noErr) { + secdebug("codesign", "client is a dot-mac application; update the ACL accordingly"); + + // create a suitable AclSubject (this is the above-the-API-line way) + CFRef reqdata; + MacOSError::check(SecRequirementCopyData(dotmac, kSecCSDefaultFlags, &reqdata.aref())); + RefPointer subject = new CodeSignatureAclSubject(NULL, "group://dot-mac"); + subject->add((const BlobCore *)CFDataGetBytePtr(reqdata)); + + // add it to the ACL and pass the access check (we just quite literally did it above) + SecurityServerAcl::addToStandardACL(context, subject); + return noErr; + } + } - // first of all, if the signature directly matches the client's code, we're obviously fine + // + // Get best names for the ACL (legacy) subject and the (signed) client + // + CFRef info; + MacOSError::check(SecCodeCopySigningInformation(code, kSecCSSigningInformation, &info.aref())); + CFStringRef signingIdentity = CFStringRef(CFDictionaryGetValue(info, kSecCodeInfoIdentifier)); + if (!signingIdentity) // unsigned + return errSecCSUnsigned; + + string bundleName; // client + if (CFDictionaryRef infoList = CFDictionaryRef(CFDictionaryGetValue(info, kSecCodeInfoPList))) + if (CFStringRef name = CFStringRef(CFDictionaryGetValue(infoList, kCFBundleNameKey))) + bundleName = trim(cfString(name), '.'); + if (bundleName.empty()) // fall back to signing identifier + bundleName = trim(cfString(signingIdentity), '.'); + + string aclName = trim(verifier.path(), '/', ".app"); // ACL + + secdebug("codesign", "matching signed client \"%s\" against legacy ACL \"%s\"", + bundleName.c_str(), aclName.c_str()); + + // + // Check whether we're matching a signed APPLE application against a legacy ACL by the same name + // + if (bundleName == aclName) { + const unsigned char reqData[] = { // "anchor apple", version 1 blob, embedded here + 0xfa, 0xde, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03 + }; + CFRef apple; + MacOSError::check(SecRequirementCreateWithData(CFTempData(reqData, sizeof(reqData)), + kSecCSDefaultFlags, &apple.aref())); + Server::active().longTermActivity(); + switch (OSStatus rc = SecCodeCheckValidity(code, kSecCSDefaultFlags, apple)) { + case noErr: + { + secdebug("codesign", "withstands strict scrutiny; quietly adding new ACL"); + RefPointer wrap = new OSXCodeWrap(code); + RefPointer subject = new CodeSignatureAclSubject(OSXVerifier(wrap)); + SecurityServerAcl::addToStandardACL(context, subject); + return noErr; + } + default: + secdebug("codesign", "validation fails with rc=%ld, rejecting", rc); + return rc; + } + secdebug("codesign", "does not withstand strict scrutiny; ask the user"); + QueryCodeCheck query; + query.inferHints(process); + if (!query(verifier.path().c_str())) { + secdebug("codesign", "user declined equivalence: cancel the access"); + CssmError::throwMe(CSSM_ERRCODE_USER_CANCELED); + } + RefPointer wrap = new OSXCodeWrap(code); + RefPointer subject = new CodeSignatureAclSubject(OSXVerifier(wrap)); + SecurityServerAcl::addToStandardACL(context, subject); + return noErr; + } + + // not close enough to even ask - this can't match + return errSecCSReqFailed; +} + + +// +// Perform legacy hash verification. +// This is the pre-Leopard (Tiger, Panther) code path. Here we only have legacy hashes +// (called, confusingly, "signatures"), which we're matching against suitably computed +// "signatures" (hashes) on the requesting application. We consult the CodeEquivalenceDatabase +// in a doomed attempt to track changes made to applications through updates, and issue +// equivalence dialogs to users if we have a name match (but hash mismatch). That's all +// there was before Code Signing; and that's what you'll continue to get if the requesting +// application is unsigned. Until we throw the whole mess out altogether, hopefully by +// the Next Big Cat After Leopard. +// +bool CodeSignatures::verifyLegacy(Process &process, const CssmData &signature, string path) +{ + // First of all, if the signature directly matches the client's code, we're obviously fine // we don't even need the database for that... Identity &clientIdentity = process; try { - if (clientIdentity.getHash(mSigner) == CssmData(*trustedSignature)) { + if (clientIdentity.getHash() == signature) { secdebug("codesign", "direct match: pass"); return true; } @@ -259,14 +408,8 @@ bool CodeSignatures::verify(Process &process, return false; } - // don't bother the user if the db is MIA - if (!mDb) { - secdebug("codesign", "database not open; cannot verify"); - return false; - } - - // ah well. Establish mediator objects for database signature links - AclIdentity aclIdentity(trustedSignature, comment ? comment->interpretedAs() : NULL); + // Ah well. Establish mediator objects for database signature links + AclIdentity aclIdentity(signature, path); uid_t user = process.uid(); { @@ -297,8 +440,7 @@ bool CodeSignatures::verify(Process &process, // The names match - we have a possible update. // Take the UI lock now to serialize "update rushes". - Server::active().longTermActivity(); - StLock uiLocker(mUILock); + LongtermStLock uiLocker(mUILock); // re-read the database in case some other thread beat us to the update { @@ -315,14 +457,14 @@ bool CodeSignatures::verify(Process &process, return false; } } - + // ask the user QueryCodeCheck query; query.inferHints(process); if (!query(aclIdentity.path().c_str())) { - secdebug("codesign", "user declined equivalence: fail"); - return false; + secdebug("codesign", "user declined equivalence: cancel the access"); + CssmError::throwMe(CSSM_ERRCODE_USER_CANCELED); } // take the database lock back for real @@ -349,7 +491,6 @@ bool CodeSignatures::verify(Process &process, // the De Novo case: no links, must create everything string ident = clientIdentity.name(); - makeApplication(ident, clientIdentity.path()); makeLink(clientIdentity, ident, true, user); makeLink(aclIdentity, ident, true, user); mDb.flush(); @@ -370,24 +511,20 @@ void CodeSignatures::debugDump(const char *how) const if (!how) how = "dump"; CssmData key, value; - if (!mDb) { - dump("CODE EQUIVALENTS DATABASE IS NOT OPEN (%s)", how); + if (!mDb.first(key, value)) { + dump("CODE EQUIVALENTS DATABASE IS EMPTY (%s)\n", how); } else { - if (!mDb.first(key, value)) { - dump("CODE EQUIVALENTS DATABASE IS EMPTY (%s)\n", how); - } else { - dump("CODE EQUIVALENTS DATABASE DUMP (%s)\n", how); - do { - const char *header = key.interpretedAs(); - size_t headerLength = strlen(header) + 1; - dump("%s:", header); - dumpData(key.at(headerLength), key.length() - headerLength); - dump(" => "); - dumpData(value); - dump("\n"); - } while (mDb.next(key, value)); - dump("END DUMP\n"); - } + dump("CODE EQUIVALENTS DATABASE DUMP (%s)\n", how); + do { + const char *header = key.interpretedAs(); + size_t headerLength = strlen(header) + 1; + dump("%s:", header); + dumpData(key.at(headerLength), key.length() - headerLength); + dump(" => "); + dumpData(value); + dump("\n"); + } while (mDb.next(key, value)); + dump("END DUMP\n"); } } @@ -398,9 +535,8 @@ void CodeSignatures::Identity::debugDump(const char *how) const how = "dump"; dump("IDENTITY (%s) path=%s", how, getPath().c_str()); dump(" name=%s hash=", mName.empty() ? "(unset)" : mName.c_str()); - CodeSigning::OSXSigner signer; - dumpData(getHash(signer)); + dumpData(getHash()); dump("\n"); } -#endif //DEBUGDUMP \ No newline at end of file +#endif //DEBUGDUMP diff --git a/src/codesigdb.h b/src/codesigdb.h index 5b38e04..02cf40f 100644 --- a/src/codesigdb.h +++ b/src/codesigdb.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003-2007 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -28,8 +28,10 @@ #ifndef _H_CODESIGDB #define _H_CODESIGDB +#include "acls.h" #include -#include +#include +#include class Process; @@ -64,7 +66,7 @@ public: IFDUMP(void debugDump(const char *how = NULL) const); virtual std::string getPath() const = 0; - virtual const CssmData getHash(CodeSigning::OSXSigner &signer) const = 0; + virtual const CssmData getHash() const = 0; private: enum { untried, valid, invalid } mState; @@ -81,7 +83,6 @@ public: bool find(Identity &id, uid_t user); void makeLink(Identity &id, const std::string &ident, bool forUser = false, uid_t user = 0); - void makeApplication(const std::string &name, const std::string &path); void addLink(const CssmData &oldHash, const CssmData &newHash, const char *name, bool forSystem); @@ -90,12 +91,15 @@ public: IFDUMP(void debugDump(const char *how = NULL) const); public: - bool verify(Process &process, - const CodeSigning::Signature *trustedSignature, const CssmData *comment); + bool verify(Process &process, const OSXVerifier &verifier, const AclValidationContext &context); + +private: + OSStatus matchSignedClientToLegacyACL(Process &process, SecCodeRef code, + const OSXVerifier &verifier, const AclValidationContext &context); + bool verifyLegacy(Process &process, const CssmData &signature, string path); private: UnixPlusPlus::UnixDb mDb; - CodeSigning::OSXSigner mSigner; // lock hierarchy: mUILock first, then mDatabaseLock, no back-off Mutex mDatabaseLock; // controls mDb access diff --git a/src/connection.cpp b/src/connection.cpp index ba2e64c..ea4fbd7 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2007 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -49,8 +49,7 @@ // Construct a Connection object. // Connection::Connection(Process &proc, Port rPort) - : mClientPort(rPort), state(idle), agentWait(NULL), - aclUpdateTrigger(NULL) + : mClientPort(rPort), mGuestRef(kSecNoGuest), state(idle), agentWait(NULL) { parent(proc); @@ -73,6 +72,16 @@ Connection::~Connection() } +// +// Set the (last known) guest handle for this connection. +// +void Connection::guestRef(SecGuestRef newGuest, SecCSFlags flags) +{ + secdebug("SS", "Connection %p switches to guest 0x%x", this, newGuest); + mGuestRef = newGuest; +} + + // // Terminate a Connection normally. // This is assumed to be properly sequenced, so no thread races are possible. @@ -125,6 +134,7 @@ void Connection::beginWork() switch (state) { case idle: state = busy; + mOverrideReturn = CSSM_OK; // clear override break; case busy: secdebug("SS", "Attempt to re-enter connection %p(port %d)", this, mClientPort.port()); @@ -148,20 +158,12 @@ void Connection::checkWork() } } -void Connection::endWork() +void Connection::endWork(CSSM_RETURN &rcode) { switch (state) { case busy: - // process the n-step aclUpdateTrigger - if (aclUpdateTrigger) { - if (--aclUpdateTriggerCount == 0) { - aclUpdateTrigger = NULL; - secdebug("kcacl", "acl update trigger expires"); - } else - secdebug("kcacl", "acl update trigger armed for %d calls", - aclUpdateTriggerCount); - } - // end involvement + if (mOverrideReturn && rcode == CSSM_OK) + rcode = mOverrideReturn; state = idle; return; case dying: diff --git a/src/connection.h b/src/connection.h index 72d5d80..551c888 100644 --- a/src/connection.h +++ b/src/connection.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2007 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -29,10 +29,9 @@ #define _H_CONNECTION #include -#include #include "process.h" #include "session.h" -#include "key.h" +#include "notifications.h" #include using MachPlusPlus::Port; @@ -43,12 +42,15 @@ class Session; // // A Connection object represents an established connection between a client -// and securityd. Note that in principle, a client process can have -// multiple Connections (each represented by an IPC channel), though there will -// usually be only one. +// and securityd. There is a separate Connection object for each Mach reply port +// that was (ever) used to talk to securityd. In practice, this maps to one reply +// port (and thus one Connection) for each client thread that (ever) talks to securityd. // -class Connection : public PerConnection { - typedef Key::Handle KeyHandle; +// If a client tricked us into using multiple reply ports from one thread, we'd treat +// them as distinct client threads (which really doesn't much matter to us). The standard +// client library (libsecurityd) won't let you do that. +// +class Connection : public PerConnection, public Listener::JitterBuffer { public: Connection(Process &proc, Port rPort); virtual ~Connection(); @@ -56,28 +58,31 @@ public: void abort(bool keepReplyPort = false); // abnormal termination Port clientPort() const { return mClientPort; } + + // Code Signing guest management - tracks current guest id in client + SecGuestRef guestRef() const { return mGuestRef; } + void guestRef(SecGuestRef newGuest, SecCSFlags flags = 0); // work framing - called as work threads pick up connection work void beginWork(); // I've got it void checkWork(); // everything still okay? - void endWork(); // Done with this + void endWork(CSSM_RETURN &rcode); // Done with this // notify that a SecurityAgent call may hang the active worker thread for a while void useAgent(SecurityAgent::Client *client) { StLock _(*this); agentWait = client; } - // special UI convenience - set a don't-ask-again trigger for Keychain-style ACLs - void setAclUpdateTrigger(const SecurityServerAcl &object) - { aclUpdateTrigger = &object; aclUpdateTriggerCount = aclUpdateTriggerLimit + 1; } - bool aclWasSetForUpdateTrigger(const SecurityServerAcl &object) const - { return aclUpdateTriggerCount > 0 && aclUpdateTrigger == &object; } + // set an overriding CSSM_RETURN to return instead of success + void overrideReturn(CSSM_RETURN rc) { mOverrideReturn = rc; } Process &process() const { return parent(); } Session &session() const { return process().session(); } private: // peer state: established during connection startup; fixed thereafter - Port mClientPort; + Port mClientPort; // client's Mach reply port + SecGuestRef mGuestRef; // last known Code Signing guest reference for this client thread + CSSM_RETURN mOverrideReturn; // override successful return code (only) // transient state (altered as we go) enum State { @@ -86,11 +91,6 @@ private: dying // busy and scheduled to die as soon as possible } state; SecurityAgent::Client *agentWait; // SA client session we may be waiting on - - // see KeychainPromptAclSubject in acl_keychain.cpp for more information on this - const SecurityServerAcl *aclUpdateTrigger; // update trigger set for this (NULL if none) - uint8 aclUpdateTriggerCount; // number of back-to-back requests honored - static const uint8 aclUpdateTriggerLimit = 3; // 3 calls (getAcl+getOwner+changeAcl) }; diff --git a/src/credential.cpp b/src/credential.cpp new file mode 100644 index 0000000..eab7c83 --- /dev/null +++ b/src/credential.cpp @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include "credential.h" +#include +#include + +#include +extern "C" int checkpw_internal( const struct passwd *pw, const char* password ); +#include "server.h" + +namespace Authorization { + +// default credential: invalid for everything, needed as a default session credential +CredentialImpl::CredentialImpl() : mUid(0), mShared(false), mName(""), mRealname(""), mCreationTime(CFAbsoluteTimeGetCurrent()), mValid(false), mRight(false) +{ +} + +// only for testing whether this credential is usable +CredentialImpl::CredentialImpl(const uid_t uid, const string &username, const string &realname, bool shared) : mUid(uid), mShared(shared), mName(username), mRealname(realname), mCreationTime(CFAbsoluteTimeGetCurrent()), mValid(true), mRight(false) +{ +} + +CredentialImpl::CredentialImpl(const string &username, const string &password, bool shared) : mShared(shared), mName(username), mCreationTime(CFAbsoluteTimeGetCurrent()), mValid(false), mRight(false) +{ + Server::active().longTermActivity(); + const char *user = username.c_str(); + struct passwd *pw = getpwnam(user); + + do { + if (!pw) { + syslog(LOG_ERR, "getpwnam() failed for user %s, creating invalid credential", user); + break; + } + + mUid = pw->pw_uid; + mName = pw->pw_name; + mRealname = pw->pw_gecos; + + const char *passwd = password.c_str(); + int checkpw_status = checkpw_internal(pw, passwd); + + if (checkpw_status != CHECKPW_SUCCESS) { + syslog(LOG_ERR, "checkpw() returned %d; failed to authenticate user %s (uid %lu).", checkpw_status, pw->pw_name, pw->pw_uid); + break; + } + + syslog(LOG_INFO, "checkpw() succeeded, creating%s credential for user %s", mShared ? " shared" : "", user); + + mValid = true; + + endpwent(); + } while (0); +} + +CredentialImpl::CredentialImpl(const string &right, bool shared) : mUid(-2), mShared(shared), mName(right), mCreationTime(CFAbsoluteTimeGetCurrent()), mValid(true), mRight(true) +{ +} + +CredentialImpl::~CredentialImpl() +{ +} + +bool +CredentialImpl::operator < (const CredentialImpl &other) const +{ + if (!mShared && other.mShared) + return true; + if (!other.mShared && mShared) + return false; + + return mUid < other.mUid; +} + +// Returns true if this CredentialImpl should be shared. +bool +CredentialImpl::isShared() const +{ + return mShared; +} + +// Merge with other +void +CredentialImpl::merge(const CredentialImpl &other) +{ + assert(mUid == other.mUid); + + if (other.mValid && (!mValid || mCreationTime < other.mCreationTime)) + { + mCreationTime = other.mCreationTime; + mValid = true; + } +} + +// The time at which this credential was obtained. +CFAbsoluteTime +CredentialImpl::creationTime() const +{ + return mCreationTime; +} + +// Return true iff this credential is valid. +bool +CredentialImpl::isValid() const +{ + return mValid; +} + +void +CredentialImpl::invalidate() +{ + mValid = false; +} + +// +// Credential class +// +Credential::Credential() : +RefPointer(new CredentialImpl()) +{ +} + +Credential::Credential(CredentialImpl *impl) : +RefPointer(impl) +{ +} + +Credential::Credential(const uid_t uid, const string &username, const string &realname, bool shared) : +RefPointer(new CredentialImpl(uid, username, realname, shared)) +{ +} + +Credential::Credential(const string &username, const string &password, bool shared) : RefPointer(new CredentialImpl(username, password, shared)) +{ +} + +Credential::Credential(const string &right, bool shared) : RefPointer(new CredentialImpl(right, shared)) +{ +} + +Credential::~Credential() +{ +} + +bool +Credential::operator < (const Credential &other) const +{ + if (!*this) + return other; + + if (!other) + return false; + + return (**this) < (*other); +} + +} // end namespace Authorization + + diff --git a/src/credential.h b/src/credential.h new file mode 100644 index 0000000..78363ee --- /dev/null +++ b/src/credential.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef _H_CREDENTIAL +#define _H_CREDENTIAL + +#include +#include +#include + +namespace Authorization { + +/* Credentials are less than comparable so they can be put in sets or maps. */ +class CredentialImpl : public RefCount +{ +public: + CredentialImpl(); + CredentialImpl(const uid_t uid, const string &username, const string &realname, bool shared); + CredentialImpl(const string &username, const string &password, bool shared); + CredentialImpl(const string &right, bool shared); + ~CredentialImpl(); + + bool operator < (const CredentialImpl &other) const; + + // Returns true if this credential should be shared. + bool isShared() const; + + // Merge with other + void merge(const CredentialImpl &other); + + // The time at which this credential was obtained. + CFAbsoluteTime creationTime() const; + + // Return true iff this credential is valid. + bool isValid() const; + + // Make this credential invalid. + void invalidate(); + + // We could make Rule a friend but instead we just expose this for now + inline const uid_t uid() const { return mUid; } + inline const string& name() const { return mName; } + inline const string& realname() const { return mRealname; } + inline const bool isRight() const { return mRight; } +private: + // Key + uid_t mUid; + + // True iff this credential is shared. + bool mShared; + + // Fields below are not used by less than operator + + // The username of the user that provided his password. + string mName; + string mRealname; + + CFAbsoluteTime mCreationTime; + bool mValid; + bool mRight; +}; + +/* Credentials are less than comparable so they can be put in sets or maps. */ +class Credential : public RefPointer +{ +public: + Credential(); + Credential(CredentialImpl *impl); + Credential(const uid_t uid, const string &username, const string &realname, bool shared); + Credential(const string &username, const string &password, bool shared); + Credential(const string &right, bool shared); + ~Credential(); + + bool operator < (const Credential &other) const; +}; + +typedef set CredentialSet; + +} // namespace Authorization + +#endif // _H_CREDENTIAL diff --git a/src/csproxy.cpp b/src/csproxy.cpp new file mode 100644 index 0000000..6511b43 --- /dev/null +++ b/src/csproxy.cpp @@ -0,0 +1,478 @@ +/* + * Copyright (c) 2006-2007 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +// +// csproxy - Code Signing Hosting Proxy +// +#include "csproxy.h" +#include "server.h" +#include + + +// +// Construct a CodeSigningHost +// +CodeSigningHost::CodeSigningHost() + : mHostingState(noHosting) +{ +} + + +// +// Cleanup code. +// +CodeSigningHost::~CodeSigningHost() +{ + reset(); +} + + +// +// Reset Code Signing Hosting state. +// This turns hosting off and clears all children. +// +void CodeSigningHost::reset() +{ + switch (mHostingState) { + case noHosting: + break; // nothing to do + case dynamicHosting: + mHostingPort.destroy(); + mHostingPort = MACH_PORT_NULL; + break; + case proxyHosting: + Server::active().remove(*this); // unhook service handler + mHostingPort.destroy(); // destroy receive right + mHostingState = noHosting; + mHostingPort = MACH_PORT_NULL; + mGuests.erase(mGuests.begin(), mGuests.end()); + break; + } +} + + +// +// Given a host reference (possibly NULL for the process itself), locate +// its most dedicated guest. This descends a contiguous chain of dedicated +// guests until it find a host that either has no guests, or whose guests +// are not dedicated. +// +CodeSigningHost::Guest *CodeSigningHost::findHost(SecGuestRef hostRef) +{ + Guest *host = findGuest(hostRef, true); + for (;;) { + if (Guest *guest = findGuest(host)) + if (guest->dedicated) { + secdebug("hosting", "%p selecting dedicated guest %p of %p", this, guest, host); + host = guest; + continue; + } + return host; + } +} + + +// +// Look up guest by guestRef. +// Throws if they we don't have a guest by that ref. +// +CodeSigningHost::Guest *CodeSigningHost::findGuest(SecGuestRef guestRef, bool hostOk /* = false */) +{ + GuestMap::iterator it = mGuests.find(guestRef); + if (it == mGuests.end()) + if (hostOk) + return NULL; + else + MacOSError::throwMe(errSecCSNoSuchCode); + assert(it->first == it->second->guestRef()); + return it->second; +} + + +// +// Look up guest by attribute set. +// Returns the host if the attributes can't be found (*loose* interpretation). +// Throws if multiple guests are found (ambiguity). +// Implicitly matches dedicated guests no matter what attributes are requested. +// +CodeSigningHost::Guest *CodeSigningHost::findGuest(Guest *host, const CssmData &attrData) +{ + CFRef attrDict = attrData + ? makeCFDictionaryFrom(attrData.data(), attrData.length()) + : makeCFDictionary(0); + CFDictionary attrs(attrDict, errSecCSInvalidAttributeValues); + + // if a guest handle was provided, start with that - it must be valid or we fail + if (CFNumberRef canonical = attrs.get(kSecGuestAttributeCanonical)) { + // direct lookup by SecGuestRef (canonical guest handle) + SecGuestRef guestRef = cfNumber(canonical); + secdebug("hosting", "host %p looking for guest handle 0x%x", host, guestRef); + if (Guest *guest = findGuest(guestRef, true)) // found guest handle + if (guest->isGuestOf(host, loose)) { + secdebug("hosting", "found guest %p, continuing search", guest); + host = guest; // new starting point + } else + MacOSError::throwMe(errSecCSNoSuchCode); // not a guest of given host + else + MacOSError::throwMe(errSecCSNoSuchCode); // not there at all + } + + // now take the rest of the attrs + CFIndex count = CFDictionaryGetCount(attrs); + CFTypeRef keys[count], values[count]; + CFDictionaryGetKeysAndValues(attrs, keys, values); + for (;;) { + secdebug("hosting", "searching host %p by attributes", host); + Guest *match = NULL; // previous match found + for (GuestMap::const_iterator it = mGuests.begin(); it != mGuests.end(); ++it) + if (it->second->isGuestOf(host, strict)) + if (it->second->matches(count, keys, values)) + if (match) + MacOSError::throwMe(errSecCSMultipleGuests); // ambiguous + else + match = it->second; + if (!match) { // nothing found + secdebug("hosting", "nothing found, returning %p", host); + return host; + } else { + secdebug("hosting", "found guest %p, continuing", match); + host = match; // and repeat + } + } +} + + +// +// Find any guest of a given host. +// This will return a randomly chosen guest of this host if it has any, +// or NULL if it has none (i.e. it is not a host). +// +CodeSigningHost::Guest *CodeSigningHost::findGuest(Guest *host) +{ + for (GuestMap::const_iterator it = mGuests.begin(); it != mGuests.end(); ++it) + if (it->second->isGuestOf(host, strict)) + return it->second; + return NULL; +} + + +// +// Register a hosting API service port where the host will dynamically +// answer hosting queries from interested parties. This switches the process +// to dynamic hosting mode, and is incompatible with proxy hosting. +// +void CodeSigningHost::registerCodeSigning(mach_port_t hostingPort, SecCSFlags flags) +{ + switch (mHostingState) { + case noHosting: + secdebug("hosting", "%p registering for dynamic hosting on port %d", + this, hostingPort); + mHostingPort = hostingPort; + mHostingState = dynamicHosting; + break; + default: + MacOSError::throwMe(errSecCSHostProtocolContradiction); + } +} + + +// +// Create a guest entry for the given host and prepare to answer for it +// when dynamic hosting queries are received for it. +// This engages proxy hosting mode, and is incompatible with dynamic hosting mode. +// +SecGuestRef CodeSigningHost::createGuest(SecGuestRef hostRef, + uint32_t status, const char *path, const CssmData &attributes, SecCSFlags flags) +{ + secdebug("hosting", "%p create guest from host %d", this, hostRef); + + if (path[0] != '/') // relative path (relative to what? :-) + MacOSError::throwMe(errSecCSHostProtocolRelativePath); + + // set up for hosting proxy services if nothing's there yet + switch (mHostingState) { + case noHosting: + // set up proxy hosting + mHostingPort.allocate(); + MachServer::Handler::port(mHostingPort); + MachServer::active().add(*this); + mHostingState = proxyHosting; + secdebug("hosting", "%p created hosting port %d for proxy hosting", this, mHostingPort.port()); + break; + case proxyHosting: + break; // all set + case dynamicHosting: + MacOSError::throwMe(errSecCSHostProtocolContradiction); + } + + RefPointer host = findHost(hostRef); + RefPointer knownGuest = findGuest(host); + if ((flags & kSecCSDedicatedHost) && knownGuest) + MacOSError::throwMe(errSecCSHostProtocolDedicationError); // can't dedicate with other guests + else if (knownGuest && knownGuest->dedicated) + MacOSError::throwMe(errSecCSHostProtocolDedicationError); // other guest is already dedicated + + // create the new guest + RefPointer guest = new Guest; + if (host) + guest->guestPath = host->guestPath; + guest->guestPath.push_back(guest->handle()); + guest->status = status; + guest->path = path; + guest->setAttributes(attributes); + guest->dedicated = (flags & kSecCSDedicatedHost); + mGuests[guest->guestRef()] = guest; + secdebug("hosting", "guest 0x%x created %sstatus=0x%x path=%s", + guest->guestRef(), guest->dedicated ? "dedicated " : "", guest->status, guest->path.c_str()); + return guest->guestRef(); +} + + +void CodeSigningHost::setGuestStatus(SecGuestRef guestRef, uint32_t status, const CssmData &attributes) +{ + secdebug("hosting", "%p set guest 0x%x", this, guestRef); + if (mHostingState != proxyHosting) + MacOSError::throwMe(errSecCSHostProtocolNotProxy); + Guest *guest = findGuest(guestRef); + + // state modification machine + if ((status & ~guest->status) & CS_VALID) + MacOSError::throwMe(errSecCSHostProtocolStateError); // can't set + if ((~status & guest->status) & (CS_HARD | CS_KILL)) + MacOSError::throwMe(errSecCSHostProtocolStateError); // can't clear + guest->status = status; + + // replace attributes if requested + if (attributes) + guest->setAttributes(attributes); +} + + +// +// Remove a guest previously introduced via createGuest(). +// +void CodeSigningHost::removeGuest(SecGuestRef hostRef, SecGuestRef guestRef) +{ + secdebug("hosting", "%p removes guest %d from host %d", this, guestRef, hostRef); + if (mHostingState != proxyHosting) + MacOSError::throwMe(errSecCSHostProtocolNotProxy); + RefPointer host = findHost(hostRef); + RefPointer guest = findGuest(guestRef); + if (guest->dedicated) // can't remove a dedicated guest + MacOSError::throwMe(errSecCSHostProtocolDedicationError); + if (!guest->isGuestOf(host, strict)) + MacOSError::throwMe(errSecCSHostProtocolUnrelated); + for (GuestMap::iterator it = mGuests.begin(); it != mGuests.end(); ++it) + if (it->second->isGuestOf(guest, loose)) + mGuests.erase(it); +} + + +// +// The internal Guest object +// +CodeSigningHost::Guest::~Guest() +{ + secdebug("hosting", "guest %ld destroyed", handle()); +} + +void CodeSigningHost::Guest::setAttributes(const CssmData &attrData) +{ + CFRef guest = makeCFNumber(guestRef()); + if (attrData) { + CFRef inputDict = makeCFDictionaryFrom(attrData.data(), attrData.length()); + CFRef dict = CFDictionaryCreateMutableCopy(NULL, 0, inputDict); + CFDictionaryAddValue(dict, kSecGuestAttributeCanonical, guest); + attributes.take(dict); + } else { + attributes.take(makeCFDictionary(1, kSecGuestAttributeCanonical, guest.get())); + } +} + + +bool CodeSigningHost::Guest::isGuestOf(Guest *host, GuestCheck check) const +{ + vector hostPath; + if (host) + hostPath = host->guestPath; + if (hostPath.size() <= guestPath.size() + && !memcmp(&hostPath[0], &guestPath[0], sizeof(SecGuestRef) * hostPath.size())) + // hostPath is a prefix of guestPath + switch (check) { + case loose: + return true; + case strict: + return guestPath.size() == hostPath.size() + 1; // immediate guest + } + return false; +} + + +// +// Check to see if a given guest matches the (possibly empty) attribute set provided +// (in broken-open form, for efficiency). A dedicated guest will match all attribute +// specifications, even empty ones. A non-dedicated guest matches if at least one +// attribute value requested matches exactly (in the sense of CFEqual) that given +// by the host for this guest. +// +bool CodeSigningHost::Guest::matches(CFIndex count, CFTypeRef keys[], CFTypeRef values[]) const +{ + if (dedicated) + return true; + for (CFIndex n = 0; n < count; n++) { + CFStringRef key = CFStringRef(keys[n]); + if (CFEqual(key, kSecGuestAttributeCanonical)) // ignore canonical attribute (handled earlier) + continue; + if (CFTypeRef value = CFDictionaryGetValue(attributes, key)) + if (CFEqual(value, values[n])) + return true; + } + return false; +} + + +// +// The MachServer dispatch handler for proxy hosting. +// +boolean_t cshosting_server(mach_msg_header_t *, mach_msg_header_t *); + +static ThreadNexus context; + +boolean_t CodeSigningHost::handle(mach_msg_header_t *in, mach_msg_header_t *out) +{ + context() = this; + return cshosting_server(in, out); +} + + +// +// Proxy implementation of Code Signing Hosting protocol +// +#define CSH_ARGS mach_port_t servicePort, mach_port_t replyPort, OSStatus *rcode + +#define BEGIN_IPC try { +#define END_IPC *rcode = noErr; } \ + catch (const CommonError &err) { *rcode = err.osStatus(); } \ + catch (...) { *rcode = errSecCSInternalError; } \ + return KERN_SUCCESS; + +#define DATA_IN(base) void *base, mach_msg_type_number_t base##Length +#define DATA_OUT(base) void **base, mach_msg_type_number_t *base##Length +#define DATA(base) CssmData(base, base##Length) + + +// +// Find a guest by arbitrary attribute set. +// +// This returns an array of canonical guest references describing the path +// from the host given to the guest found. If the host itself is returned +// as a guest, this will be an empty array (zero length). +// +// The subhost return argument may in the future return the hosting port for +// a guest who dynamically manages its hosting (thus breaking out of proxy mode), +// but this is not yet implemented. +// +kern_return_t cshosting_server_findGuest(CSH_ARGS, SecGuestRef hostRef, + DATA_IN(attributes), + GuestChain *foundGuest, mach_msg_type_number_t *depth, mach_port_t *subhost) +{ + BEGIN_IPC + + *subhost = MACH_PORT_NULL; // preset no sub-hosting port returned + + Process::Guest *host = context()->findGuest(hostRef, true); + if (Process::Guest *guest = context()->findGuest(host, DATA(attributes))) { + *foundGuest = &guest->guestPath[0]; + *depth = guest->guestPath.size(); + } else { + *foundGuest = NULL; + *depth = 0; + } + END_IPC +} + + +// +// Retrieve the path to a guest specified by canonical reference. +// +kern_return_t cshosting_server_guestPath(CSH_ARGS, SecGuestRef guestRef, char *path) +{ + BEGIN_IPC + strncpy(path, context()->findGuest(guestRef)->path.c_str(), MAXPATHLEN); + END_IPC +} + + +// +// Retrieve the status word for a guest specified by canonical reference. +// +kern_return_t cshosting_server_guestStatus(CSH_ARGS, SecGuestRef guestRef, uint32_t *status) +{ + BEGIN_IPC + *status = context()->findGuest(guestRef)->status; + END_IPC +} + + +// +// Debug support +// +#if defined(DEBUGDUMP) + +void CodeSigningHost::dump() const +{ + switch (mHostingState) { + case noHosting: + break; + case dynamicHosting: + Debug::dump(" dynamic host port=%d", mHostingPort.port()); + break; + case proxyHosting: + Debug::dump(" proxy-host port=%d", mHostingPort.port()); + if (!mGuests.empty()) { + Debug::dump(" %d guests={", int(mGuests.size())); + for (GuestMap::const_iterator it = mGuests.begin(); it != mGuests.end(); ++it) { + if (it != mGuests.begin()) + Debug::dump(", "); + it->second->dump(); + } + Debug::dump("}"); + } + break; + } +} + +void CodeSigningHost::Guest::dump() const +{ + Debug::dump("%s[", path.c_str()); + for (vector::const_iterator it = guestPath.begin(); it != guestPath.end(); ++it) { + if (it != guestPath.begin()) + Debug::dump("/"); + Debug::dump("0x%x", *it); + } + Debug::dump("; status=0x%x attrs=%s]", + status, cfString(CFCopyDescription(attributes), true).c_str()); +} + +#endif //DEBUGDUMP diff --git a/src/csproxy.h b/src/csproxy.h new file mode 100644 index 0000000..33a3662 --- /dev/null +++ b/src/csproxy.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2006-2007 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +// +// csproxy - Code Signing Hosting Proxy +// +#ifndef _H_CSPROXY +#define _H_CSPROXY + +#include +#include +#include +#include +#include +#include +#include +#include + +using MachPlusPlus::Port; +using MachPlusPlus::MachServer; + + +// +// CodeSigningHost is a mix-in for an object representing a primary +// Code Signing host object. It performs two notionally separate functions: +// (1) Register a hosting port. +// (2) Optionally, maintain a guest registry to offload the host's work. +// +class CodeSigningHost : private MachServer::Handler { +public: + CodeSigningHost(); + ~CodeSigningHost(); + void reset(); + + enum HostingState { + noHosting, // is not a host (yet), could go either way + dynamicHosting, // gave us its own hosting port to keep + proxyHosting // we act as a proxy for it + }; + + enum GuestCheck { + strict, // direct guest relationship required + loose // indirect or identity is okay (prefix check) + }; + + struct Guest : public RefCount, public HandleObject { + public: + ~Guest(); + std::vector guestPath; // guest chain to this guest + uint32_t status; // dynamic status + std::string path; // canonical code path + CFRef attributes; // matching attributes set + bool dedicated; // host is dedicated (and this is the only guest) + + operator bool() const { return attributes; } // exists + SecGuestRef guestRef() const { return handle(); } + void setAttributes(const CssmData &attrData); + + bool isGuestOf(Guest *host, GuestCheck check) const; + bool matches(CFIndex count, CFTypeRef keys[], CFTypeRef values[]) const; + + IFDUMP(void dump() const); + }; + + void registerCodeSigning(mach_port_t hostingPort, SecCSFlags flags); + Port hostingPort() const { return mHostingPort; } + + SecGuestRef createGuest(SecGuestRef guest, + uint32_t status, const char *path, const CssmData &attributes, SecCSFlags flags); + void setGuestStatus(SecGuestRef guest, uint32_t status, const CssmData &attributes); + void removeGuest(SecGuestRef host, SecGuestRef guest); + + Guest *findHost(SecGuestRef hostRef); // find most dedicated guest of this host + Guest *findGuest(Guest *host, const CssmData &attrData); // by host and attributes + Guest *findGuest(SecGuestRef guestRef, bool hostOk = false); // by guest reference + Guest *findGuest(Guest *host); // any guest of this host + + IFDUMP(void dump() const); + +private: + boolean_t handle(mach_msg_header_t *in, mach_msg_header_t *out); + void eraseGuest(Guest *guest); + +private: + // host port registry + HostingState mHostingState; // status of hosting support + Port mHostingPort; // his or ours or NULL + + // guest map (only used if mHostingState == proxyHosting) + typedef std::map > GuestMap; + GuestMap mGuests; +}; + + +#endif //_H_CSPROXY diff --git a/src/database.cpp b/src/database.cpp index cb49a92..a29cd70 100644 --- a/src/database.cpp +++ b/src/database.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2007 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -67,7 +67,7 @@ Process& Database::process() const { return referent(); } - + // // Send a keychain-related notification event about this database @@ -87,6 +87,7 @@ void DbCommon::notify(NotificationEvent event, const DLDbIdentifier &ident) free (data.data()); } + // // Default behaviors // @@ -186,7 +187,7 @@ SecurityServerAcl &Database::acl() CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); } -bool Database::isLocked() const +bool Database::isLocked() { secdebug("database", "%p calling unimplemented isLocked", this); CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); diff --git a/src/database.h b/src/database.h index b6b3bd9..9534fcf 100644 --- a/src/database.h +++ b/src/database.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2007 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -65,7 +65,7 @@ public: DbCommon(Session &ssn); Session &session() const; - + virtual void sleepProcessing(); // generic action on system sleep virtual void lockProcessing(); // generic action on "lock" requests @@ -148,7 +148,7 @@ public: virtual void authenticate(CSSM_DB_ACCESS_TYPE mode, const AccessCredentials *cred); virtual SecurityServerAcl &acl(); - virtual bool isLocked() const; + virtual bool isLocked(); public: class Search : public Subsidiary { diff --git a/src/dbcrypto.cpp b/src/dbcrypto.cpp index 5054f85..98b1caa 100644 --- a/src/dbcrypto.cpp +++ b/src/dbcrypto.cpp @@ -306,31 +306,45 @@ void DatabaseCryptoCore::importSecrets(const DatabaseCryptoCore &src) // Encode a key blob // KeyBlob *DatabaseCryptoCore::encodeKeyCore(const CssmKey &inKey, - const CssmData &publicAcl, const CssmData &privateAcl) const + const CssmData &publicAcl, const CssmData &privateAcl, + bool inTheClear) const { - assert(isValid()); // need our database secrets - - // create new IV - uint8 iv[8]; - Server::active().random(iv); - - // extract and hold some header bits the CSP does not want to see CssmKey key = inKey; + uint8 iv[8]; + CssmKey wrappedKey; + + if(inTheClear && (privateAcl.Length != 0)) { + /* can't store private ACL component in the clear */ + CssmError::throwMe(CSSMERR_DL_INVALID_ACCESS_CREDENTIALS); + } + + // extract and hold some header bits the CSP does not want to see uint32 heldAttributes = key.attributes() & managedAttributes; key.clearAttribute(managedAttributes); key.setAttribute(forcedAttributes); - // use a CMS wrap to encrypt the key - WrapKey wrap(Server::csp(), CSSM_ALGID_3DES_3KEY_EDE); - wrap.key(mEncryptionKey); - wrap.mode(CSSM_ALGMODE_CBCPadIV8); - wrap.padding(CSSM_PADDING_PKCS1); - CssmData ivd(iv, sizeof(iv)); wrap.initVector(ivd); - wrap.add(CSSM_ATTRIBUTE_WRAPPED_KEY_FORMAT, - uint32(CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM)); - CssmKey wrappedKey; - wrap(key, wrappedKey, &privateAcl); - + if(inTheClear) { + /* NULL wrap of public key */ + WrapKey wrap(Server::csp(), CSSM_ALGID_NONE); + wrap(key, wrappedKey, NULL); + } + else { + assert(isValid()); // need our database secrets + + // create new IV + Server::active().random(iv); + + // use a CMS wrap to encrypt the key + WrapKey wrap(Server::csp(), CSSM_ALGID_3DES_3KEY_EDE); + wrap.key(mEncryptionKey); + wrap.mode(CSSM_ALGMODE_CBCPadIV8); + wrap.padding(CSSM_PADDING_PKCS1); + CssmData ivd(iv, sizeof(iv)); wrap.initVector(ivd); + wrap.add(CSSM_ATTRIBUTE_WRAPPED_KEY_FORMAT, + uint32(CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM)); + wrap(key, wrappedKey, &privateAcl); + } + // stick the held attribute bits back in key.clearAttribute(forcedAttributes); key.setAttribute(heldAttributes); @@ -342,7 +356,9 @@ KeyBlob *DatabaseCryptoCore::encodeKeyCore(const CssmKey &inKey, // assemble the KeyBlob memset(blob, 0, sizeof(KeyBlob)); // fill alignment gaps blob->initialize(); - memcpy(blob->iv, iv, sizeof(iv)); + if(!inTheClear) { + memcpy(blob->iv, iv, sizeof(iv)); + } blob->header = key.header(); h2ni(blob->header); // endian-correct the header blob->wrappedHeader.blobType = wrappedKey.blobType(); @@ -354,17 +370,23 @@ KeyBlob *DatabaseCryptoCore::encodeKeyCore(const CssmKey &inKey, memcpy(blob->cryptoBlob(), wrappedKey.data(), wrappedKey.length()); blob->totalLength = blob->startCryptoBlob + wrappedKey.length(); - // sign the blob - CssmData signChunk[] = { - CssmData(blob->data(), fieldOffsetOf(&KeyBlob::blobSignature)), - CssmData(blob->publicAclBlob(), blob->publicAclBlobLength() + blob->cryptoBlobLength()) - }; - CssmData signature(blob->blobSignature, sizeof(blob->blobSignature)); - GenerateMac signer(Server::csp(), CSSM_ALGID_SHA1HMAC_LEGACY); //@@@!!! CRUD - signer.key(mSigningKey); - signer.sign(signChunk, 2, signature); - assert(signature.length() == sizeof(blob->blobSignature)); - + if(inTheClear) { + /* indicate that this is cleartext for decoding */ + blob->setClearTextSignature(); + } + else { + // sign the blob + CssmData signChunk[] = { + CssmData(blob->data(), fieldOffsetOf(&KeyBlob::blobSignature)), + CssmData(blob->publicAclBlob(), blob->publicAclBlobLength() + blob->cryptoBlobLength()) + }; + CssmData signature(blob->blobSignature, sizeof(blob->blobSignature)); + GenerateMac signer(Server::csp(), CSSM_ALGID_SHA1HMAC_LEGACY); //@@@!!! CRUD + signer.key(mSigningKey); + signer.sign(signChunk, 2, signature); + assert(signature.length() == sizeof(blob->blobSignature)); + } + // all done. Clean up Server::csp()->allocator().free(wrappedKey); return blob; @@ -376,9 +398,7 @@ KeyBlob *DatabaseCryptoCore::encodeKeyCore(const CssmKey &inKey, // void DatabaseCryptoCore::decodeKeyCore(KeyBlob *blob, CssmKey &key, void * &pubAcl, void * &privAcl) const -{ - assert(isValid()); // need our database secrets - +{ // Assemble the encrypted blob as a CSSM "wrapped key" CssmKey wrappedKey; wrappedKey.KeyHeader = blob->header; @@ -389,39 +409,55 @@ void DatabaseCryptoCore::decodeKeyCore(KeyBlob *blob, wrappedKey.wrapMode(blob->wrappedHeader.wrapMode); wrappedKey.KeyData = CssmData(blob->cryptoBlob(), blob->cryptoBlobLength()); - // verify signature (check against corruption) - CssmData signChunk[] = { - CssmData::wrap(blob, fieldOffsetOf(&KeyBlob::blobSignature)), - CssmData(blob->publicAclBlob(), blob->publicAclBlobLength() + blob->cryptoBlobLength()) - }; - CSSM_ALGORITHMS verifyAlgorithm = CSSM_ALGID_SHA1HMAC; -#if defined(COMPAT_OSX_10_0) - if (blob->version() == blob->version_MacOS_10_0) - verifyAlgorithm = CSSM_ALGID_SHA1HMAC_LEGACY; // BSafe bug compatibility -#endif - VerifyMac verifier(Server::csp(), verifyAlgorithm); - verifier.key(mSigningKey); - CssmData signature(blob->blobSignature, sizeof(blob->blobSignature)); - verifier.verify(signChunk, 2, signature); - + bool inTheClear = blob->isClearText(); + if(!inTheClear) { + // verify signature (check against corruption) + assert(isValid()); // need our database secrets + CssmData signChunk[] = { + CssmData::wrap(blob, fieldOffsetOf(&KeyBlob::blobSignature)), + CssmData(blob->publicAclBlob(), blob->publicAclBlobLength() + blob->cryptoBlobLength()) + }; + CSSM_ALGORITHMS verifyAlgorithm = CSSM_ALGID_SHA1HMAC; + #if defined(COMPAT_OSX_10_0) + if (blob->version() == blob->version_MacOS_10_0) + verifyAlgorithm = CSSM_ALGID_SHA1HMAC_LEGACY; // BSafe bug compatibility + #endif + VerifyMac verifier(Server::csp(), verifyAlgorithm); + verifier.key(mSigningKey); + CssmData signature(blob->blobSignature, sizeof(blob->blobSignature)); + verifier.verify(signChunk, 2, signature); + } + /* else signature indicates cleartext */ + // extract and hold some header bits the CSP does not want to see uint32 heldAttributes = n2h(blob->header.attributes()) & managedAttributes; - // decrypt the key using an unwrapping operation - UnwrapKey unwrap(Server::csp(), CSSM_ALGID_3DES_3KEY_EDE); - unwrap.key(mEncryptionKey); - unwrap.mode(CSSM_ALGMODE_CBCPadIV8); - unwrap.padding(CSSM_PADDING_PKCS1); - CssmData ivd(blob->iv, sizeof(blob->iv)); unwrap.initVector(ivd); - unwrap.add(CSSM_ATTRIBUTE_WRAPPED_KEY_FORMAT, - uint32(CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM)); - CssmData privAclData; - wrappedKey.clearAttribute(managedAttributes); //@@@ shouldn't be needed(?) - unwrap(wrappedKey, - KeySpec(n2h(blob->header.usage()), - (n2h(blob->header.attributes()) & ~managedAttributes) | forcedAttributes), - key, &privAclData); - + CssmData privAclData; + if(inTheClear) { + /* NULL unwrap */ + UnwrapKey unwrap(Server::csp(), CSSM_ALGID_NONE); + wrappedKey.clearAttribute(managedAttributes); //@@@ shouldn't be needed(?) + unwrap(wrappedKey, + KeySpec(n2h(blob->header.usage()), + (n2h(blob->header.attributes()) & ~managedAttributes) | forcedAttributes), + key, &privAclData); + } + else { + // decrypt the key using an unwrapping operation + UnwrapKey unwrap(Server::csp(), CSSM_ALGID_3DES_3KEY_EDE); + unwrap.key(mEncryptionKey); + unwrap.mode(CSSM_ALGMODE_CBCPadIV8); + unwrap.padding(CSSM_PADDING_PKCS1); + CssmData ivd(blob->iv, sizeof(blob->iv)); unwrap.initVector(ivd); + unwrap.add(CSSM_ATTRIBUTE_WRAPPED_KEY_FORMAT, + uint32(CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM)); + wrappedKey.clearAttribute(managedAttributes); //@@@ shouldn't be needed(?) + unwrap(wrappedKey, + KeySpec(n2h(blob->header.usage()), + (n2h(blob->header.attributes()) & ~managedAttributes) | forcedAttributes), + key, &privAclData); + } + // compare retrieved key headers with blob headers (sanity check) // @@@ this should probably be checked over carefully CssmKey::Header &real = key.header(); @@ -437,9 +473,15 @@ void DatabaseCryptoCore::decodeKeyCore(KeyBlob *blob, // re-insert held bits key.header().KeyAttr |= heldAttributes; + if(inTheClear && (real.keyClass() != CSSM_KEYCLASS_PUBLIC_KEY)) { + /* Spoof - cleartext KeyBlob passed off as private key */ + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); + } + // got a valid key: return the pieces pubAcl = blob->publicAclBlob(); // points into blob (shared) - privAcl = privAclData; // was allocated by CSP decrypt + privAcl = privAclData; // was allocated by CSP decrypt, else NULL for + // cleatext keys // key was set by unwrap operation } diff --git a/src/dbcrypto.h b/src/dbcrypto.h index 16d42e3..5970f51 100644 --- a/src/dbcrypto.h +++ b/src/dbcrypto.h @@ -61,13 +61,14 @@ public: void importSecrets(const DatabaseCryptoCore &src); KeyBlob *encodeKeyCore(const CssmKey &key, - const CssmData &publicAcl, const CssmData &privateAcl) const; + const CssmData &publicAcl, const CssmData &privateAcl, + bool inTheClear) const; void decodeKeyCore(KeyBlob *blob, CssmKey &key, void * &pubAcl, void * &privAcl) const; static const uint32 managedAttributes = KeyBlob::managedAttributes; static const uint32 forcedAttributes = KeyBlob::forcedAttributes; - + public: bool validatePassphrase(const CssmData &passphrase); diff --git a/src/flippers.cpp b/src/flippers.cpp deleted file mode 100644 index 4f8fa31..0000000 --- a/src/flippers.cpp +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -// -// process - track a single client process and its belongings -// -#include "flippers.h" -#include - -using namespace LowLevelMemoryUtilities; - - -namespace Flippers { - -// -// The raw byte reversal flipper -// -void flip(void *addr, size_t size) -{ - assert(size > 1 && (size % 2 == 0)); - Byte *word = reinterpret_cast(addr); - for (size_t n = 0; n < size/2; n++) { - Byte b = word[n]; - word[n] = word[size-1-n]; - word[size-1-n] = b; - } -} - - -// -// Basic flippers -// -void flip(uint32 &obj) { flip(&obj, sizeof(obj)); } -void flip(uint16 &obj) { flip(&obj, sizeof(obj)); } -void flip(sint32 &obj) { flip(&obj, sizeof(obj)); } -void flip(sint16 &obj) { flip(&obj, sizeof(obj)); } - - -// -// Flip a context attribute. This is heavily polymorphic. -// -void flip(CSSM_CONTEXT_ATTRIBUTE &obj) -{ - flip(obj.AttributeType); - flip(obj.AttributeLength); - switch (obj.AttributeType & CSSM_ATTRIBUTE_TYPE_MASK) { - case CSSM_ATTRIBUTE_DATA_UINT32: - flip(obj.Attribute.Uint32); - break; - // all other alternatives are handled by CSSM_CONTEXT_ATTRIBUTE's walker - default: - break; - } -} - - -// -// Flip a CSSM_DB_ATTRIBUTE_INFO, also very polymorphic -// -void flip(CSSM_DB_ATTRIBUTE_INFO &obj) -{ - bool flippedAttributeNameFormat = false; - // check and see if obj is in host byte order. If not, flip it now - if (obj.AttributeNameFormat > CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER) - { - flip(obj.AttributeNameFormat); - flippedAttributeNameFormat = true; - } - - switch (obj.AttributeNameFormat) - { - case CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER: - { - flip(obj.Label.AttributeID); - } - break; - } - - flip (obj.AttributeFormat); - - if (!flippedAttributeNameFormat) - { - flip(obj.AttributeNameFormat); - } - -} - -// -// Automatically generated flippers -// -#include "flip_gen.cpp" - - -} // end namespace Flippers diff --git a/src/flippers.h b/src/flippers.h deleted file mode 100644 index 9d2fb8c..0000000 --- a/src/flippers.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -// -// process - track a single client process and its belongings -// -#ifndef _H_FLIPPERS -#define _H_FLIPPERS - -#include -#include - -// various types we make flippers for -#include -#include -#include -#include -#include -#include -#include - - -namespace Flippers { - - -// -// The default flipper does nothing -// -template -inline void flip(T &obj) -{ } - - -// -// It's a bad idea to try to flip a const, so flag that -// -template -inline void flip(const T &); - - -// -// Basic flippers -// -void flip(uint32 &obj); -void flip(uint16 &obj); -void flip(sint32 &obj); -void flip(sint16 &obj); - -template -inline void flip(Base * &obj) { flip(&obj, sizeof(obj)); } - - -// -// The raw byte reversal flipper -// -void flip(void *addr, size_t size); - -void flip(CSSM_DB_ATTRIBUTE_INFO &obj); -inline void flip(CssmDbAttributeInfo &obj) { flip(static_cast(obj)); } - -// -// Include automatically generated flipper declarations -// -#include "flip_gen.h" - - -} // end namespace flippers - - -#endif //_H_FLIPPERS diff --git a/src/generate.cf b/src/generate.cf deleted file mode 100644 index fa387c5..0000000 --- a/src/generate.cf +++ /dev/null @@ -1,44 +0,0 @@ -# -# Byte flipper generator configuration. -# -# Syntax of each non-comment line: -# cssmType[/podwrapperType] field1 ... fieldn -# cssmType[/podwrapperType] * -# Generates flippers for each cssmType (with forwarders for podwrapperType if present), -# flipping the fields given. If '*' is used, take field definitions from cssmtype.h. -# - -# -# CSSM standard structures -# -CSSM_DATA/CssmData Length -CSSM_VERSION * -CSSM_SUBSERVICE_UID/CssmSubserviceUid * -CSSM_NET_ADDRESS * -CSSM_LIST_ELEMENT/ListElement WordID ElementType -CSSM_DL_DB_HANDLE * -CSSM_CONTEXT_ATTRIBUTE/Context::Attr CUSTOM -CSSM_CONTEXT/Context * -CSSM_LIST/CssmList/TypedList ListType Tail -CSSM_SAMPLE/CssmSample * -CSSM_SAMPLEGROUP/SampleGroup NumberOfSamples -CSSM_ACCESS_CREDENTIALS/AccessCredentials Callback CallerCtx -CSSM_AUTHORIZATIONGROUP/AuthorizationGroup NumberOfAuthTags -CSSM_ACL_VALIDITY_PERIOD * -CSSM_ACL_ENTRY_PROTOTYPE/AclEntryPrototype Delegate -CSSM_ACL_OWNER_PROTOTYPE/AclOwnerPrototype Delegate -CSSM_ACL_ENTRY_INPUT/AclEntryInput Callback CallerContext -CSSM_ACL_ENTRY_INFO/AclEntryInfo EntryHandle -CSSM_RANGE * -CSSM_KEY_SIZE/CssmKeySize * -CSSM_KEYHEADER/CssmKey::Header * -CSSM_KEY/CssmKey KeyHeader -CSSM_QUERY/CssmQuery RecordType Conjunctive NumSelectionPredicates QueryLimits QueryFlags -CSSM_DB_ATTRIBUTE_DATA/CssmDbAttributeData NumberOfValues -CSSM_DB_RECORD_ATTRIBUTE_DATA/CssmDbRecordAttributeData DataRecordType SemanticInformation NumberOfAttributes - -# -# Authorization structures -# -AuthorizationItem valueLength flags -AuthorizationItemSet count diff --git a/src/generate.mk b/src/generate.mk deleted file mode 100644 index 112c477..0000000 --- a/src/generate.mk +++ /dev/null @@ -1,39 +0,0 @@ -# -# Makefile to build MIG-generated sources and headers -# -XSRCROOT:=$(shell cd $(SRCROOT) >/dev/null; pwd) -TARGET:=$(shell cd $(BUILT_PRODUCTS_DIR) >/dev/null; pwd) -SRC:=$(TARGET)/derived_src -HDR:=$(TARGET)/include - -build: $(SRC)/.mig.ucsp $(SRC)/.mig.secagent - -debug: build - -profile: build - -install: build - -installhdrs: build - -installsrc: - -clean: - rm -f $(SRC)/.mig.ucsp $(SRC)/.mig.secagent \ - $(SRC)/ucsp*.cpp $(SRC)/secagent*.cpp $(HDR)/ucsp.h $(HDR)/secagent.h - -$(SRC)/.mig.ucsp: SecurityServer/ucsp.defs SecurityServer/ucspNotify.defs SecurityServer/ucsp_types.h - mkdir -p $(SRC) - mkdir -p $(HDR) - cd /tmp; mig -server $(SRC)/ucspServer.cpp -user $(SRC)/ucspUser.cpp \ - -header $(HDR)/ucsp.h $(XSRCROOT)/SecurityServer/ucsp.defs - cd /tmp; mig -server $(SRC)/ucspNotifyReceiver.cpp -user $(SRC)/ucspNotifySender.cpp \ - -header $(HDR)/ucspNotify.h $(XSRCROOT)/SecurityServer/ucspNotify.defs - touch $(SRC)/.mig.ucsp - -$(SRC)/.mig.secagent: SecurityServer/secagent.defs SecurityServer/secagent_types.h - mkdir -p $(SRC) - mkdir -p $(HDR) - cd /tmp; mig -server $(SRC)/secagentServer.cpp -user $(SRC)/secagentUser.cpp \ - -header $(HDR)/secagent.h $(XSRCROOT)/SecurityServer/secagent.defs - touch $(SRC)/.mig.secagent diff --git a/src/generate.pl b/src/generate.pl deleted file mode 100755 index 4ec7cd1..0000000 --- a/src/generate.pl +++ /dev/null @@ -1,74 +0,0 @@ -#!/usr/bin/perl -# -# -# -#use strict; - -my $disclaimer = "Automatically generated - do not edit on penalty of futility!"; - - -# arguments -my ($configfile, $out_h, $out_cpp, $types, $hdrpath) = @ARGV; - - -# open configuration file -open(CFG, "$configfile") || die "$configfile: $!"; - -# open and load cssmtypes file -for my $hdrdir (split (/:/, $hdrpath)) { - open(TYPES, "$hdrdir/$types") and last; -} -TYPES or die "cannot find $types in $hdrpath: $!"; -$/=undef; -my $types_h = ; -close(TYPES); $/="\n"; - -# open output files -open(H, ">$out_h") || die "$out_h: $!"; -open(CPP, ">$out_cpp") || die "$out_cpp: $!"; - -# cautionary headings to each file -print H <) { - chomp; - next if /^[ ]*#/; - next if /^[ ]*$/; - - my @args = split; - $_ = shift @args; - my ($cssmName, @aliases) = split /\//; - - print H "void flip($cssmName &obj);\n"; - for my $alias (@aliases) { - print H "inline void flip($alias &obj) { flip(static_cast<$cssmName &>(obj)); }\n"; - } - - next if ($args[0] eq 'CUSTOM'); - - if ($args[0] eq '*') { - # extract definition from types file - my ($list) = $types_h =~ /{\s+([^}]+)\s+}\s*$cssmName,/; - die "cannot find struct definition for $cssmName in $types" unless $list; - @args = $list =~ /([A-Za-z0-9_]+);/gm; - } - - print CPP "void flip($cssmName &obj)\n{\n"; - for my $field (@args) { - print CPP "\tflip(obj.$field);\n"; - } - print CPP "}\n\n"; -} diff --git a/src/kcdatabase.cpp b/src/kcdatabase.cpp index 32160b5..ad5ee8f 100644 --- a/src/kcdatabase.cpp +++ b/src/kcdatabase.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2007 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -46,6 +46,7 @@ #include // @@@ 4003540 workaround #include #include // for default owner ACLs +#include #include #include #include @@ -54,6 +55,7 @@ #include #include +void unflattenKey(const CssmData &flatKey, CssmKey &rawKey); //>> make static method on KeychainDatabase // // Create a Database object from initial parameters (create operation) @@ -127,13 +129,13 @@ KeychainDatabase::KeychainDatabase(const DLDbIdentifier &id, const DbBlob *blob, parent(*dbcom); //@@@ arbitrate sequence number here, perhaps update common().mParams secdebug("KCdb", - "open database %s(%p) version %lx at known common %p", + "open database %s(%p) version %x at known common %p", common().dbName(), this, blob->version(), &common()); } else { // DbCommon not present; make a new one parent(*new KeychainDbCommon(proc.session(), ident)); common().mParams = blob->params; - secdebug("KCdb", "open database %s(%p) version %lx with new common %p", + secdebug("KCdb", "open database %s(%p) version %x with new common %p", common().dbName(), this, blob->version(), &common()); // this DbCommon is locked; no timer or reference setting } @@ -336,7 +338,7 @@ void KeychainDatabase::encode() Allocator::standard().free(mBlob); mBlob = blob; version = common().version; - secdebug("KCdb", "encoded database %p common %p(%s) version %ld params=(%ld,%d)", + secdebug("KCdb", "encoded database %p common %p(%s) version %u params=(%u,%u)", this, &common(), dbName(), version, common().mParams.idleTimeout, common().mParams.lockOnSleep); } @@ -464,7 +466,8 @@ void KeychainDatabase::makeUnlocked(const AccessCredentials *cred) assert(mBlob || (mValidData && common().hasMaster())); establishOldSecrets(cred); common().setUnlocked(); // mark unlocked - } else if (!mValidData) { // need to decode to get our ACLs, master secret available + } + if (!mValidData) { // need to decode to get our ACLs, master secret available secdebug("KCdb", "%p(%p) is unlocked; decoding for makeUnlocked()", this, &common()); if (!decode()) CssmError::throwMe(CSSM_ERRCODE_OPERATION_AUTH_DENIED); @@ -568,15 +571,8 @@ void KeychainDatabase::establishOldSecrets(const AccessCredentials *creds) switch (sample.type()) { // interactively prompt the user - no additional data case CSSM_SAMPLE_TYPE_KEYCHAIN_PROMPT: - { - secdebug("KCdb", "%p attempting interactive unlock", this); - QueryUnlock query(*this); - // Holding DB common lock during UI will deadlock securityd - StSyncLock uisync(common().uiLock(), common()); - query.inferHints(Server::process()); - if (query() == SecurityAgent::noReason) + if (interactiveUnlock()) return; - } break; // try to use an explicitly given passphrase - Data:passphrase case CSSM_SAMPLE_TYPE_PASSWORD: @@ -587,7 +583,8 @@ void KeychainDatabase::establishOldSecrets(const AccessCredentials *creds) return; break; // try to open with a given master key - Data:CSP or KeyHandle, Data:CssmKey - case CSSM_WORDID_SYMMETRIC_KEY: + case CSSM_SAMPLE_TYPE_SYMMETRIC_KEY: + case CSSM_SAMPLE_TYPE_ASYMMETRIC_KEY: assert(mBlob); secdebug("KCdb", "%p attempting explicit key unlock", this); common().setup(mBlob, keyFromCreds(sample, 4)); @@ -605,7 +602,7 @@ void KeychainDatabase::establishOldSecrets(const AccessCredentials *creds) // But instead we try to be tolerant and continue on. // This DOES however count as an explicit attempt at specifying unlock, // so we will no longer try the default case below... - secdebug("KCdb", "%p unknown sub-sample unlock (%ld) ignored", this, sample.type()); + secdebug("KCdb", "%p unknown sub-sample unlock (%d) ignored", this, sample.type()); break; } } @@ -622,11 +619,7 @@ void KeychainDatabase::establishOldSecrets(const AccessCredentials *creds) return; } - QueryUnlock query(*this); - // attempt interactive unlock - StSyncLock uisync(common().uiLock(), common()); - query.inferHints(Server::process()); - if (query() == SecurityAgent::noReason) + if (interactiveUnlock()) return; } @@ -634,6 +627,23 @@ void KeychainDatabase::establishOldSecrets(const AccessCredentials *creds) CssmError::throwMe(CSSM_ERRCODE_OPERATION_AUTH_DENIED); } +bool KeychainDatabase::interactiveUnlock() +{ + secdebug("KCdb", "%p attempting interactive unlock", this); + QueryUnlock query(*this); + // take UI interlock and release DbCommon lock (to avoid deadlocks) + StSyncLock uisync(common().uiLock(), common()); + + // now that we have the UI lock, interact unless another thread unlocked us first + if (isLocked()) { + query.inferHints(Server::process()); + return query() == SecurityAgent::noReason; + } else { + secdebug("KCdb", "%p was unlocked during uiLock delay", this); + return true; + } +} + // // Same thing, but obtain a new secret somehow and set it into the common. @@ -669,6 +679,7 @@ void KeychainDatabase::establishNewSecrets(const AccessCredentials *creds, Secur return; // try to open with a given master key case CSSM_WORDID_SYMMETRIC_KEY: + case CSSM_SAMPLE_TYPE_ASYMMETRIC_KEY: secdebug("KCdb", "%p specified explicit master key", this); common().setup(NULL, keyFromCreds(sample, 3)); return; @@ -683,7 +694,7 @@ void KeychainDatabase::establishNewSecrets(const AccessCredentials *creds, Secur // But instead we try to be tolerant and continue on. // This DOES however count as an explicit attempt at specifying unlock, // so we will no longer try the default case below... - secdebug("KCdb", "%p unknown sub-sample acquisition (%ld) ignored", + secdebug("KCdb", "%p unknown sub-sample acquisition (%d) ignored", this, sample.type()); break; } @@ -712,7 +723,7 @@ void KeychainDatabase::establishNewSecrets(const AccessCredentials *creds, Secur CssmClient::Key KeychainDatabase::keyFromCreds(const TypedList &sample, unsigned int requiredLength) { // decode TypedList structure (sample type; Data:CSPHandle; Data:CSSM_KEY) - assert(sample.type() == CSSM_WORDID_SYMMETRIC_KEY); + assert(sample.type() == CSSM_SAMPLE_TYPE_SYMMETRIC_KEY || sample.type() == CSSM_SAMPLE_TYPE_ASYMMETRIC_KEY); if (sample.length() != requiredLength || sample[1].type() != CSSM_LIST_ELEMENT_DATUM || sample[2].type() != CSSM_LIST_ELEMENT_DATUM @@ -724,7 +735,74 @@ CssmClient::Key KeychainDatabase::keyFromCreds(const TypedList &sample, unsigned if (key.header().cspGuid() == gGuidAppleCSPDL) { // handleOrKey is a SecurityServer KeyHandle; ignore key argument return safer_cast(*Server::key(handle)); - } else { + } else + if (sample.type() == CSSM_SAMPLE_TYPE_ASYMMETRIC_KEY) { + /* + Contents (see DefaultCredentials::unlockKey in libsecurity_keychain/defaultcreds.cpp) + + sample[0] sample type + sample[1] csp handle for master or wrapping key; is really a keyhandle + sample[2] masterKey [not used since securityd cannot interpret; use sample[1] handle instead] + sample[3] UnlockReferralRecord data, in this case the flattened symmetric key + */ + + // RefPointer Server::key(KeyHandle key) + KeyHandle keyhandle = *sample[1].data().interpretedAs(CSSM_ERRCODE_INVALID_SAMPLE_VALUE); + CssmData &flattenedKey = sample[3].data(); + RefPointer unwrappingKey = Server::key(keyhandle); + Database &db=unwrappingKey->database(); + + CssmKey rawWrappedKey; + unflattenKey(flattenedKey, rawWrappedKey); + + RefPointer masterKey; + CssmData emptyDescriptiveData; + const AccessCredentials *cred = NULL; + const AclEntryPrototype *owner = NULL; + CSSM_KEYUSE usage = CSSM_KEYUSE_ANY; + CSSM_KEYATTR_FLAGS attrs = CSSM_KEYATTR_EXTRACTABLE; //CSSM_KEYATTR_RETURN_REF | + + // Get default credentials for unwrappingKey (the one on the token) + // Copied from Statics::Statics() in libsecurity_keychain/aclclient.cpp + // Following KeyItem::getCredentials, one sees that the "operation" parameter + // e.g. "CSSM_ACL_AUTHORIZATION_DECRYPT" is ignored + Allocator &alloc = Allocator::standard(); + AutoCredentials promptCred(alloc, 3);// enable interactive prompting + + // promptCred: a credential permitting user prompt confirmations + // contains: + // a KEYCHAIN_PROMPT sample, both by itself and in a THRESHOLD + // a PROMPTED_PASSWORD sample + promptCred.sample(0) = TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_PROMPT); + promptCred.sample(1) = TypedList(alloc, CSSM_SAMPLE_TYPE_THRESHOLD, + new(alloc) ListElement(TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_PROMPT))); + promptCred.sample(2) = TypedList(alloc, CSSM_SAMPLE_TYPE_PROMPTED_PASSWORD, + new(alloc) ListElement(alloc, CssmData())); + + // This unwrap object is here just to provide a context + CssmClient::UnwrapKey unwrap(Server::csp(), CSSM_ALGID_NONE); //ok to lie about csp here + unwrap.mode(CSSM_ALGMODE_NONE); + unwrap.padding(CSSM_PADDING_PKCS1); + unwrap.cred(promptCred); + unwrap.add(CSSM_ATTRIBUTE_WRAPPED_KEY_FORMAT, uint32(CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7)); + Security::Context *tmpContext; + CSSM_CC_HANDLE CCHandle = unwrap.handle(); + /*CSSM_RETURN rx = */ CSSM_GetContext (CCHandle, (CSSM_CONTEXT_PTR *)&tmpContext); + + // OK, this is skanky but necessary. We overwrite fields in the context struct + + tmpContext->ContextType = CSSM_ALGCLASS_ASYMMETRIC; + tmpContext->AlgorithmType = CSSM_ALGID_RSA; + + db.unwrapKey(*tmpContext, cred, owner, unwrappingKey, NULL, usage, attrs, + rawWrappedKey, masterKey, emptyDescriptiveData); + + Allocator::standard().free(rawWrappedKey.KeyData.Data); + + return safer_cast(*masterKey).key(); + } + else + { // not a KeyHandle reference; use key as a raw key if (key.header().blobType() != CSSM_KEYBLOB_RAW) CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_REFERENCE); @@ -734,6 +812,22 @@ CssmClient::Key KeychainDatabase::keyFromCreds(const TypedList &sample, unsigned } } +void unflattenKey(const CssmData &flatKey, CssmKey &rawKey) +{ + // unflatten the raw input key naively: key header then key data + // We also convert it back to host byte order + // A CSSM_KEY is a CSSM_KEYHEADER followed by a CSSM_DATA + + // Now copy: header, then key struct, then key data + memcpy(&rawKey.KeyHeader, flatKey.Data, sizeof(CSSM_KEYHEADER)); + memcpy(&rawKey.KeyData, flatKey.Data + sizeof(CSSM_KEYHEADER), sizeof(CSSM_DATA)); + const uint32 keyDataLength = flatKey.length() - sizeof(CSSM_KEY); + rawKey.KeyData.Data = Allocator::standard().malloc(keyDataLength); + rawKey.KeyData.Length = keyDataLength; + memcpy(rawKey.KeyData.Data, flatKey.Data + sizeof(CSSM_KEY), keyDataLength); + Security::n2hi(rawKey.KeyHeader); // convert it to host byte order +} + // // Verify a putative database passphrase. @@ -774,10 +868,18 @@ void KeychainDatabase::lockDb() // KeyBlob *KeychainDatabase::encodeKey(const CssmKey &key, const CssmData &pubAcl, const CssmData &privAcl) { - unlockDb(); - + bool inTheClear = false; + + if((key.keyClass() == CSSM_KEYCLASS_PUBLIC_KEY) && + !(key.attribute(CSSM_KEYATTR_PUBLIC_KEY_ENCRYPT))) { + inTheClear = true; + } + if(!inTheClear) { + unlockDb(); + } + // tell the cryptocore to form the key blob - return common().encodeKeyCore(key, pubAcl, privAcl); + return common().encodeKeyCore(key, pubAcl, privAcl, inTheClear); } @@ -787,8 +889,10 @@ KeyBlob *KeychainDatabase::encodeKey(const CssmKey &key, const CssmData &pubAcl, // void KeychainDatabase::decodeKey(KeyBlob *blob, CssmKey &key, void * &pubAcl, void * &privAcl) { - unlockDb(); // we need our keys - + if(!blob->isClearText()) { + unlockDb(); // we need our keys + } + common().decodeKeyCore(blob, key, pubAcl, privAcl); // memory protocol: pubAcl points into blob; privAcl was allocated @@ -808,7 +912,17 @@ KeyBlob *KeychainDatabase::recodeKey(KeychainKey &oldKey) CssmData publicAcl, privateAcl; oldKey.exportBlob(publicAcl, privateAcl); // NB: blob's memory belongs to caller, not the common - KeyBlob *blob = common().encodeKeyCore(oldKey.cssmKey(), publicAcl, privateAcl); + + /* + * Make sure the new key is in the same cleartext/encrypted state. + */ + bool inTheClear = false; + assert(oldKey.blob()); + if(oldKey.blob() && oldKey.blob()->isClearText()) { + /* careful....*/ + inTheClear = true; + } + KeyBlob *blob = common().encodeKeyCore(oldKey.cssmKey(), publicAcl, privateAcl, inTheClear); oldKey.acl().allocator.free(publicAcl); oldKey.acl().allocator.free(privateAcl); return blob; @@ -825,7 +939,7 @@ void KeychainDatabase::setParameters(const DBParameters ¶ms) common().mParams = params; common().invalidateBlob(); // invalidate old blobs activity(); // (also resets the timeout timer) - secdebug("KCdb", "%p common %p(%s) set params=(%ld,%d)", + secdebug("KCdb", "%p common %p(%s) set params=(%u,%u)", this, &common(), dbName(), params.idleTimeout, params.lockOnSleep); } @@ -898,7 +1012,7 @@ void KeychainDbCommon::dumpNode() { PerSession::dumpNode(); uint32 sig; memcpy(&sig, &mIdentifier.signature(), sizeof(sig)); - Debug::dump(" %s[%8.8lx]", mIdentifier.dbName(), sig); + Debug::dump(" %s[%8.8x]", mIdentifier.dbName(), sig); if (isLocked()) { Debug::dump(" locked"); } else { @@ -906,17 +1020,17 @@ void KeychainDbCommon::dumpNode() Debug::dump(" unlocked(%24.24s/%.2g)", ctime(&whenTime), (when() - Time::now()).seconds()); } - Debug::dump(" params=(%ld,%d)", mParams.idleTimeout, mParams.lockOnSleep); + Debug::dump(" params=(%u,%u)", mParams.idleTimeout, mParams.lockOnSleep); } void KeychainDatabase::dumpNode() { PerProcess::dumpNode(); - Debug::dump(" %s vers=%ld", + Debug::dump(" %s vers=%u", mValidData ? " data" : " nodata", version); if (mBlob) { uint32 sig; memcpy(&sig, &mBlob->randomSignature, sizeof(sig)); - Debug::dump(" blob=%p[%8.8lx]", mBlob, sig); + Debug::dump(" blob=%p[%8.8x]", mBlob, sig); } else { Debug::dump(" noblob"); } @@ -963,6 +1077,14 @@ KeychainDbGlobal &KeychainDbCommon::global() const } +void KeychainDbCommon::select() +{ this->ref(); } + +void KeychainDbCommon::unselect() +{ this->unref(); } + + + void KeychainDbCommon::makeNewSecrets() { // we already have a master key (right?) @@ -1004,10 +1126,14 @@ bool KeychainDbCommon::unlockDb(DbBlob *blob, void **privateAclBlob) mValidParams = true; // sticky } + bool isLocked = mIsLocked; + setUnlocked(); // mark unlocked - // broadcast unlock notification - notify(kNotificationEventUnlocked); + if (isLocked) { + // broadcast unlock notification, but only if we were previously locked + notify(kNotificationEventUnlocked); + } return true; } @@ -1061,25 +1187,6 @@ DbBlob *KeychainDbCommon::encode(KeychainDatabase &db) } -// -// Send a keychain-related notification event about this keychain -// -void KeychainDbCommon::notify(NotificationEvent event) -{ - // form the data (encoded DLDbIdentifier) - NameValueDictionary nvd; - NameValueDictionary::MakeNameValueDictionaryFromDLDbIdentifier(identifier(), nvd); - CssmData data; - nvd.Export(data); - - // inject notification into Security event system - Listener::notify(kNotificationDomainDatabase, event, data); - - // clean up - free (data.data()); -} - - // // Perform deferred lock processing for a database. // diff --git a/src/kcdatabase.h b/src/kcdatabase.h index 69714aa..3656bfa 100644 --- a/src/kcdatabase.h +++ b/src/kcdatabase.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2007 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -99,9 +99,9 @@ public: bool unlockDb(DbBlob *blob, void **privateAclBlob = NULL); void lockDb(); // make locked (if currently unlocked) - bool isLocked() const { return mIsLocked; } // lock status + bool isLocked() { return mIsLocked; } // lock status void setUnlocked(); - void invalidateBlob() { version++; } + void invalidateBlob() { version++; } void activity(); // reset lock timeout @@ -113,7 +113,7 @@ public: DbBlob *encode(KeychainDatabase &db); - void notify(NotificationEvent event); + void notify(NotificationEvent event) { DbCommon::notify(event, identifier()); } void sleepProcessing(); void lockProcessing(); @@ -124,6 +124,10 @@ public: protected: void action(); // timer queue action to lock keychain + + // lifetime management for our Timer personality + void select(); + void unselect(); public: // all following data locked with object lock @@ -187,9 +191,9 @@ public: bool decode(const CssmData &passphrase); // set master key from PP, try unlock bool validatePassphrase(const CssmData &passphrase) const; // nonthrowing validation - bool isLocked() const { return common().isLocked(); } // lock status + bool isLocked() { return common().isLocked(); } // lock status void notify(NotificationEvent event) { return common().notify(event); } - void activity() const { common().activity(); } // reset timeout clock + void activity() const { common().activity(); } // reset timeout clock // encoding/decoding keys void decodeKey(KeyBlob *blob, CssmKey &key, void * &pubAcl, void * &privAcl); @@ -228,7 +232,9 @@ protected: void establishOldSecrets(const AccessCredentials *creds); void establishNewSecrets(const AccessCredentials *creds, SecurityAgent::Reason reason); - static CssmClient::Key keyFromCreds(const TypedList &sample, unsigned int requiredLength); + bool interactiveUnlock(); + + CssmClient::Key keyFromCreds(const TypedList &sample, unsigned int requiredLength); void encode(); // (re)generate mBlob if needed diff --git a/src/kckey.cpp b/src/kckey.cpp index f6ed602..2f96682 100644 --- a/src/kckey.cpp +++ b/src/kckey.cpp @@ -56,7 +56,7 @@ KeychainKey::KeychainKey(Database &db, const KeyBlob *blob) mBlob = blob->copy(Allocator::standard()); mValidBlob = true; db.addReference(*this); - secdebug("SSkey", "%p (handle 0x%lx) created from blob version %lx", + secdebug("SSkey", "%p (handle 0x%lx) created from blob version %x", this, handle(), blob->version()); } @@ -195,9 +195,13 @@ void KeychainKey::changedAcl() void KeychainKey::validate(AclAuthorization auth, const AccessCredentials *cred, Database *relatedDatabase) { - if (KeychainDatabase *db = dynamic_cast(relatedDatabase)) - db->unlockDb(); + if(!mBlob->isClearText()) { + /* unlock not needed for cleartext keys */ + if (KeychainDatabase *db = dynamic_cast(relatedDatabase)) + db->unlockDb(); + } SecurityServerAcl::validate(auth, cred, relatedDatabase); + database().activity(); // upon successful validation } diff --git a/src/kckey.h b/src/kckey.h index a5d5ce6..ed979e5 100644 --- a/src/kckey.h +++ b/src/kckey.h @@ -57,7 +57,7 @@ public: KeychainDatabase &database() const; - // we can also yield an encoded KeyBlob *if* we belong to a database + // we can also yield an encoded KeyBlob KeyBlob *blob(); void invalidateBlob(); diff --git a/src/localdatabase.cpp b/src/localdatabase.cpp index 1ffc954..30aa4a0 100644 --- a/src/localdatabase.cpp +++ b/src/localdatabase.cpp @@ -183,7 +183,8 @@ void LocalDatabase::generateKey(const Context &context, privKey, LocalKey::KeySpec(privUsage, privAttrs)); // register and return the generated keys - publicKey = makeKey(pubKey, pubAttrs & LocalKey::managedAttributes, owner); + publicKey = makeKey(pubKey, pubAttrs & LocalKey::managedAttributes, + (pubAttrs & CSSM_KEYATTR_PUBLIC_KEY_ENCRYPT) ? owner : NULL); privateKey = makeKey(privKey, privAttrs & LocalKey::managedAttributes, owner); } diff --git a/src/localkey.cpp b/src/localkey.cpp index e50d82f..37e8c7b 100644 --- a/src/localkey.cpp +++ b/src/localkey.cpp @@ -39,7 +39,7 @@ LocalKey::LocalKey(Database &db, const CssmKey &newKey, CSSM_KEYATTR_FLAGS moreA { mValidKey = true; setup(newKey, moreAttributes); - secdebug("SSkey", "%p (handle 0x%lx) created from key alg=%ld use=0x%lx attr=0x%lx db=%p", + secdebug("SSkey", "%p (handle 0x%lx) created from key alg=%u use=0x%x attr=0x%x db=%p", this, handle(), mKey.header().algorithm(), mKey.header().usage(), mAttributes, &db); } @@ -101,6 +101,7 @@ LocalDatabase &LocalKey::database() const // CssmClient::Key LocalKey::keyValue() { + StLock _(*this); if (!mValidKey) { getKey(); mValidKey = true; @@ -123,6 +124,8 @@ CSSM_KEYATTR_FLAGS LocalKey::attributes() // void LocalKey::returnKey(Handle &h, CssmKey::Header &hdr) { + StLock _(*this); + // return handle h = this->handle(); @@ -145,6 +148,7 @@ void LocalKey::returnKey(Handle &h, CssmKey::Header &hdr) // const CssmData &LocalKey::canonicalDigest() { + StLock _(*this); if (!mDigest) { CssmClient::PassThrough ctx(Server::csp()); ctx.key(keyValue()); diff --git a/src/main.cpp b/src/main.cpp index 5b47f5e..d61e309 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2007 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -31,6 +31,7 @@ #include "entropy.h" #include "authority.h" #include "session.h" +#include "notifications.h" #include "pcscmonitor.h" #include "self.h" @@ -38,7 +39,8 @@ #include #include #include -#include + +#include #include #include @@ -64,6 +66,7 @@ #include #include "acl_keychain.h" + // // Local functions of the main program driver // @@ -90,25 +93,37 @@ int main(int argc, char *argv[]) // clear the umask - we know what we're doing secdebug("SS", "starting umask was 0%o", ::umask(0)); ::umask(0); - + + // tell the keychain (client) layer to turn off the server interface + SecKeychainSetServerMode(); + // program arguments (preset to defaults) bool debugMode = false; const char *bootstrapName = NULL; + const char* messagingName = SECURITY_MESSAGES_NAME; bool doFork = false; bool reExecute = false; int workerTimeout = 0; int maxThreads = 0; + bool waitForClients = false; const char *authorizationConfig = "/etc/authorization"; const char *tokenCacheDir = "/var/db/TokenCache"; const char *entropyFile = "/var/db/SystemEntropyCache"; const char *equivDbFile = EQUIVALENCEDBPATH; const char *smartCardOptions = getenv("SMARTCARDS"); + uint32_t keychainAclDefault = CSSM_ACL_KEYCHAIN_PROMPT_INVALID | CSSM_ACL_KEYCHAIN_PROMPT_UNSIGNED; + + // check for the Installation-DVD environment and modify some default arguments if found + if (access("/etc/rc.cdrom", F_OK) == 0) { // /etc/rc.cdrom exists + secdebug("SS", "configuring for installation"); + smartCardOptions = "off"; // needs writable directories that aren't + } // parse command line arguments extern char *optarg; extern int optind; int arg; - while ((arg = getopt(argc, argv, "a:c:de:E:fN:s:t:T:X")) != -1) { + while ((arg = getopt(argc, argv, "a:c:de:E:fiN:s:t:T:Xuw")) != -1) { switch (arg) { case 'a': authorizationConfig = optarg; @@ -128,6 +143,9 @@ int main(int argc, char *argv[]) case 'f': fprintf(stderr, "%s: the -f option is obsolete\n", argv[0]); break; + case 'i': + keychainAclDefault &= ~CSSM_ACL_KEYCHAIN_PROMPT_INVALID; + break; case 'N': bootstrapName = optarg; break; @@ -142,6 +160,12 @@ int main(int argc, char *argv[]) if ((workerTimeout = atoi(optarg)) < 0) workerTimeout = 0; break; + case 'w': + waitForClients = true; + break; + case 'u': + keychainAclDefault &= ~CSSM_ACL_KEYCHAIN_PROMPT_UNSIGNED; + break; case 'X': doFork = true; reExecute = true; @@ -159,9 +183,19 @@ int main(int argc, char *argv[]) if (!bootstrapName) { bootstrapName = getenv(SECURITYSERVER_BOOTSTRAP_ENV); if (!bootstrapName) + { bootstrapName = SECURITYSERVER_BOOTSTRAP_NAME; + } + else + { + messagingName = bootstrapName; + } } - + else + { + messagingName = bootstrapName; + } + // configure logging first if (debugMode) { Syslog::open(bootstrapName, LOG_AUTHPRIV, LOG_PERROR); @@ -199,18 +233,20 @@ int main(int argc, char *argv[]) secdebug("SS", "Cannot handle SIGINT: errno=%d", errno); if (signal(SIGTERM, handleSignals) == SIG_ERR) secdebug("SS", "Cannot handle SIGTERM: errno=%d", errno); + if (signal(SIGPIPE, handleSignals) == SIG_ERR) + secdebug("SS", "Cannot handle SIGPIPE: errno=%d", errno); #if !defined(NDEBUG) if (signal(SIGUSR1, handleSignals) == SIG_ERR) secdebug("SS", "Cannot handle SIGHUP: errno=%d", errno); #endif //NDEBUG - - // create a code signing engine - CodeSigning::OSXSigner signer; + + // create the shared memory notification hub + new SharedMemoryListener(messagingName, kSharedMemoryPoolSize); // create an Authorization engine Authority authority(authorizationConfig); - // establish the ACL machinery + // introduce all supported ACL subject types new AnyAclSubject::Maker(); new PasswordAclSubject::Maker(); new ProtectedPasswordAclSubject::Maker(); @@ -218,8 +254,8 @@ int main(int argc, char *argv[]) new ThresholdAclSubject::Maker(); new CommentAclSubject::Maker(); new ProcessAclSubject::Maker(); - new CodeSignatureAclSubject::Maker(signer); - new KeychainPromptAclSubject::Maker(); + new CodeSignatureAclSubject::Maker(); + new KeychainPromptAclSubject::Maker(keychainAclDefault); new PreAuthorizationAcls::OriginMaker(); new PreAuthorizationAcls::SourceMaker(); @@ -237,6 +273,8 @@ int main(int argc, char *argv[]) server.timeout(workerTimeout); if (maxThreads) server.maxThreads(maxThreads); + server.floatingThread(true); + server.waitForClients(waitForClients); // add the RNG seed timer # if defined(NDEBUG) @@ -252,7 +290,7 @@ int main(int argc, char *argv[]) #endif //NDEBUG // create a smartcard monitor to manage external token devices - PCSCMonitor secureCards(server, tokenCacheDir, scOptions(smartCardOptions)); + new PCSCMonitor(server, tokenCacheDir, scOptions(smartCardOptions)); // create the RootSession object (if -d, give it graphics and tty attributes) RootSession rootSession(server, @@ -260,7 +298,7 @@ int main(int argc, char *argv[]) // install MDS and initialize the local CSSM server.loadCssm(); - + // okay, we're ready to roll Syslog::notice("Entering service"); secdebug("SS", "%s initialized", bootstrapName); @@ -302,7 +340,7 @@ int main(int argc, char *argv[]) // static void usage(const char *me) { - fprintf(stderr, "Usage: %s [-dX]" + fprintf(stderr, "Usage: %s [-dwX]" "\n\t[-a authConfigFile] Authorization configuration file" "\n\t[-c tokencache] smartcard token cache directory" "\n\t[-e equivDatabase] path to code equivalence database" diff --git a/src/notifications.cpp b/src/notifications.cpp index ebee947..4ad4198 100644 --- a/src/notifications.cpp +++ b/src/notifications.cpp @@ -23,31 +23,34 @@ // -// EntropyManager - manage entropy on the system. +// notifications - handling of securityd-gated notification messages // +#include + #include "notifications.h" #include "server.h" +#include "connection.h" #include -Listener::ListenerMap Listener::listeners; -Mutex Listener::setLock; +Listener::ListenerMap Listener::listeners; +Mutex Listener::setLock(Mutex::recursive); -Listener::Listener(Port port, NotificationDomain dom, NotificationMask evs) - : domain(dom), events(evs), mPort(port) -{ setup(); } -Listener::Listener(NotificationDomain dom, NotificationMask evs) +// +// Listener basics +// +Listener::Listener(NotificationDomain dom, NotificationMask evs, mach_port_t port) : domain(dom), events(evs) -{ setup(); } - -void Listener::setup() { assert(events); // what's the point? - + // register in listener set StLock _(setLock); - listeners.insert(ListenerMap::value_type(mPort, this)); + listeners.insert(ListenerMap::value_type(port, this)); + + secdebug("notify", "%p created for domain 0x%x events 0x%x port %d", + this, dom, evs, port); } Listener::~Listener() @@ -61,12 +64,32 @@ Listener::~Listener() // void Listener::notify(NotificationDomain domain, NotificationEvent event, const CssmData &data) +{ + RefPointer message = new Notification(domain, event, 0, data); + StLock _(setLock); + sendNotification(message); +} + +void Listener::notify(NotificationDomain domain, + NotificationEvent event, uint32 sequence, const CssmData &data) +{ + Connection ¤t = Server::active().connection(); + RefPointer message = new Notification(domain, event, sequence, data); + if (current.inSequence(message)) { + StLock _(setLock); + sendNotification(message); + while (RefPointer next = current.popNotification()) + sendNotification(next); + } +} + +void Listener::sendNotification(Notification *message) { for (ListenerMap::const_iterator it = listeners.begin(); it != listeners.end(); it++) { Listener *listener = it->second; - if (listener->domain == domain && listener->wants(event)) - listener->notifyMe(domain, event, data); + if (listener->domain == kNotificationDomainAll || (message->domain == listener->domain && listener->wants(message->event))) + listener->notifyMe(message); } } @@ -77,15 +100,20 @@ void Listener::notify(NotificationDomain domain, // bool Listener::remove(Port port) { - assert(port); // Listeners with null ports are eternal typedef ListenerMap::iterator Iterator; StLock _(setLock); pair range = listeners.equal_range(port); if (range.first == range.second) return false; // not one of ours - for (Iterator it = range.first; it != range.second; it++) - delete it->second; + assert(range.first != listeners.end()); + secdebug("notify", "remove port %d", port.port()); +#if !defined(NDEBUG) + for (Iterator it = range.first; it != range.second; it++) { + assert(it->first == port); + secdebug("notify", "%p listener removed", it->second.get()); + } +#endif //NDEBUG listeners.erase(range.first, range.second); port.destroy(); return true; // got it @@ -93,32 +121,91 @@ bool Listener::remove(Port port) // -// Construct a new Listener and hook it up +// Notification message objects // -ProcessListener::ProcessListener(Process &proc, Port receiver, - NotificationDomain dom, NotificationMask evs) - : Listener(receiver, dom, evs), process(proc) +Listener::Notification::Notification(NotificationDomain inDomain, + NotificationEvent inEvent, uint32 seq, const CssmData &inData) + : domain(inDomain), event(inEvent), sequence(seq), data(Allocator::standard(), inData) { - // let's get told when the receiver port dies - Server::active().notifyIfDead(mPort); - - secdebug("notify", "%p created domain %ld events 0x%lx port %d", - this, domain, events, mPort.port()); + secdebug("notify", "%p notification created domain 0x%lx event %ld seq %ld", + this, domain, event, sequence); +} + +Listener::Notification::~Notification() +{ + secdebug("notify", "%p notification done domain 0x%lx event %ld seq %ld", + this, domain, event, sequence); } // -// Send a single notification for this listener +// Jitter buffering // -void ProcessListener::notifyMe(NotificationDomain domain, - NotificationEvent event, const CssmData &data) +bool Listener::JitterBuffer::inSequence(Notification *message) +{ + if (message->sequence == mNotifyLast + 1) { // next in sequence + mNotifyLast++; // record next sequence + return true; // go ahead + } else { + secdebug("notify-jit", "%p out of sequence (last %ld got %ld); buffering", + message, mNotifyLast, message->sequence); + mBuffer[message->sequence] = message; // save for later + return false; // hold your fire + } +} + +RefPointer Listener::JitterBuffer::popNotification() +{ + JBuffer::iterator it = mBuffer.find(mNotifyLast + 1); // have next message? + if (it == mBuffer.end()) + return NULL; // nothing here + else { + RefPointer result = it->second; // save value + mBuffer.erase(it); // remove from buffer + secdebug("notify-jit", "%p retrieved from jitter buffer", result.get()); + return result; // return it + } +} + +/* + * Shared memory listener + */ + + +SharedMemoryListener::SharedMemoryListener(const char* segmentName, SegmentOffsetType segmentSize) : + Listener (kNotificationDomainAll, kNotificationAllEvents), + SharedMemoryServer (segmentName, segmentSize), + mActive (false) +{ + if (segmentName == NULL) + { + secdebug("notify", "Attempted to start securityd with a NULL segmentName"); + exit(1); + } +} + +SharedMemoryListener::~SharedMemoryListener () +{ +} + +const double kServerWait = 0.005; // time in seconds before clients will be notified that data is available + +void SharedMemoryListener::notifyMe(Notification* notification) +{ + const void* data = notification->data.data(); + UInt32 length = notification->data.length(); + WriteMessage (notification->domain, notification->event, data, length); + + if (!mActive) + { + Server::active().setTimer (this, Time::Interval(kServerWait)); + mActive = true; + } +} + +void SharedMemoryListener::action () { - secdebug("notify", "%p sending domain %ld event 0x%lx to port %d process %d", - this, domain, event, mPort.port(), process.pid()); - - // send mach message (via MIG simpleroutine) - if (IFDEBUG(kern_return_t rc =) ucsp_notify_sender_notify(mPort, - domain, event, data.data(), data.length(), - 0 /*@@@ placeholder for sender ID */)) - secdebug("notify", "%p send failed (error=%d)", this, rc); + secdebug("notify", "Posted notification to clients."); + notify_post (mSegmentName.c_str ()); + mActive = false; } diff --git a/src/notifications.h b/src/notifications.h index 115df09..858e12e 100644 --- a/src/notifications.h +++ b/src/notifications.h @@ -23,21 +23,27 @@ // -// +// notifications - handling of securityd-gated notification messages // #ifndef _H_NOTIFICATIONS #define _H_NOTIFICATIONS #include +#include #include #include #include +#include + +#include "SharedMemoryServer.h" using MachPlusPlus::Port; +using MachPlusPlus::MachServer; using SecurityServer::NotificationDomain; using SecurityServer::NotificationEvent; using SecurityServer::NotificationMask; +class SharedMemoryListener; // // A registered receiver of notifications. @@ -56,20 +62,18 @@ using SecurityServer::NotificationMask; // If you need another Listener lifetime management strategy, you will probably // have to change things around here. // -class Listener { +class Listener: public RefCount { public: - Listener(Port port, NotificationDomain domain, NotificationMask events); - Listener(NotificationDomain domain, NotificationMask events); + Listener(NotificationDomain domain, NotificationMask events, + mach_port_t port = MACH_PORT_NULL); virtual ~Listener(); // inject an event into the notification system static void notify(NotificationDomain domain, NotificationEvent event, const CssmData &data); + static void notify(NotificationDomain domain, + NotificationEvent event, uint32 sequence, const CssmData &data); static bool remove(Port port); - - // consume an event for this Listener - virtual void notifyMe(NotificationDomain domain, - NotificationEvent event, const CssmData &data) = 0; const NotificationDomain domain; const NotificationMask events; @@ -78,37 +82,59 @@ public: { return (1 << event) & events; } protected: - Port mPort; - + class Notification : public RefCount { + public: + Notification(NotificationDomain domain, NotificationEvent event, + uint32 seq, const CssmData &data); + virtual ~Notification(); + + const NotificationDomain domain; + const NotificationEvent event; + const uint32 sequence; + const CssmAutoData data; + + size_t size() const + { return data.length(); } //@@@ add "slop" here for heuristic? + }; + + virtual void notifyMe(Notification *message) = 0; + +public: + class JitterBuffer { + public: + JitterBuffer() : mNotifyLast(0) { } + + bool inSequence(Notification *message); + RefPointer popNotification(); + + private: + uint32 mNotifyLast; // last notification seq processed + typedef std::map > JBuffer; + JBuffer mBuffer; // early messages buffer + }; + private: - void setup(); + static void Listener::sendNotification(Notification *message); private: - typedef multimap ListenerMap; + typedef multimap > ListenerMap; static ListenerMap listeners; static Mutex setLock; }; -// -// A registered receiver of notifications. -// Each one is for a particular database (or all), set of events, -// and to a particular Mach port. A process may have any number -// of listeners, each independent; so that multiple notifications can -// be sent to the same process if it registers repeatedly. -// -class Process; -class ProcessListener : public Listener { -public: - ProcessListener(Process &proc, Port receiver, NotificationDomain domain, - NotificationMask evs = SecurityServer::kNotificationAllEvents); +class SharedMemoryListener : public Listener, public SharedMemoryServer, public Security::MachPlusPlus::MachServer::Timer +{ +protected: + virtual void action (); + virtual void notifyMe(Notification *message); - Process &process; - - void notifyMe(NotificationDomain domain, - NotificationEvent event, const CssmData &data); -}; + bool mActive; +public: + SharedMemoryListener (const char* serverName, u_int32_t serverSize); + virtual ~SharedMemoryListener (); +}; -#endif //_H_NOTIFICATIONS +#endif diff --git a/src/osxcodewrap.cpp b/src/osxcodewrap.cpp new file mode 100644 index 0000000..8aeabef --- /dev/null +++ b/src/osxcodewrap.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +// +// osxcodewrap - wrap an OSXCode around a SecCodeRef +// +#include "osxcodewrap.h" +#include + + +// +// We don't really HAVE a canonical encoding, in the sense that +// the matching OSXCode::decode function won't recognize us. +// That's not the point; if you want use the old transmission logic, +// use the canonical OSXCode subclasses. +// +string OSXCodeWrap::encode() const +{ + return "?:unsupported"; +} + + +// +// Canonical path directly from the SecCode's mouth +// +string OSXCodeWrap::canonicalPath() const +{ + CFURLRef path; + MacOSError::check(SecCodeCopyPath(mCode, kSecCSDefaultFlags, &path)); + return cfString(path, true); +} + + +// +// The executable path is a bit annoying to get, but not quite +// annoying enough to cache the result. +// +string OSXCodeWrap::executablePath() const +{ + CFRef info; + MacOSError::check(SecCodeCopySigningInformation(mCode, kSecCSDefaultFlags, &info.aref())); + return cfString(CFURLRef(CFDictionaryGetValue(info, kSecCodeInfoMainExecutable))); +} diff --git a/src/osxcodewrap.h b/src/osxcodewrap.h new file mode 100644 index 0000000..8112fad --- /dev/null +++ b/src/osxcodewrap.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +// +// osxcodewrap - wrap an OSXCode around a SecCodeRef +// +#ifndef _H_OSXCODEWRAP +#define _H_OSXCODEWRAP + +#include +#include +#include +#include + + +// +// OSXCodeWrap is a partial OSXCode implementation that gets all its information +// from a SecStaticCodeRef API object. OSXCode and SecStaticCode are in many ways +// twin brothers, and this class allows the use of a SecStaticCode in places where +// an OSXCode is required. +// Note that OSXCodeWrap will not provide the capabilities of the canonical +// OSXCode subclasses (such as Bundle). its encodings will always specify a type +// code of '?' (unknown). +// +class OSXCodeWrap : public OSXCode { +public: + OSXCodeWrap(SecStaticCodeRef code) : mCode(code) { } + + string encode() const; + + string canonicalPath() const; + string executablePath() const; + +private: + CFCopyRef mCode; +}; + + +#endif //_H_OSXCODEWRAP diff --git a/src/pcscmonitor.cpp b/src/pcscmonitor.cpp index 6921eca..2385507 100644 --- a/src/pcscmonitor.cpp +++ b/src/pcscmonitor.cpp @@ -47,6 +47,11 @@ static const char PCSCD_EXEC_PATH[] = "/usr/sbin/pcscd"; // override with $PCSCD static const char PCSCD_WORKING_DIR[] = "/var/run/pcscd"; // pcscd's working directory static const Time::Interval PCSCD_IDLE_SHUTDOWN(120); // kill daemon if no devices present +// Apple built-in iSight Device VendorID/ProductID: 0x05AC/0x8501 + +static const uint32_t kVendorProductMask = 0x0000FFFF; +static const uint32_t kVendorIDApple = 0x05AC; +static const uint16_t kProductIDBuiltInISight = 0x8501; // // Construct a PCSCMonitor. @@ -143,6 +148,24 @@ void PCSCMonitor::pollReaders() } } +// +// Poll PCSC for smartcard status. +// We are enumerating all readers on each call. +// +void PCSCMonitor::clearReaders() +{ + if (!mReaders.empty()) { + // uh-oh. We had readers connected when pcscd suddenly left + secdebug("pcsc", "%ld readers were present when pcscd died", mReaders.size()); + for (ReaderMap::const_iterator it = mReaders.begin(); it != mReaders.end(); it++) { + Reader *reader = it->second; + secdebug("pcsc", "removing reader %s", reader->name().c_str()); + reader->kill(); // prepare to die + } + mReaders.erase(mReaders.begin(), mReaders.end()); + secdebug("pcsc", "orphaned readers cleared"); + } +} TokenCache& PCSCMonitor::getTokenCache () { @@ -204,12 +227,16 @@ void PCSCMonitor::childAction() // Event notifier. // These events are sent by pcscd for our (sole) benefit. // -void PCSCMonitor::notifyMe(SecurityServer::NotificationDomain domain, - SecurityServer::NotificationEvent event, const CssmData &data) +void PCSCMonitor::notifyMe(Notification *message) { Server::active().longTermActivity(); StLock _(*this); assert(mServiceLevel == externalDaemon || Child::state() == alive); + if (message->event == kNotificationPCSCInitialized) + { + clearReaders(); +// mSession.close(); + } pollReaders(); scheduleTimer(mReaders.empty() && !mGoingToSleep); } @@ -373,20 +400,31 @@ PCSCMonitor::DeviceSupport PCSCMonitor::deviceSupport(const IOKit::Device &dev) return definite; case kUSBVendorSpecificInterfaceClass: secdebug("scsel", " Vendor-specific interface - possible match"); + if (isExcludedDevice(dev)) + { + secdebug("scsel", " interface class %d is not a smartcard device (excluded)", clas); + return impossible; + } return possible; default: - secdebug("scsel", " interface class %ld is not a smartcard device", clas); + secdebug("scsel", " interface class %d is not a smartcard device", clas); return impossible; } // noncomposite USB device if (CFRef cfDevice = dev.property("bDeviceClass")) - if (cfNumber(cfDevice) == kUSBVendorSpecificClass) { + if (cfNumber(cfDevice) == kUSBVendorSpecificClass) + { + if (isExcludedDevice(dev)) + { + secdebug("scsel", " device class %d is not a smartcard device (excluded)", cfNumber(cfDevice)); + return impossible; + } secdebug("scsel", " Vendor-specific device - possible match"); return possible; } - // PCCard (aka PCMCIA aka ...) interface (don't know how to recognize a reader here) + // PCCard (aka PCMCIA aka ...) interface (don't know how to recognize a reader here) if (CFRef ioName = dev.property("IOName")) if (cfString(ioName).find("pccard", 0, 1) == 0) { secdebug("scsel", " PCCard - possible match"); @@ -399,6 +437,19 @@ PCSCMonitor::DeviceSupport PCSCMonitor::deviceSupport(const IOKit::Device &dev) } } +bool PCSCMonitor::isExcludedDevice(const IOKit::Device &dev) +{ + uint32_t vendorID = 0, productID = 0; + // Simplified version of getVendorAndProductID in pcscd + if (CFRef cfVendorID = dev.property(kUSBVendorID)) + vendorID = cfNumber(cfVendorID); + + if (CFRef cfProductID = dev.property(kUSBProductID)) + productID = cfNumber(cfProductID); + + secdebug("scsel", " checking device for possible exclusion [vendor id: 0x%08X, product id: 0x%08X]", vendorID, productID); + return ((vendorID & kVendorProductMask) == kVendorIDApple && (productID & kVendorProductMask) == kProductIDBuiltInISight); +} // // This gets called (by the Unix/Child system) when pcscd has died for any reason @@ -408,16 +459,6 @@ void PCSCMonitor::dying() Server::active().longTermActivity(); StLock _(*this); assert(Child::state() == dead); - if (!mReaders.empty()) { - // uh-oh. We had readers connected when pcscd suddenly left - secdebug("pcsc", "%ld readers were present when pcscd died", mReaders.size()); - for (ReaderMap::const_iterator it = mReaders.begin(); it != mReaders.end(); it++) { - Reader *reader = it->second; - secdebug("pcsc", "removing reader %s", reader->name().c_str()); - reader->kill(); // prepare to die - } - mReaders.erase(mReaders.begin(), mReaders.end()); - secdebug("pcsc", "orphaned readers cleared"); - } + clearReaders(); //@@@ this is where we would attempt a restart, if we wanted to... } diff --git a/src/pcscmonitor.h b/src/pcscmonitor.h index 4e48d5e..6b023e1 100644 --- a/src/pcscmonitor.h +++ b/src/pcscmonitor.h @@ -65,7 +65,8 @@ public: protected: void pollReaders(); - + void clearReaders(); + Server &server; TokenCache *cache; std::string cachePath; @@ -73,8 +74,7 @@ protected: protected: // Listener - void notifyMe(SecurityServer::NotificationDomain domain, - SecurityServer::NotificationEvent event, const CssmData &data); + void notifyMe(Notification *message); // MachServer::Timer void action(); @@ -102,7 +102,8 @@ protected: possible // perhaps... we're not sure }; DeviceSupport deviceSupport(const IOKit::Device &dev); - + bool isExcludedDevice(const IOKit::Device &dev); + private: ServiceLevel mServiceLevel; // level of service requested/determined void (PCSCMonitor::*mTimerAction)(); // what to do when our timer fires diff --git a/src/process.cpp b/src/process.cpp index 87caf65..4f482f8 100644 --- a/src/process.cpp +++ b/src/process.cpp @@ -30,7 +30,9 @@ #include "session.h" #include "tempdatabase.h" #include "authority.h" -#include "flippers.h" + +#include //@@@ debug only +#include "agentquery.h" // @@ -51,8 +53,9 @@ Process::Process(Port servicePort, TaskPort taskPort, CssmError::throwMe(CSSMERR_CSSM_ADDIN_AUTHENTICATE_FAILED); // you lied! } - setup(info, identity); - + setup(info); + ClientIdentification::setup(this->pid()); + secdebug("SS", "New process %p(%d) uid=%d gid=%d session=%p TP=%d %sfor %s", this, mPid, mUid, mGid, &session(), mTaskPort.port(), @@ -63,8 +66,9 @@ Process::Process(Port servicePort, TaskPort taskPort, // // Screen a process setup request for an existing process. -// This usually means the client has called exec(2) and forgotten all about itself. -// Though it could be a nefarious attempt to fool us... +// This means the client has requested intialization even though we remember having +// talked to it in the past. This could either be an exec(2), or the client could just +// have forgotten all about its securityd client state. Or it could be an attack... // void Process::reset(Port servicePort, TaskPort taskPort, const ClientSetupInfo *info, const char *identity, const CommonCriteria::AuditToken &audit) @@ -73,10 +77,24 @@ void Process::reset(Port servicePort, TaskPort taskPort, secdebug("SS", "Process %p(%d) reset mismatch (sp %d-%d, tp %d-%d) for %s", this, pid(), servicePort.port(), session().servicePort().port(), taskPort.port(), mTaskPort.port(), (identity && identity[0]) ? identity : "(unknown)"); - CssmError::throwMe(CSSMERR_CSSM_ADDIN_AUTHENTICATE_FAILED); // liar + Session &newSession = Session::find(servicePort); + Syslog::alert("Process reset %p(%d) session %d(0x%x:0x%x)->%d(0x%x:0x%x) for %s", + this, pid(), + session().servicePort().port(), &session(), session().attributes(), + newSession.servicePort().port(), &newSession, newSession.attributes(), + (identity && identity[0]) ? identity : "(unknown)"); + //CssmError::throwMe(CSSM_ERRCODE_VERIFICATION_FAILURE); // liar + } + + string oldPath = codePath(processCode()); + setup(info); + ClientIdentification::setup(this->pid()); + if (codePath(processCode()) == oldPath) { + secdebug("SS", "process %p(%d) path unchanged; assuming client-side reset", this, mPid); + } else { + secdebug("SS", "process %p(%d) path changed; assuming exec with full reset", this, mPid); + CodeSigningHost::reset(); } - - setup(info, identity); secdebug("SS", "process %p(%d) has reset; now %sfor %s", this, mPid, mByteFlipped ? "FLIP " : "", @@ -87,13 +105,14 @@ void Process::reset(Port servicePort, TaskPort taskPort, // // Common set processing // -void Process::setup(const ClientSetupInfo *info, const char *identity) +void Process::setup(const ClientSetupInfo *info) { // process setup info assert(info); uint32 pversion; if (info->order == 0x1234) { // right side up pversion = info->version; + mByteFlipped = false; } else if (info->order == 0x34120000) { // flip side up pversion = ntohl(info->version); mByteFlipped = true; @@ -103,17 +122,6 @@ void Process::setup(const ClientSetupInfo *info, const char *identity) // check wire protocol version if (pversion != SSPROTOVERSION) CssmError::throwMe(CSSM_ERRCODE_INCOMPATIBLE_VERSION); - - // process identity (if given) - try { - mClientCode = OSXCode::decode(identity); - mClientIdent = deferred; // will calculate code identity when needed - } catch (...) { - secdebug("SS", "process %p(%d) identity decode threw exception", this, pid()); - mClientCode = NULL; - mClientIdent = unknown; // no chance to squeeze a code identity from this - secdebug("SS", "process %p(%d) no clientCode - marked anonymous", this, pid()); - } } @@ -188,43 +196,6 @@ void Process::changeSession(Port servicePort) } -// -// CodeSignatures implementation of Identity. -// The caller must make sure we have a valid (not necessarily hash-able) clientCode(). -// -string Process::getPath() const -{ - assert(mClientCode); - return mClientCode->canonicalPath(); -} - -const CssmData Process::getHash(CodeSigning::OSXSigner &signer) const -{ - switch (mClientIdent) { - case deferred: - try { - // try to calculate our signature hash (first time use) - mCachedSignature.reset(mClientCode->sign(signer)); - assert(mCachedSignature.get()); - mClientIdent = known; - secdebug("SS", "process %p(%d) code signature computed", this, pid()); - break; - } catch (...) { - // couldn't get client signature (unreadable, gone, hack attack, ...) - mClientIdent = unknown; - secdebug("SS", "process %p(%d) no code signature - anonymous", this, pid()); - CssmError::throwMe(CSSM_ERRCODE_INSUFFICIENT_CLIENT_IDENTIFICATION); - } - case known: - assert(mCachedSignature.get()); - break; - case unknown: - CssmError::throwMe(CSSM_ERRCODE_INSUFFICIENT_CLIENT_IDENTIFICATION); - } - return CssmData(*mCachedSignature); -} - - // // Authorization set maintainance // @@ -267,21 +238,6 @@ bool Process::removeAuthorization(AuthorizationToken *auth) } -// -// Notification client maintainance -// -void Process::requestNotifications(Port port, SecurityServer::NotificationDomain domain, SecurityServer::NotificationMask events) -{ - new ProcessListener(*this, port, domain, events); -} - -void Process::stopNotifications(Port port) -{ - if (!Listener::remove(port)) - CssmError::throwMe(CSSMERR_CSSM_INVALID_HANDLE_USAGE); //@@@ bad name (should be "no such callback") -} - - // // Debug dump support // @@ -294,21 +250,8 @@ void Process::dumpNode() Debug::dump(" FLIPPED"); Debug::dump(" task=%d pid=%d uid/gid=%d/%d", mTaskPort.port(), mPid, mUid, mGid); - if (mClientCode) { - Debug::dump(" client=%s", mClientCode->canonicalPath().c_str()); - switch (mClientIdent) { - case deferred: - break; - case known: - Debug::dump("[OK]"); - break; - case unknown: - Debug::dump("[UNKNOWN]"); - break; - } - } else { - Debug::dump(" NO CLIENT ID"); - } + CodeSigningHost::dump(); + ClientIdentification::dump(); } #endif //DEBUGDUMP diff --git a/src/process.h b/src/process.h index 97735f3..59cc330 100644 --- a/src/process.h +++ b/src/process.h @@ -32,8 +32,9 @@ #include #include #include +#include "clientid.h" +#include "csproxy.h" #include "localkey.h" -#include "codesigdb.h" #include "notifications.h" #include @@ -47,9 +48,25 @@ class AuthorizationToken; // // A Process object represents a UNIX process (and associated Mach Task) that has -// had contact with us and may have some state associated with it. +// had contact with us and may have some state associated with it. It primarily tracks +// the process nature of the client. Individual threads in the client are tracked by +// Connection objects. // -class Process : public PerProcess, public CodeSignatures::Identity { +// Code Signing-style Guest identities are managed in two of our mix-ins. The two play +// distinct but related roles: +// * CodeSigningHost manages the public identity of guests within the client. +// In this relationship, securityd provides registry and proxy services to the client. +// * ClientIdentification tracks the identity of guests in the client *as securityd clients*. +// It is concerned with which guest is asking for securityd services, and whether this +// should be granted. +// Often, the two form a loop: ClientIdentification uses CodeSigningHost to determine +// the guest client identity, but it does so through public (Mach IPC) interfaces, because +// clients may implement their own proxy (though currently not registry) services. +// We could short-circuit the IPC leg in those cases where securityd serves itself, +// but there's no evidence (yet) that this is worth the trouble. +// +class Process : public PerProcess, + public CodeSigningHost, public ClientIdentification { public: Process(Port servicePort, TaskPort tPort, const ClientSetupInfo *info, const char *identity, @@ -66,8 +83,6 @@ public: TaskPort taskPort() const { return mTaskPort; } bool byteFlipped() const { return mByteFlipped; } - OSXCode *clientCode() const { return (mClientIdent == unknown) ? NULL : mClientCode; } - void addAuthorization(AuthorizationToken *auth); void checkAuthorization(AuthorizationToken *auth); bool removeAuthorization(AuthorizationToken *auth); @@ -77,9 +92,6 @@ public: void changeSession(Port servicePort); // very special indeed - void requestNotifications(Port port, NotificationDomain domain, NotificationMask events); - void stopNotifications(Port port); - Session& session() const; LocalDatabase &localStore(); @@ -91,11 +103,8 @@ public: IFDUMP(void dumpNode()); -protected: - std::string getPath() const; - const CssmData getHash(CodeSigning::OSXSigner &signer) const; - - void setup(const ClientSetupInfo *info, const char *identity); +private: + void setup(const ClientSetupInfo *info); private: // peer state: established during connection startup; fixed thereafter @@ -105,10 +114,6 @@ private: uid_t mUid; // UNIX uid credential gid_t mGid; // primary UNIX gid credential - RefPointer mClientCode; // code object for client (NULL if unknown) - mutable enum { deferred, known, unknown } mClientIdent; // state of client identity - mutable auto_ptr mCachedSignature; // cached signature (if already known) - // authorization dictionary typedef multiset AuthorizationSet; AuthorizationSet mAuthorizations; // set of valid authorizations for process diff --git a/src/securityd.exp b/src/securityd.exp new file mode 100644 index 0000000..e69de29 diff --git a/src/securityd.order b/src/securityd.order index e181296..bd1a5ae 100644 --- a/src/securityd.order +++ b/src/securityd.order @@ -321,7 +321,6 @@ _uw_install_context_1 _init_dwarf_reg_size_table eh_rest_world_r10 rest_world_eh_r7r8 -__Unwind_Resume ___cxa_begin_catch __ZN8Security9CssmError9cssmErrorERKNS_11CommonErrorEl __ZNK13Authorization5Error8osStatusEv diff --git a/src/server.cpp b/src/server.cpp index f440a7d..f07241d 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -37,6 +37,9 @@ #include #include +#include "agentquery.h" + + using namespace MachPlusPlus; // @@ -57,6 +60,7 @@ Authority::~Authority() Server::Server(Authority &authority, CodeSignatures &signatures, const char *bootstrapName) : MachServer(bootstrapName), mBootstrapName(bootstrapName), + mShutdown(shutdownImmediately), mCSPModule(gGuidAppleCSP, mCssm), mCSP(mCSPModule), mAuthority(authority), mCodeSignatures(signatures), @@ -106,11 +110,11 @@ Connection &Server::connection(bool tolerant) return *conn; } -void Server::requestComplete() +void Server::requestComplete(CSSM_RETURN &rcode) { // note: there may not be an active connection if connection setup failed if (RefPointer &conn = active().mCurrentConnection()) { - conn->endWork(); + conn->endWork(rcode); conn = NULL; } IFDUMPING("state", NodeCore::dumpAll()); @@ -199,21 +203,18 @@ void Server::threadLimitReached(UInt32 limit) boolean_t ucsp_server(mach_msg_header_t *, mach_msg_header_t *); boolean_t self_server(mach_msg_header_t *, mach_msg_header_t *); -#if defined(NDEBUG) - -boolean_t Server::handle(mach_msg_header_t *in, mach_msg_header_t *out) -{ - return ucsp_server(in, out) || self_server(in, out); -} -#else //NDEBUG +#if !defined(NDEBUG) struct IPCName { const char *name; int ipc; }; static IPCName ucspNames[] = { subsystem_to_name_map_ucsp }; // generated by MIG static IPCName selfNames[] = { subsystem_to_name_map_self }; // generated by MIG +#endif //NDEBUG + boolean_t Server::handle(mach_msg_header_t *in, mach_msg_header_t *out) { +#if !defined(NDEBUG) const int id = in->msgh_id; const int ucspBase = ucspNames[0].ipc; const int selfBase = selfNames[0].ipc; @@ -222,13 +223,14 @@ boolean_t Server::handle(mach_msg_header_t *in, mach_msg_header_t *out) (id >= selfBase && id < selfBase + self_MSG_COUNT) ? selfNames[id - selfBase].name : "OUT OF BOUNDS"; secdebug("SSreq", "begin %s (%d)", name, in->msgh_id); +#endif //NDEBUG + boolean_t result = ucsp_server(in, out) || self_server(in, out); - secdebug("SSreq", "end %s (%d)", name, in->msgh_id); + IFDEBUG(secdebug("SSreq", "end %s (%d)", name, in->msgh_id)); + return result; } -#endif //NDEBUG - // // Set up a new Connection. This establishes the environment (process et al) as needed @@ -251,6 +253,7 @@ void Server::setupConnection(ConnectLevel type, Port servicePort, Port replyPort // the client has amnesia - reset it assert(info && identity); proc->reset(servicePort, taskPort, info, identity, AuditToken(auditToken)); + proc->changeSession(servicePort); } if (!proc) { if (type == connectNewThread) // client error (or attack) @@ -258,6 +261,7 @@ void Server::setupConnection(ConnectLevel type, Port servicePort, Port replyPort assert(info && identity); proc = new Process(servicePort, taskPort, info, identity, AuditToken(auditToken)); notifyIfDead(taskPort); + mPids[proc->pid()] = proc; } // now, establish a connection and register it in the server @@ -305,15 +309,13 @@ void Server::notifyDeadName(Port port) // is it a process? PortMap::iterator procIt = mProcesses.find(port); if (procIt != mProcesses.end()) { - procIt->second->kill(); + Process *proc = procIt->second; + proc->kill(); + mPids.erase(proc->pid()); mProcesses.erase(procIt); return; } - // is it a notification client? - if (Listener::remove(port)) - return; - // well, what IS IT?! secdebug("server", "spurious dead port notification for port %d", port.port()); } @@ -342,7 +344,7 @@ kern_return_t self_server_handleSignal(mach_port_t sport, if (taskPort != mach_task_self()) { Syslog::error("handleSignal: received from someone other than myself"); secdebug("SS", "unauthorized handleSignal"); - return 0; + return KERN_SUCCESS; } secdebug("SS", "dispatching indirect signal %d", sig); switch (sig) { @@ -350,10 +352,23 @@ kern_return_t self_server_handleSignal(mach_port_t sport, ServerChild::checkChildren(); break; case SIGINT: - case SIGTERM: - secdebug("SS", "signal %d received: terminating", sig); - Syslog::notice("securityd terminating due to signal %d", sig); + secdebug("SS", "SIGINT received: terminating immediately"); + Syslog::notice("securityd terminated due to SIGINT"); exit(0); + case SIGTERM: + if (Server::active().beginShutdown()) { + Syslog::notice("securityd shutting down; lingering for remaining clients"); + } else { + secdebug("SS", "SIGTERM received: terminating immediately"); + Syslog::notice("securityd terminated due to SIGTERM"); + exit(0); + } + break; + case SIGPIPE: + secdebug("SS", "SIGPIPE received: ignoring"); + Syslog::notice("securityd ignoring SIGPIPE received"); + break; + #if defined(DEBUGDUMP) case SIGUSR1: NodeCore::dumpAll(); @@ -366,7 +381,7 @@ kern_return_t self_server_handleSignal(mach_port_t sport, secdebug("SS", "exception handling a signal (ignored)"); } mach_port_deallocate(mach_task_self(), taskPort); - return 0; + return KERN_SUCCESS; } @@ -402,6 +417,85 @@ void Server::SleepWatcher::remove(PowerWatcher *client) } +// +// Expose the process/pid map to the outside +// +Process *Server::findPid(pid_t pid) const +{ + PidMap::const_iterator it = mPids.find(pid); + return (it == mPids.end()) ? NULL : it->second; +} + + +// +// Set delayed shutdown mode +// +void Server::waitForClients(bool waiting) +{ + if (mShutdown == shuttingDown) // too late to change your mind now + return; + if (waiting) + mShutdown = shutdownDelayed; + else + mShutdown = shutdownImmediately; +} + + +// +// Shutdown processing +// +bool Server::beginShutdown() +{ + if (mShutdown != shutdownDelayed) + return false; + + secdebug("server", "beginning shutdown with %d client(s)", int(mProcesses.size())); + mShutdown = shuttingDown; + +#if defined(SHUTDOWN_SNITCH) + struct Snitch : public MachServer::Timer { + void action() { Server::active().shutdownSnitch(); } + }; + setTimer(new Snitch, Time::Interval(29)); // right before we get SIGKILLed +#endif + + return true; +} + + +void Server::eventDone() +{ + if (mShutdown == shuttingDown) { + if (mProcesses.empty()) { + secdebug("SS", "out of clients - shutdown complete"); + Syslog::notice("securityd has finished serving its clients - terminating now"); + exit(0); + } else { + secdebug("SS", "shutdown in progress - %d process(es) left", int(mProcesses.size())); + IFDUMPING("shutdown", NodeCore::dumpAll()); + } + } +} + +#if defined(SHUTDOWN_SNITCH) + +void Server::shutdownSnitch() +{ + Syslog::notice("29 seconds after shutdown began, securityd still has %d clients:", int(mPids.size())); + for (PidMap::const_iterator it = mPids.begin(); it != mPids.end(); ++it) + if (SecCodeRef clientCode = it->second->processCode()) { + CFRef path; + SecCodeCopyPath(clientCode, kSecCSDefaultFlags, &path.aref()); + if (path) + Syslog::notice(" %s (%d)", cfString(path).c_str(), it->first); + else + Syslog::notice(" pid=%d", it->first); + } +} + +#endif //SHUTDOWN_SNITCH + + // // Initialize the CSSM/MDS subsystem. // This was once done lazily on demand. These days, we are setting up the @@ -414,7 +508,8 @@ void Server::loadCssm() StLock _(*this); if (!mCssm->isActive()) { secdebug("SS", "Installing MDS"); - MDSClient::mds().install(); + IFDEBUG(if (geteuid() == 0)) + MDSClient::mds().install(); secdebug("SS", "CSSM initializing"); mCssm->init(); mCSP->attach(); @@ -422,3 +517,18 @@ void Server::loadCssm() } } } + + +// +// LongtermActivity/lock combo +// +LongtermStLock::LongtermStLock(Mutex &lck) + : StLock(lck, false) // don't take the lock yet +{ + if (lck.tryLock()) { // uncontested + this->mActive = true; + } else { // contested - need backup thread + Server::active().longTermActivity(); + this->lock(); + } +} diff --git a/src/server.h b/src/server.h index 011a649..5d6717b 100644 --- a/src/server.h +++ b/src/server.h @@ -20,6 +20,7 @@ * * @APPLE_LICENSE_HEADER_END@ */ +#define SHUTDOWN_SNITCH // @@ -34,7 +35,6 @@ #include #include #include -#include #include #include #include "codesigdb.h" @@ -94,7 +94,7 @@ public: // static Connection &connection(mach_port_t replyPort); // find by reply port and make active static Connection &connection(bool tolerant = false); // return active (or fail unless tolerant) - static void requestComplete(); // de-activate active connection + static void requestComplete(CSSM_RETURN &rcode); // de-activate active connection // // Process and session of the active Connection @@ -161,6 +161,7 @@ protected: void notifyDeadName(Port port); void notifyNoSenders(Port port, mach_port_mscount_t); void threadLimitReached(UInt32 count); + void eventDone(); private: class SleepWatcher : public MachPlusPlus::PortPowerWatcher { @@ -182,6 +183,12 @@ public: using MachServer::remove; void add(MachPlusPlus::PowerWatcher *client) { StLock _(*this); sleepWatcher.add(client); } void remove(MachPlusPlus::PowerWatcher *client) { StLock _(*this); sleepWatcher.remove(client); } + +public: + Process *findPid(pid_t pid) const; + + void waitForClients(bool waiting); // set waiting behavior + bool beginShutdown(); // start delayed shutdown if configured private: // mach bootstrap registration name @@ -191,7 +198,16 @@ private: PortMap mConnections; // process map (by process task port) - PortMap mProcesses; + typedef std::map PidMap; + PortMap mProcesses; // strong reference + PidMap mPids; // weak reference (subsidiary to mProcesses) + + enum ShutdownMode { + shutdownImmediately, // shut down immediately on SIGTERM + shutdownDelayed, // wait for clients on SIGTERM + shuttingDown // delayed shutdown in progress + } mShutdown; // shutdown mode + void shutdownSnitch(); // rat out lingering clients (to syslog) // Current connection, if any (per thread). // Set as a side effect of calling connection(mach_port_t) @@ -210,4 +226,14 @@ private: CommonCriteria::AuditSession mAudit; }; + +// +// A StLock that (also) declares a longTermActivity (only) once it's been entered. +// +class LongtermStLock : public StLock { +public: + LongtermStLock(Mutex &lck); + // destructor inherited +}; + #endif //_H_SERVER diff --git a/src/session.cpp b/src/session.cpp index 7cabc91..105b2af 100644 --- a/src/session.cpp +++ b/src/session.cpp @@ -31,17 +31,21 @@ // // Sessions are multi-threaded objects. // +#include +#include // kAuthorizationFlagLeastPrivileged + #include "session.h" #include "connection.h" #include "database.h" #include "server.h" - // // The static session map // PortMap Session::mSessions; +std::string Session::kUsername = "username"; +std::string Session::kRealname = "realname"; // // Create a Session object from initial parameters (create) @@ -164,21 +168,11 @@ RootSession::RootSession(Server &server, SessionAttributeBits attrs) mSessions[mServicePort] = this; } -uid_t RootSession::originatorUid() const -{ - return 0; // it's root, obviously -} - -CFDataRef RootSession::copyUserPrefs() -{ - return NULL; -} - // // Dynamic sessions use the given bootstrap and re-register in it // DynamicSession::DynamicSession(TaskPort taskPort) - : ReceivePort(Server::active().bootstrapName(), taskPort.bootstrap()), + : ReceivePort(Server::active().bootstrapName(), taskPort.bootstrap(), false), Session(taskPort.bootstrap(), *this), mOriginatorTask(taskPort), mHaveOriginatorUid(false) { @@ -265,10 +259,19 @@ void DynamicSession::originatorUid(uid_t uid) MacOSError::throwMe(errSessionAuthorizationDenied); mHaveOriginatorUid = true; mOriginatorUid = uid; + + Server::active().longTermActivity(); + struct passwd *pw = getpwuid(uid); + + if (pw != NULL) { + + mOriginatorCredential = Credential(uid, pw->pw_name ? pw->pw_name : "", pw->pw_gecos ? pw->pw_gecos : "", true/*shared*/); + endpwent(); + } + secdebug("SSsession", "%p session uid set to %d", this, uid); } - // // Authorization operations // @@ -282,7 +285,7 @@ OSStatus Session::authCreate(const AuthItemSet &rights, CredentialSet resultCreds; // this will acquire the object lock, so we delay acquiring it (@@@ no longer needed) - auto_ptr auth(new AuthorizationToken(*this, resultCreds, auditToken)); + auto_ptr auth(new AuthorizationToken(*this, resultCreds, auditToken, (flags&kAuthorizationFlagLeastPrivileged))); // Make a copy of the mSessionCreds CredentialSet sessionCreds; @@ -335,9 +338,17 @@ OSStatus Session::authGetRights(const AuthorizationBlob &authBlob, const AuthItemSet &rights, const AuthItemSet &environment, AuthorizationFlags flags, AuthItemSet &grantedRights) +{ + AuthorizationToken &auth = authorization(authBlob); + return auth.session().authGetRights(auth, rights, environment, flags, grantedRights); +} + +OSStatus Session::authGetRights(AuthorizationToken &auth, + const AuthItemSet &rights, const AuthItemSet &environment, + AuthorizationFlags flags, + AuthItemSet &grantedRights) { CredentialSet resultCreds; - AuthorizationToken &auth = authorization(authBlob); CredentialSet effective; { StLock _(mCredsLock); @@ -355,7 +366,7 @@ OSStatus Session::authGetRights(const AuthorizationBlob &authBlob, } secdebug("SSauth", "Authorization %p copyRights asked for %d got %d", - &authorization(authBlob), int(rights.size()), int(grantedRights.size())); + &auth, int(rights.size()), int(grantedRights.size())); return result; } @@ -487,7 +498,7 @@ void Session::mergeCredentials(CredentialSet &creds) secdebug("SSsession", "%p merge creds @%p", this, &creds); CredentialSet updatedCredentials = creds; for (CredentialSet::const_iterator it = creds.begin(); it != creds.end(); it++) - if (((*it)->isShared() && (*it)->isValid())) { + if ((*it)->isShared() && (*it)->isValid()) { CredentialSet::iterator old = mSessionCreds.find(*it); if (old == mSessionCreds.end()) { mSessionCreds.insert(*it); @@ -542,6 +553,8 @@ Session::authhost(const AuthHostType hostType, const bool restart) void DynamicSession::setUserPrefs(CFDataRef userPrefsDict) { checkOriginator(); + if (Server::process().uid() != 0) + MacOSError::throwMe(errSessionAuthorizationDenied); StLock _(*this); mSessionAgentPrefs = userPrefsDict; } diff --git a/src/session.h b/src/session.h index 7799cc4..2575794 100644 --- a/src/session.h +++ b/src/session.h @@ -77,10 +77,16 @@ public: bool attribute(SessionAttributeBits bits) const { return mAttributes & bits; } virtual void setupAttributes(SessionCreationFlags flags, SessionAttributeBits attrs); + virtual bool haveOriginatorUid() const = 0; virtual uid_t originatorUid() const = 0; + Credential originatorCredential() const { return mOriginatorCredential; } + virtual CFDataRef copyUserPrefs() = 0; + static std::string kUsername; + static std::string kRealname; + protected: void setAttributes(SessionAttributeBits attrs) { mAttributes |= attrs; } @@ -90,7 +96,7 @@ public: OSStatus authCreate(const AuthItemSet &rights, const AuthItemSet &environment, AuthorizationFlags flags, AuthorizationBlob &newHandle, const audit_token_t &auditToken); void authFree(const AuthorizationBlob &auth, AuthorizationFlags flags); - OSStatus authGetRights(const AuthorizationBlob &auth, + static OSStatus authGetRights(const AuthorizationBlob &auth, const AuthItemSet &requestedRights, const AuthItemSet &environment, AuthorizationFlags flags, AuthItemSet &grantedRights); OSStatus authGetInfo(const AuthorizationBlob &auth, const char *tag, AuthItemSet &contextInfo); @@ -109,7 +115,10 @@ private: }; protected: - AuthorizationToken &authorization(const AuthorizationBlob &blob); + static AuthorizationToken &authorization(const AuthorizationBlob &blob); + OSStatus authGetRights(AuthorizationToken &auth, + const AuthItemSet &requestedRights, const AuthItemSet &environment, + AuthorizationFlags flags, AuthItemSet &grantedRights); void mergeCredentials(CredentialSet &creds); public: @@ -134,8 +143,9 @@ protected: mutable Mutex mAuthHostLock; AuthHostInstance *mSecurityAgent; AuthHostInstance *mAuthHost; - + CFRef mSessionAgentPrefs; + Credential mOriginatorCredential; void kill(); @@ -165,8 +175,8 @@ public: RootSession(Server &server, SessionAttributeBits attrs = 0); bool haveOriginatorUid() const { return true; } - uid_t originatorUid() const; - CFDataRef copyUserPrefs(); + uid_t originatorUid() const { return 0; } + CFDataRef copyUserPrefs() { return NULL; } }; diff --git a/src/token.cpp b/src/token.cpp index 2f3381b..9b3de21 100644 --- a/src/token.cpp +++ b/src/token.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2007 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -67,7 +67,7 @@ Token::Token() Token::~Token() { - secdebug("token", "%p (%s:%ld) destroyed", + secdebug("token", "%p (%s:%d) destroyed", this, mGuid.toString().c_str(), mSubservice); } @@ -128,6 +128,27 @@ RefPointer Token::find(uint32 ssid) } +// +// We override getAcl to provide PIN state feedback +// +void Token::getAcl(const char *tag, uint32 &count, AclEntryInfo *&acls) +{ + if (pinFromAclTag(tag, "?")) { // read from tokend - do not cache + AclEntryInfo *racls; + token().tokend().getAcl(aclKind(), tokenHandle(), tag, count, racls); + // make a chunk-copy because that's the contract we have with the caller + acls = Allocator::standard().alloc(count * sizeof(AclEntryInfo)); + memcpy(acls, racls, count * sizeof(AclEntryInfo)); + ChunkCopyWalker copy; + for (uint32 n = 0; n < count; n++) + walk(copy, acls[n]); + return; + } + + TokenAcl::cssmGetAcl(tag, count, acls); +} + + // // Reset management. // A Token has a "reset level", a number that is incremented whenever a token @@ -154,8 +175,8 @@ void Token::resetAcls() // Make a copy to avoid deadlock with TokenDbCommon lock tmpCommons = mCommons; } - for (CommonSet::const_iterator it = tmpCommons.begin(); it != tmpCommons.end(); it++) - RefPointer(*it)->resetAcls(); + for (CommonSet::const_iterator it = tmpCommons.begin(); it != tmpCommons.end();) + RefPointer(*it++)->resetAcls(); } void Token::addCommon(TokenDbCommon &dbc) @@ -205,12 +226,12 @@ void Token::insert(::Reader &slot) // locate or establish cache directories if (tokend->hasTokenUid()) { - secdebug("token", "%p CHOOSING %s (score=%ld, uid=\"%s\")", + secdebug("token", "%p CHOOSING %s (score=%d, uid=\"%s\")", this, tokend->bundlePath().c_str(), tokend->score(), tokend->tokenUid().c_str()); mCache = new TokenCache::Token(reader().cache, tokend->bundleIdentifier() + ":" + tokend->tokenUid()); } else { - secdebug("token", "%p CHOOSING %s (score=%ld, temporary)", + secdebug("token", "%p CHOOSING %s (score=%d, temporary)", this, tokend->bundlePath().c_str(), tokend->score()); mCache = new TokenCache::Token(reader().cache); } @@ -237,7 +258,7 @@ void Token::insert(::Reader &slot) mPrintName = printName; if (mPrintName.empty()) { // last resort - new card and tokend didn't give us one - snprintf(printName, sizeof(printName), "smart card #%ld", mSubservice); + snprintf(printName, sizeof(printName), "smart card #%d", mSubservice); mPrintName = printName; } if (mCache->type() != TokenCache::Token::existing) @@ -276,7 +297,7 @@ void Token::insert(::Reader &slot) slot.name().c_str(), mPrintName.c_str(), mTokend->hasTokenUid() ? mTokend->tokenUid().c_str() : "NO UID", mSubservice, mTokend->bundleIdentifier().c_str()); - secdebug("token", "%p inserted as %s:%ld", this, mGuid.toString().c_str(), mSubservice); + secdebug("token", "%p inserted as %s:%d", this, mGuid.toString().c_str(), mSubservice); } catch (const CommonError &err) { Syslog::notice("token in reader %s cannot be used (error %ld)", slot.name().c_str(), err.osStatus()); secdebug("token", "exception during insertion processing"); @@ -345,7 +366,7 @@ void Token::fault(bool async) notify(kNotificationCDSAFailure); // cast off our TokenDaemon for good - mTokend = NULL; +//>>> mTokend = NULL; } // if this is a synchronous fault, abort this operation now @@ -420,12 +441,12 @@ void Token::notify(NotificationEvent event) RefPointer Token::chooseTokend() { //@@@ CodeRepository should learn to update from disk changes to be re-usable - CodeRepository candidates("Security/tokend", ".tokend", "TOKENDAEMONPATH", false); + CodeRepository candidates("Security/tokend", ".tokend", "TOKENDAEMONPATH", false); candidates.update(); //@@@ we could sort by reverse "maxScore" and avoid launching those who won't cut it anyway... RefPointer leader; - for (CodeRepository::const_iterator it = candidates.begin(); + for (CodeRepository::const_iterator it = candidates.begin(); it != candidates.end(); it++) { try { // any pre-launch screening of candidate *it goes here @@ -473,7 +494,7 @@ Token::Access::~Access() void Token::dumpNode() { PerGlobal::dumpNode(); - Debug::dump(" %s[%ld] tokend=%p", + Debug::dump(" %s[%d] tokend=%p", mGuid.toString().c_str(), mSubservice, mTokend.get()); } diff --git a/src/token.h b/src/token.h index 06a118d..3acd721 100644 --- a/src/token.h +++ b/src/token.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2007 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -71,6 +71,7 @@ public: static RefPointer find(uint32 ssid); + void getAcl(const char *tag, uint32 &count, AclEntryInfo *&acls); ResetGeneration resetGeneration() const; bool resetGeneration(ResetGeneration rg) const { return rg == resetGeneration(); } void resetAcls(); diff --git a/src/tokenacl.cpp b/src/tokenacl.cpp index e6a1d00..0fe9955 100644 --- a/src/tokenacl.cpp +++ b/src/tokenacl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004-2007 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -110,8 +110,7 @@ void TokenAcl::changeAcl(const AclEdit &edit, const AccessCredentials *cred, Dat if (TokenDatabase *tokenDb = dynamic_cast(db)) if (edit.mode() == CSSM_ACL_EDIT_MODE_REPLACE) if (const AclEntryInput *input = edit.newEntry()) { - unsigned int pin; - if (sscanf(input->proto().s_tag().c_str(), "PIN%d", &pin) == 1) { + if (unsigned pin = pinFromAclTag(input->proto().tag())) { // assume this is a PIN change request pinChange(pin, edit.handle(), *tokenDb); invalidateAcl(); @@ -160,7 +159,7 @@ SecurityAgent::Reason QueryNewPin::accept(CssmManagedData &passphrase, CssmData new(alloc) ListElement(passphrase) )); proto.authorization() = AuthorizationGroup(CSSM_ACL_AUTHORIZATION_PREAUTH(pin), alloc); - char pintag[10]; sprintf(pintag, "PIN%d", pin); + char pintag[20]; sprintf(pintag, "PIN%d", pin); proto.tag(pintag); AclEntryInput input(proto); AclEdit edit(CSSM_ACL_EDIT_MODE_REPLACE, handle, &input); diff --git a/src/tokencache.cpp b/src/tokencache.cpp index c843340..2460db1 100644 --- a/src/tokencache.cpp +++ b/src/tokencache.cpp @@ -68,7 +68,7 @@ static const char cacheDir[] = "cache"; static uint32 getFile(const string &path, uint32 defaultValue) { try { - FileDesc fd(path); + AutoFileDesc fd(path); string s; fd.readAll(s); uint32 value; sscanf(s.c_str(), "%ld", &value); return value; @@ -80,7 +80,7 @@ static uint32 getFile(const string &path, uint32 defaultValue) static string getFile(const string &path, const string &defaultValue) { try { - FileDesc fd(path); + AutoFileDesc fd(path); string s; fd.readAll(s); return s; } catch (...) { @@ -93,12 +93,12 @@ static void putFile(const string &path, uint32 value) { char buffer[64]; snprintf(buffer, sizeof(buffer), "%ld\n", value); - FileDesc(path, O_WRONLY | O_CREAT | O_TRUNC).writeAll(buffer); + AutoFileDesc(path, O_WRONLY | O_CREAT | O_TRUNC).writeAll(buffer); } static void putFile(const string &path, const string &value) { - FileDesc(path, O_WRONLY | O_CREAT | O_TRUNC).writeAll(value); + AutoFileDesc(path, O_WRONLY | O_CREAT | O_TRUNC).writeAll(value); } diff --git a/src/tokend.cpp b/src/tokend.cpp index 350752f..2b14dc7 100644 --- a/src/tokend.cpp +++ b/src/tokend.cpp @@ -37,7 +37,7 @@ // it has died (or been unable to start at all). It's then our owner's responsibility // to manage us from there, including deleting us eventually. // -TokenDaemon::TokenDaemon(RefPointer code, +TokenDaemon::TokenDaemon(RefPointer code, const string &reader, const PCSC::ReaderState &readerState, TokenCache &cache) : Tokend::ClientSession(Allocator::standard(), Allocator::standard()), mMe(code), mReaderName(reader), mState(readerState), @@ -171,7 +171,7 @@ bool TokenDaemon::probe() { secdebug("tokend", "%p probing", this); ClientSession::probe(mScore, mTokenUid); - secdebug("tokend", "%p probed score=%ld tokenUid=\"%s\"", this, mScore, mTokenUid.c_str()); + secdebug("tokend", "%p probed score=%d tokenUid=\"%s\"", this, mScore, mTokenUid.c_str()); mProbed = true; return mScore > 0; } diff --git a/src/tokend.h b/src/tokend.h index e4b808a..63d9750 100644 --- a/src/tokend.h +++ b/src/tokend.h @@ -62,12 +62,12 @@ public: // it right there and then. That's good enough for hard error recovery, though you may // try to let it down easier to allow it to save its caches and wind down. Caller's choice. // -// NB: If you ever want to make TokenDaemon BE a GenericBundle, you must switch NodeCore +// NB: If you ever want to make TokenDaemon BE a Bundle, you must switch NodeCore // AND OSXCode to virtually derive RefCount. // class TokenDaemon : public PerGlobal, public ServerChild, public Tokend::ClientSession { public: - TokenDaemon(RefPointer code, + TokenDaemon(RefPointer code, const std::string &reader, const PCSC::ReaderState &state, TokenCache &cache); virtual ~TokenDaemon(); @@ -100,7 +100,7 @@ protected: void fault(); // relay from Tokend::ClientSession private: - RefPointer mMe; // code object for the tokend (it's an Application) + RefPointer mMe; // code object for the tokend (it's an Application) std::string mReaderName; // PCSC name of reader we're working with PCSC::ReaderState mState; // card state at time of creation (not updated after that) diff --git a/src/tokendatabase.cpp b/src/tokendatabase.cpp index 2251d7e..2525623 100644 --- a/src/tokendatabase.cpp +++ b/src/tokendatabase.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2007 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -38,7 +38,7 @@ // Construct a TokenDbCommon // TokenDbCommon::TokenDbCommon(Session &ssn, Token &tk, const char *name) - : DbCommon(ssn), mDbName(name ? name : ""), mResetLevel(0) + : DbCommon(ssn), mDbName(name ? name : ""), mHasAclState(false), mResetLevel(0) { secdebug("tokendb", "creating tokendbcommon %p: with token %p", this, &tk); parent(tk); @@ -55,7 +55,7 @@ Token &TokenDbCommon::token() const return parent(); } -const std::string &TokenDbCommon::dbName() const +std::string TokenDbCommon::dbName() const { return token().printName(); } @@ -69,25 +69,29 @@ Adornable &TokenDbCommon::store() StLock _(*this); // if this is the first one, hook for lifetime - if (mAdornments.empty()) { + if (!mHasAclState) { session().addReference(*this); // hold and slave to SSN lifetime token().addCommon(*this); // register with Token + mHasAclState = true; } // return our (now active) adornments - return mAdornments; + return *this; } void TokenDbCommon::resetAcls() { StLock _(*this); - if (!mAdornments.empty()) { - mAdornments.clearAdornments(); // clear ACL state + if (mHasAclState) { + clearAdornments(); // clear ACL state session().removeReference(*this); // unhook from SSN + mHasAclState = false; } token().removeCommon(*this); // unregister from Token } + +// // Send out a "keychain" notification for this database // void TokenDbCommon::notify(NotificationEvent event) @@ -124,12 +128,12 @@ TokenDatabase::TokenDatabase(uint32 ssid, Process &proc, StLock _(session); if (TokenDbCommon *dbcom = session.findFirst(&TokenDbCommon::subservice, ssid)) { parent(*dbcom); - secdebug("tokendb", "open tokendb %p(%ld) at known common %p", + secdebug("tokendb", "open tokendb %p(%d) at known common %p", this, subservice(), dbcom); } else { // DbCommon not present; make a new one parent(*new TokenDbCommon(proc.session(), *token, name)); - secdebug("tokendb", "open tokendb %p(%ld) with new common %p", + secdebug("tokendb", "open tokendb %p(%d) with new common %p", this, subservice(), &common()); } mOpenCreds = copy(cred, Allocator::standard()); @@ -167,15 +171,103 @@ bool TokenDatabase::transient() const } +// +// Our ObjectAcl resides in the Token object. +// SecurityServerAcl &TokenDatabase::acl() { return token(); } -bool TokenDatabase::isLocked() const + +// +// We post-process the status version of getAcl to account for virtual (per-session) +// PIN lock status. +// +void TokenDatabase::getAcl(const char *tag, uint32 &count, AclEntryInfo *&acls) +{ + AclSource::getAcl(tag, count, acls); + + for (unsigned n = 0; n < count; n++) { + AclEntryPrototype &proto = acls[n]; + if (unsigned pin = pinFromAclTag(proto.tag(), "?")) { // pin state response + secdebug("tokendb", "%p updating PIN%d state response", this, pin); + TypedList &subject = proto.subject(); + // subject == { CSSM_WORID_PIN, pin-number, status [, count ] } # all numbers + if (subject.length() > 2 + && subject[0].is(CSSM_LIST_ELEMENT_WORDID) + && subject[0] == CSSM_WORDID_PIN + && subject[1].is(CSSM_LIST_ELEMENT_WORDID) + && subject[2].is(CSSM_LIST_ELEMENT_WORDID)) { + uint32 pin = subject[1]; + if (!common().attachment((void *)pin).accepted) { + // we are not pre-authorized in this session + secdebug("tokendb", "%p session state forces PIN%d reporting unauthorized", this, pin); + uint32 status = subject[2]; + status &= ~CSSM_ACL_PREAUTH_TRACKING_AUTHORIZED; // clear authorized bit + subject[2] = status; +#if !defined(NDEBUG) + if (subject.length() > 3 && subject[3].is(CSSM_LIST_ELEMENT_WORDID)) + secdebug("tokendb", "%p PIN%d count=%d", this, pin, subject[3].word()); +#endif //NDEBUG + } + } + } + } +} + + +bool TokenDatabase::isLocked() { Access access(token()); - return access().isLocked(); + + bool lockState = pinState(1); +// bool lockState = access().isLocked(); + + secdebug("tokendb", "returning isLocked=%d", lockState); + return lockState; +} + +bool TokenDatabase::pinState(uint32 pin, int *pinCount /* = NULL */) +{ + uint32 count; + AclEntryInfo *acls; + this->getAcl("PIN1?", count, acls); + bool locked = true; // preset locked + if (pinCount) + *pinCount = -1; // preset unknown + switch (count) { + case 0: + secdebug("tokendb", "PIN%d query returned no entries", pin); + break; + default: + secdebug("tokendb", "PIN%d query returned multiple entries", pin); + break; + case 1: + { + TypedList &subject = acls[0].proto().subject(); + if (subject.length() > 2 + && subject[0].is(CSSM_LIST_ELEMENT_WORDID) + && subject[0] == CSSM_WORDID_PIN + && subject[1].is(CSSM_LIST_ELEMENT_WORDID) + && subject[2].is(CSSM_LIST_ELEMENT_WORDID)) { + uint32 status = subject[2]; + locked = !(status & CSSM_ACL_PREAUTH_TRACKING_AUTHORIZED); + if (pinCount && locked && subject.length() > 3 && subject[3].is(CSSM_LIST_ELEMENT_WORDID)) + *pinCount = subject[3]; + } + } + break; + } + + // release memory allocated by getAcl + ChunkFreeWalker free; + for (uint32 n = 0; n < count; n++) + walk(free, acls[n]); + Allocator::standard().free(acls); + + // return status + return locked; } @@ -197,13 +289,13 @@ void TokenDatabase::dbName(const char *name) // local transient store. // RefPointer TokenDatabase::makeKey(KeyHandle hKey, const CssmKey *key, - const AclEntryPrototype *owner) + uint32 moreAttributes, const AclEntryPrototype *owner) { switch (key->blobType()) { case CSSM_KEYBLOB_REFERENCE: return new TokenKey(*this, hKey, key->header()); case CSSM_KEYBLOB_RAW: - return process().makeTemporaryKey(*key, 0, owner); + return process().makeTemporaryKey(*key, moreAttributes, owner); default: CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); // bad key return from tokend } @@ -359,7 +451,7 @@ void TokenDatabase::generateKey(const Context &context, KeyHandle hKey; CssmKey *result; access().generateKey(context, cred, owner, usage, modattrs(attrs), hKey, result); - newKey = makeKey(hKey, result, owner); + newKey = makeKey(hKey, result, 0, owner); DONE } @@ -377,8 +469,8 @@ void TokenDatabase::generateKey(const Context &context, access().generateKey(context, cred, owner, pubUsage, modattrs(pubAttrs), privUsage, modattrs(privAttrs), hPublic, pubKey, hPrivate, privKey); - publicKey = makeKey(hPublic, pubKey, owner); - privateKey = makeKey(hPrivate, privKey, owner); + publicKey = makeKey(hPublic, pubKey, 0, owner); + privateKey = makeKey(hPrivate, privKey, 0, owner); DONE } @@ -429,7 +521,7 @@ void TokenDatabase::unwrapKey(const Context &context, access().unwrapKey(context, cred, owner, cWrappingKey, cWrappingKey, cPublicKey, cPublicKey, wrappedKey, usage, modattrs(attrs), descriptiveData, hKey, result); - unwrappedKey = makeKey(hKey, result, owner); + unwrappedKey = makeKey(hKey, result, modattrs(attrs) & LocalKey::managedAttributes, owner); DONE } @@ -458,7 +550,7 @@ void TokenDatabase::deriveKey(const Context &context, Key *sourceKey, *param = params; //@@@ leak? what's the rule here? } - derivedKey = makeKey(hKey, result, owner); + derivedKey = makeKey(hKey, result, 0, owner); DONE } @@ -488,9 +580,7 @@ void TokenDatabase::authenticate(CSSM_DB_ACCESS_TYPE mode, const AccessCredentia GUARD if (mode != CSSM_DB_ACCESS_RESET && cred) { secdebug("tokendb", "%p authenticate calling validate", this); - int pin; - if (sscanf(cred->EntryTag, "PIN%d", &pin) == 1) - { + if (unsigned pin = pinFromAclTag(cred->EntryTag)) { validate(CSSM_ACL_AUTHORIZATION_PREAUTH(pin), cred); notify(kNotificationEventUnlocked); return; @@ -505,15 +595,15 @@ void TokenDatabase::authenticate(CSSM_DB_ACCESS_TYPE mode, const AccessCredentia notify(kNotificationEventLocked); break; default: - { - // no idea what that did to the token; - // But let's remember the new creds for our own sake. - AccessCredentials *newCred = copy(cred, Allocator::standard()); - Allocator::standard().free(mOpenCreds); - mOpenCreds = newCred; + { + // no idea what that did to the token; + // But let's remember the new creds for our own sake. + AccessCredentials *newCred = copy(cred, Allocator::standard()); + Allocator::standard().free(mOpenCreds); + mOpenCreds = newCred; + } break; } - } DONE } diff --git a/src/tokendatabase.h b/src/tokendatabase.h index 437158d..cf39062 100644 --- a/src/tokendatabase.h +++ b/src/tokendatabase.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2007 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -60,20 +60,20 @@ public: Token &token() const; uint32 subservice() const { return token().subservice(); } - const std::string &dbName() const; - + std::string dbName() const; + Adornable &store(); void resetAcls(); - - void notify(NotificationEvent event); + void notify(NotificationEvent event); + void lockProcessing(); typedef Token::ResetGeneration ResetGeneration; private: std::string mDbName; // name given during open - Adornable mAdornments; // Adornable for ACL store + bool mHasAclState; // Adornment is carrying active ACL state ResetGeneration mResetLevel; // validity tag }; @@ -97,10 +97,12 @@ public: bool transient() const; SecurityServerAcl &acl(); // it's our Token + void getAcl(const char *tag, uint32 &count, AclEntryInfo *&acls); // post-processing - bool isLocked() const; + bool isLocked(); + bool pinState(uint32 pin, int *count = NULL); - void notify(NotificationEvent event) { return common().notify(event); } + void notify(NotificationEvent event) { return common().notify(event); } bool validateSecret(const AclSubject *subject, const AccessCredentials *cred); @@ -215,7 +217,7 @@ public: private: // internal utilities RefPointer makeKey(KeyHandle hKey, const CssmKey *key, - const AclEntryPrototype *owner); + uint32 moreAttributes, const AclEntryPrototype *owner); class InputKey { public: diff --git a/src/transition.cpp b/src/transition.cpp index c83169b..b18fa2b 100644 --- a/src/transition.cpp +++ b/src/transition.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2007 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -25,6 +25,11 @@ // // transition - securityd IPC-to-class-methods transition layer // +// This file contains all server-side MIG implementations for the main +// securityd protocol ("ucsp"). It dispatches them into the vast object +// conspiracy that is securityd, anchored in the Server object. +// +#include #include #include "server.h" #include "session.h" @@ -32,25 +37,25 @@ #include "kcdatabase.h" #include "tokendatabase.h" #include "kckey.h" -#include "transwalkers.h" #include "child.h" #include +#include +#include +#include #include #include - // // Bracket Macros // -#define UCSP_ARGS mach_port_t servicePort, mach_port_t replyPort, audit_token_t auditToken, \ - CSSM_RETURN *rcode -#define CONTEXT_ARGS Context context, Pointer contextBase, Context::Attr *attributes, mach_msg_type_number_t attrSize +#define UCSP_ARGS mach_port_t servicePort, mach_port_t replyPort, \ + audit_token_t auditToken, CSSM_RETURN *rcode #define BEGIN_IPCN *rcode = CSSM_OK; try { #define BEGIN_IPC BEGIN_IPCN RefPointer connRef(&Server::connection(replyPort)); \ -Connection &connection __attribute__((unused)) = *connRef; -#define END_IPC(base) END_IPCN(base) Server::requestComplete(); return KERN_SUCCESS; + Connection &connection __attribute__((unused)) = *connRef; +#define END_IPC(base) END_IPCN(base) Server::requestComplete(*rcode); return KERN_SUCCESS; #define END_IPCN(base) } \ catch (const CommonError &err) { *rcode = CssmError::cssmError(err, CSSM_ ## base ## _BASE_ERROR); } \ catch (const std::bad_alloc &) { *rcode = CssmError::merge(CSSM_ERRCODE_MEMORY_ERROR, CSSM_ ## base ## _BASE_ERROR); } \ @@ -64,18 +69,144 @@ Connection &connection __attribute__((unused)) = *connRef; #define DATA_IN(base) void *base, mach_msg_type_number_t base##Length #define DATA_OUT(base) void **base, mach_msg_type_number_t *base##Length #define DATA(base) CssmData(base, base##Length) -#define OPTDATA(base) (base ? &CssmData(base, base##Length) : NULL) #define SSBLOB(Type, name) makeBlob(DATA(name)) -#define COPY_IN(type,name) type *name, mach_msg_type_number_t name##Length, type *name##Base -#define COPY_OUT(type,name) \ - type **name, mach_msg_type_number_t *name##Length, type **name##Base - - using LowLevelMemoryUtilities::increment; using LowLevelMemoryUtilities::difference; +class CopyOutAccessCredentials : public CopyOut { +public: + CopyOutAccessCredentials(void *copy, size_t size) : CopyOut(copy, size + sizeof(CSSM_ACCESS_CREDENTIALS), reinterpret_cast(xdr_CSSM_ACCESS_CREDENTIALS_PTR)) { } + operator AccessCredentials *() { return static_cast(reinterpret_cast(data())); } +}; + + +class CopyOutEntryAcl : public CopyOut { +public: + CopyOutEntryAcl(void *copy, size_t size) : CopyOut(copy, size + sizeof(CSSM_ACL_ENTRY_PROTOTYPE), reinterpret_cast(xdr_CSSM_ACL_ENTRY_PROTOTYPE_PTR)) { } + operator AclEntryPrototype *() { return static_cast(reinterpret_cast(data())); } +}; + +class CopyOutOwnerAcl : public CopyOut { +public: + CopyOutOwnerAcl(void *copy, size_t size) : CopyOut(copy, size + sizeof(CSSM_ACL_OWNER_PROTOTYPE), reinterpret_cast(xdr_CSSM_ACL_OWNER_PROTOTYPE_PTR)) { } + operator AclOwnerPrototype *() { return static_cast(reinterpret_cast(data())); } +}; + +class CopyOutAclEntryInput : public CopyOut { +public: + CopyOutAclEntryInput(void *copy, size_t size) : CopyOut(copy, size + sizeof(CSSM_ACL_ENTRY_INPUT), reinterpret_cast(xdr_CSSM_ACL_ENTRY_INPUT_PTR)) { } + operator AclEntryInput *() { return static_cast(reinterpret_cast(data())); } +}; + + +class CopyOutDeriveData : public CopyOut { +public: + CopyOutDeriveData(void *copy, size_t size) : CopyOut(copy, size + sizeof(CSSM_DERIVE_DATA), reinterpret_cast(xdr_CSSM_DERIVE_DATA_PTR)) { } + CSSM_DERIVE_DATA * derive_data() { return reinterpret_cast(data()); } + CSSM_DATA &cssm_data() { return derive_data()->baseData; } + CSSM_ALGORITHMS algorithm() { return derive_data()->algorithm; } +}; + + +class CopyOutContext : public CopyOut { +public: + CopyOutContext(void *copy, size_t size) : CopyOut(copy, size + sizeof(CSSM_CONTEXT), reinterpret_cast(xdr_CSSM_CONTEXT_PTR)) { } + operator Context *() { return static_cast(reinterpret_cast(data())); } + Context &context() { return *static_cast(reinterpret_cast(data())); } +}; + +class CopyOutKey : public CopyOut { +public: + CopyOutKey(void *copy, size_t size) : CopyOut(copy, size + sizeof(CSSM_KEY), reinterpret_cast(xdr_CSSM_KEY_PTR)) { } + operator CssmKey *() { return static_cast(reinterpret_cast(data())); } + CssmKey &key() { return *static_cast(reinterpret_cast(data())); } +}; + +class CopyOutDbRecordAttributes : public CopyOut { +public: + CopyOutDbRecordAttributes(void *copy, size_t size) : CopyOut(copy, size + sizeof(CSSM_DB_RECORD_ATTRIBUTE_DATA), reinterpret_cast(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR)) { } + CssmDbRecordAttributeData *attribute_data() { return static_cast(reinterpret_cast(data())); } +}; + +class CopyOutQuery : public CopyOut { +public: + CopyOutQuery(void *copy, size_t size) : CopyOut(copy, size, reinterpret_cast(xdr_CSSM_QUERY_PTR)) { } + operator CssmQuery *() { return static_cast(reinterpret_cast(data())); } +}; + +// +// Take a DATA type RPC argument purportedly representing a Blob of some kind, +// turn it into a Blob, and fail properly if it's not kosher. +// +template +const BlobType *makeBlob(const CssmData &blobData, CSSM_RETURN error = CSSM_ERRCODE_INVALID_DATA) +{ + if (!blobData.data() || blobData.length() < sizeof(BlobType)) + CssmError::throwMe(error); + const BlobType *blob = static_cast(blobData.data()); + if (blob->totalLength != blobData.length()) + CssmError::throwMe(error); + return blob; +} + +// +// An OutputData object will take memory allocated within securityd, +// hand it to the MIG return-output parameters, and schedule it to be released +// after the MIG reply has been sent. It will also get rid of it in case of +// error. +// +class OutputData : public CssmData { +public: + OutputData(void **outP, mach_msg_type_number_t *outLength) + : mData(*outP), mLength(*outLength) { } + ~OutputData() + { mData = data(); mLength = length(); Server::releaseWhenDone(mData); } + + void operator = (const CssmData &source) + { CssmData::operator = (source); } + +private: + void * &mData; + mach_msg_type_number_t &mLength; +}; + +// +// Choose a Database from a choice of two sources, giving preference +// to persistent stores and to earlier sources. +// +Database *pickDb(Database *db1, Database *db2); + +static inline Database *dbOf(Key *key) { return key ? &key->database() : NULL; } + +inline Database *pickDb(Key *k1, Key *k2) { return pickDb(dbOf(k1), dbOf(k2)); } +inline Database *pickDb(Database *db1, Key *k2) { return pickDb(db1, dbOf(k2)); } +inline Database *pickDb(Key *k1, Database *db2) { return pickDb(dbOf(k1), db2); } + +// +// Choose a Database from a choice of two sources, giving preference +// to persistent stores and to earlier sources. +// +Database *pickDb(Database *db1, Database *db2) +{ + // persistent db1 always wins + if (db1 && !db1->transient()) + return db1; + + // persistent db2 is next choice + if (db2 && !db2->transient()) + return db2; + + // pick any existing transient database + if (db1) + return db1; + if (db2) + return db2; + + // none at all. use the canonical transient store + return Server::optionalDatabase(noDb); +} // // Setup/Teardown functions. @@ -133,18 +264,18 @@ kern_return_t ucsp_server_teardown(UCSP_ARGS) // // Common database operations // -kern_return_t ucsp_server_authenticateDb(UCSP_ARGS, DbHandle db, - CSSM_DB_ACCESS_TYPE accessType, COPY_IN(AccessCredentials, cred)) +kern_return_t ucsp_server_authenticateDb(UCSP_ARGS, IPCDbHandle db, + CSSM_DB_ACCESS_TYPE accessType, DATA_IN(cred)) { BEGIN_IPC secdebug("dl", "authenticateDb"); - relocate(cred, credBase, credLength); + CopyOutAccessCredentials creds(cred, credLength); // ignoring accessType - Server::database(db)->authenticate(accessType, cred); + Server::database(db)->authenticate(accessType, creds); END_IPC(DL) } -kern_return_t ucsp_server_releaseDb(UCSP_ARGS, DbHandle db) +kern_return_t ucsp_server_releaseDb(UCSP_ARGS, IPCDbHandle db) { BEGIN_IPC connection.process().kill(*Server::database(db)); @@ -152,7 +283,7 @@ kern_return_t ucsp_server_releaseDb(UCSP_ARGS, DbHandle db) } -kern_return_t ucsp_server_getDbName(UCSP_ARGS, DbHandle db, char name[PATH_MAX]) +kern_return_t ucsp_server_getDbName(UCSP_ARGS, IPCDbHandle db, char name[PATH_MAX]) { BEGIN_IPC string result = Server::database(db)->dbName(); @@ -161,7 +292,7 @@ kern_return_t ucsp_server_getDbName(UCSP_ARGS, DbHandle db, char name[PATH_MAX]) END_IPC(DL) } -kern_return_t ucsp_server_setDbName(UCSP_ARGS, DbHandle db, const char *name) +kern_return_t ucsp_server_setDbName(UCSP_ARGS, IPCDbHandle db, const char *name) { BEGIN_IPC Server::database(db)->dbName(name); @@ -173,31 +304,30 @@ kern_return_t ucsp_server_setDbName(UCSP_ARGS, DbHandle db, const char *name) // External database interface // kern_return_t ucsp_server_openToken(UCSP_ARGS, uint32 ssid, FilePath name, - COPY_IN(AccessCredentials, accessCredentials), DbHandle *db) + DATA_IN(accessCredentials), IPCDbHandle *db) { BEGIN_IPC - relocate(accessCredentials, accessCredentialsBase, accessCredentialsLength); - *db = (new TokenDatabase(ssid, connection.process(), name, accessCredentials))->handle(); + CopyOutAccessCredentials creds(accessCredentials, accessCredentialsLength); + *db = (new TokenDatabase(ssid, connection.process(), name, creds))->handle(); END_IPC(DL) } -kern_return_t ucsp_server_findFirst(UCSP_ARGS, DbHandle db, - COPY_IN(CssmQuery, query), - COPY_IN(CssmDbRecordAttributeData, inAttributes), - COPY_OUT(CssmDbRecordAttributeData, outAttributes), - boolean_t getData, - DATA_OUT(data), KeyHandle *hKey, SearchHandle *hSearch, RecordHandle *hRecord) +kern_return_t ucsp_server_findFirst(UCSP_ARGS, IPCDbHandle db, + DATA_IN(inQuery), DATA_IN(inAttributes), DATA_OUT(outAttributes), + boolean_t getData, DATA_OUT(data), + IPCKeyHandle *hKey, IPCSearchHandle *hSearch, IPCRecordHandle *hRecord) { BEGIN_IPC - relocate (query, queryBase, queryLength); - relocate (inAttributes, inAttributesBase, inAttributesLength); + CopyOutQuery query(inQuery, inQueryLength); + CopyOutDbRecordAttributes attrs(inAttributes, inAttributesLength); RefPointer search; RefPointer record; RefPointer key; - CssmData outData; //OutputData outData(data, dataLength); - CssmDbRecordAttributeData *outAttrs; mach_msg_type_number_t outAttrsLength; - Server::database(db)->findFirst(*query, inAttributes, inAttributesLength, + CssmData outData; + CssmDbRecordAttributeData *outAttrs = NULL; mach_msg_type_number_t outAttrsLength; + Server::database(db)->findFirst(*query, + attrs.attribute_data(), attrs.length(), getData ? &outData : NULL, key, search, record, outAttrs, outAttrsLength); // handle nothing-found case without exceptions @@ -211,39 +341,43 @@ kern_return_t ucsp_server_findFirst(UCSP_ARGS, DbHandle db, *hSearch = search->handle(); *hKey = key ? key->handle() : noKey; - // return attributes (assumes relocated flat blob) - flips(outAttrs, outAttributes, outAttributesBase); - // flipCssmDbAttributeData(outAttrs, outAttributes, outAttributesBase); - *outAttributesLength = outAttrsLength; - + if (outAttrsLength && outAttrs) { + Server::releaseWhenDone(outAttrs); // exception proof it against next line + if (!copyin(outAttrs, reinterpret_cast (xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA), outAttributes, outAttributesLength)) + CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR); + Server::releaseWhenDone(*outAttributes); + } + // return data (temporary fix) if (getData) { - if (key) { - flip (*outData.interpretedAs()); - } - - *data = outData.data(); - *dataLength = outData.length(); + Server::releaseWhenDone(outData.data()); + xdrproc_t encode_proc = reinterpret_cast(xdr_CSSM_NO_KEY_IN_DATA); + if (key) + encode_proc = reinterpret_cast(xdr_CSSM_KEY_IN_DATA); + if (!copyin(&outData, encode_proc, data, dataLength)) + CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR); + Server::releaseWhenDone(*data); } } END_IPC(DL) } -kern_return_t ucsp_server_findNext(UCSP_ARGS, SearchHandle hSearch, - COPY_IN(CssmDbRecordAttributeData, inAttributes), - COPY_OUT(CssmDbRecordAttributeData, outAttributes), - boolean_t getData, DATA_OUT(data), KeyHandle *hKey, - RecordHandle *hRecord) + +kern_return_t ucsp_server_findNext(UCSP_ARGS, IPCSearchHandle hSearch, + DATA_IN(inAttributes), + DATA_OUT(outAttributes), + boolean_t getData, DATA_OUT(data), IPCKeyHandle *hKey, + IPCRecordHandle *hRecord) { BEGIN_IPC - relocate(inAttributes, inAttributesBase, inAttributesLength); + CopyOutDbRecordAttributes attrs(inAttributes, inAttributesLength); RefPointer search = Server::find(hSearch, CSSMERR_DL_INVALID_RESULTS_HANDLE); RefPointer record; RefPointer key; - CssmData outData; //OutputData outData(data, dataLength); - CssmDbRecordAttributeData *outAttrs; mach_msg_type_number_t outAttrsLength; - search->database().findNext(search, inAttributes, inAttributesLength, + CssmData outData; + CssmDbRecordAttributeData *outAttrs = NULL; mach_msg_type_number_t outAttrsLength; + search->database().findNext(search, attrs.attribute_data(), attrs.length(), getData ? &outData : NULL, key, record, outAttrs, outAttrsLength); // handle nothing-found case without exceptions @@ -255,84 +389,95 @@ kern_return_t ucsp_server_findNext(UCSP_ARGS, SearchHandle hSearch, *hRecord = record->handle(); *hKey = key ? key->handle() : noKey; - // return attributes (assumes relocated flat blob) - flips(outAttrs, outAttributes, outAttributesBase); - *outAttributesLength = outAttrsLength; - + if (outAttrsLength && outAttrs) { + secdebug("attrmem", "Found attrs: %p of length: %d", outAttrs, outAttrsLength); + Server::releaseWhenDone(outAttrs); // exception proof it against next line + if (!copyin(outAttrs, reinterpret_cast (xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA), outAttributes, outAttributesLength)) + CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR); + secdebug("attrmem", "Copied attrs: %p of length: %d", *outAttributes, *outAttributesLength); + Server::releaseWhenDone(*outAttributes); + } + // return data (temporary fix) if (getData) { - if (key) { - flip (*outData.interpretedAs()); - } - - *data = outData.data(); - *dataLength = outData.length(); + Server::releaseWhenDone(outData.data()); + xdrproc_t encode_proc = reinterpret_cast(xdr_CSSM_NO_KEY_IN_DATA); + if (key) + encode_proc = reinterpret_cast(xdr_CSSM_KEY_IN_DATA); + if (!copyin(&outData, encode_proc, data, dataLength)) + CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR); + Server::releaseWhenDone(*data); } } END_IPC(DL) } -kern_return_t ucsp_server_findRecordHandle(UCSP_ARGS, RecordHandle hRecord, - COPY_IN(CssmDbRecordAttributeData, inAttributes), - COPY_OUT(CssmDbRecordAttributeData, outAttributes), - boolean_t getData, DATA_OUT(data), KeyHandle *hKey) +kern_return_t ucsp_server_findRecordHandle(UCSP_ARGS, IPCRecordHandle hRecord, + DATA_IN(inAttributes), DATA_OUT(outAttributes), + boolean_t getData, DATA_OUT(data), IPCKeyHandle *hKey) { BEGIN_IPC - relocate(inAttributes, inAttributesBase, inAttributesLength); + CopyOutDbRecordAttributes attrs(inAttributes, inAttributesLength); RefPointer record = Server::find(hRecord, CSSMERR_DL_INVALID_RECORD_UID); RefPointer key; - CssmData outData; //OutputData outData(data, dataLength); + CssmData outData; CssmDbRecordAttributeData *outAttrs; mach_msg_type_number_t outAttrsLength; - record->database().findRecordHandle(record, inAttributes, inAttributesLength, + record->database().findRecordHandle(record, attrs.attribute_data(), attrs.length(), getData ? &outData : NULL, key, outAttrs, outAttrsLength); // return handles *hKey = key ? key->handle() : noKey; - // return attributes (assumes relocated flat blob) - flips(outAttrs, outAttributes, outAttributesBase); - *outAttributesLength = outAttrsLength; - + if (outAttrsLength && outAttrs) { + Server::releaseWhenDone(outAttrs); // exception proof it against next line + if (!copyin(outAttrs, reinterpret_cast (xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA), outAttributes, outAttributesLength)) + CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR); + Server::releaseWhenDone(*outAttributes); + } + // return data (temporary fix) if (getData) { - if (key) { - flip (*outData.interpretedAs()); - } - - *data = outData.data(); - *dataLength = outData.length(); + Server::releaseWhenDone(outData.data()); + xdrproc_t encode_proc = reinterpret_cast(xdr_CSSM_NO_KEY_IN_DATA); + if (key) + encode_proc = reinterpret_cast(xdr_CSSM_KEY_IN_DATA); + if (!copyin(&outData, encode_proc, data, dataLength)) + CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR); + Server::releaseWhenDone(*data); } END_IPC(DL) } -kern_return_t ucsp_server_insertRecord(UCSP_ARGS, DbHandle db, CSSM_DB_RECORDTYPE recordType, - COPY_IN(CssmDbRecordAttributeData, attributes), DATA_IN(data), RecordHandle *record) +kern_return_t ucsp_server_insertRecord(UCSP_ARGS, IPCDbHandle db, CSSM_DB_RECORDTYPE recordType, + DATA_IN(inAttributes), DATA_IN(data), IPCRecordHandle *record) { BEGIN_IPC - relocate(attributes, attributesBase, attributesLength); - Server::database(db)->insertRecord(recordType, attributes, attributesLength, - DATA(data), *record); + RecordHandle recordHandle; + CopyOutDbRecordAttributes attrs(inAttributes, inAttributesLength); + Server::database(db)->insertRecord(recordType, attrs.attribute_data(), attrs.length(), + DATA(data), recordHandle); + *record = recordHandle; END_IPC(DL) } -kern_return_t ucsp_server_modifyRecord(UCSP_ARGS, DbHandle db, RecordHandle *hRecord, - CSSM_DB_RECORDTYPE recordType, COPY_IN(CssmDbRecordAttributeData, attributes), +kern_return_t ucsp_server_modifyRecord(UCSP_ARGS, IPCDbHandle db, IPCRecordHandle *hRecord, + CSSM_DB_RECORDTYPE recordType, DATA_IN(attributes), boolean_t setData, DATA_IN(data), CSSM_DB_MODIFY_MODE modifyMode) { BEGIN_IPC - relocate(attributes, attributesBase, attributesLength); + CopyOutDbRecordAttributes attrs(attributes, attributesLength); CssmData newData(DATA(data)); RefPointer record = Server::find(*hRecord, CSSMERR_DL_INVALID_RECORD_UID); - Server::database(db)->modifyRecord(recordType, record, attributes, attributesLength, + Server::database(db)->modifyRecord(recordType, record, attrs.attribute_data(), attrs.length(), setData ? &newData : NULL, modifyMode); // note that the record handle presented to the client never changes here // (we could, but have no reason to - our record handles are just always up to date) END_IPC(DL) } -kern_return_t ucsp_server_deleteRecord(UCSP_ARGS, DbHandle db, RecordHandle hRecord) +kern_return_t ucsp_server_deleteRecord(UCSP_ARGS, IPCDbHandle db, IPCRecordHandle hRecord) { BEGIN_IPC Server::database(db)->deleteRecord( @@ -340,7 +485,7 @@ kern_return_t ucsp_server_deleteRecord(UCSP_ARGS, DbHandle db, RecordHandle hRec END_IPC(DL) } -kern_return_t ucsp_server_releaseSearch(UCSP_ARGS, SearchHandle hSearch) +kern_return_t ucsp_server_releaseSearch(UCSP_ARGS, IPCSearchHandle hSearch) { BEGIN_IPC RefPointer search = Server::find(hSearch, 0); @@ -348,7 +493,7 @@ kern_return_t ucsp_server_releaseSearch(UCSP_ARGS, SearchHandle hSearch) END_IPC(DL) } -kern_return_t ucsp_server_releaseRecord(UCSP_ARGS, RecordHandle hRecord) +kern_return_t ucsp_server_releaseRecord(UCSP_ARGS, IPCRecordHandle hRecord) { BEGIN_IPC RefPointer record = Server::find(hRecord, 0); @@ -356,33 +501,19 @@ kern_return_t ucsp_server_releaseRecord(UCSP_ARGS, RecordHandle hRecord) END_IPC(DL) } -kern_return_t ucsp_server_getRecordFromHandle(UCSP_ARGS, RecordHandle record, - COPY_IN(CssmDbRecordAttributeData, inAttributes), - COPY_OUT(CssmDbRecordAttributeData, outAttributes), - boolean_t getData, - DATA_OUT(data)) -{ - BEGIN_IPC - secdebug("dl", "getRecordFromHandle"); - relocate(inAttributes, inAttributesBase, inAttributesLength); - // @@@ - END_IPC(DL) -} - // // Internal database management // -kern_return_t ucsp_server_createDb(UCSP_ARGS, DbHandle *db, - COPY_IN(DLDbFlatIdentifier, ident), - COPY_IN(AccessCredentials, cred), COPY_IN(AclEntryPrototype, owner), +kern_return_t ucsp_server_createDb(UCSP_ARGS, IPCDbHandle *db, + DATA_IN(ident), DATA_IN(cred), DATA_IN(owner), DBParameters params) { BEGIN_IPC - relocate(cred, credBase, credLength); - relocate(owner, ownerBase, ownerLength); - relocate(ident, identBase, identLength); - *db = (new KeychainDatabase(*ident, params, connection.process(), cred, owner))->handle(); + CopyOutAccessCredentials creds(cred, credLength); + CopyOutEntryAcl owneracl(owner, ownerLength); + CopyOut flatident(ident, identLength, reinterpret_cast(xdr_DLDbFlatIdentifierRef)); + *db = (new KeychainDatabase(*reinterpret_cast(flatident.data()), params, connection.process(), creds, owneracl))->handle(); END_IPC(DL) } @@ -390,7 +521,7 @@ kern_return_t ucsp_server_createDb(UCSP_ARGS, DbHandle *db, // @@@ caller should be required to call decodeDb() to get a DbHandle // instead of passing the blob itself kern_return_t ucsp_server_cloneDbForSync(UCSP_ARGS, DATA_IN(blob), - DbHandle srcDb, DATA_IN(agentData), DbHandle *newDb) + IPCDbHandle srcDb, DATA_IN(agentData), IPCDbHandle *newDb) { BEGIN_IPC RefPointer srcKC = Server::keychain(srcDb); @@ -399,8 +530,8 @@ kern_return_t ucsp_server_cloneDbForSync(UCSP_ARGS, DATA_IN(blob), END_IPC(DL) } -kern_return_t ucsp_server_commitDbForSync(UCSP_ARGS, DbHandle srcDb, - DbHandle cloneDb, DATA_OUT(blob)) +kern_return_t ucsp_server_commitDbForSync(UCSP_ARGS, IPCDbHandle srcDb, + IPCDbHandle cloneDb, DATA_OUT(blob)) { BEGIN_IPC RefPointer srcKC = Server::keychain(srcDb); @@ -418,18 +549,18 @@ kern_return_t ucsp_server_commitDbForSync(UCSP_ARGS, DbHandle srcDb, END_IPC(DL) } -kern_return_t ucsp_server_decodeDb(UCSP_ARGS, DbHandle *db, - COPY_IN(DLDbFlatIdentifier, ident), COPY_IN(AccessCredentials, cred), DATA_IN(blob)) +kern_return_t ucsp_server_decodeDb(UCSP_ARGS, IPCDbHandle *db, + DATA_IN(ident), DATA_IN(cred), DATA_IN(blob)) { BEGIN_IPC - relocate(cred, credBase, credLength); - relocate(ident, identBase, identLength); - *db = (new KeychainDatabase(*ident, SSBLOB(DbBlob, blob), - connection.process(), cred))->handle(); + CopyOutAccessCredentials creds(cred, credLength); + CopyOut flatident(ident, identLength, reinterpret_cast(xdr_DLDbFlatIdentifierRef)); + *db = (new KeychainDatabase(*reinterpret_cast(flatident.data()), SSBLOB(DbBlob, blob), + connection.process(), creds))->handle(); END_IPC(DL) } -kern_return_t ucsp_server_encodeDb(UCSP_ARGS, DbHandle db, DATA_OUT(blob)) +kern_return_t ucsp_server_encodeDb(UCSP_ARGS, IPCDbHandle db, DATA_OUT(blob)) { BEGIN_IPC DbBlob *dbBlob = Server::keychain(db)->blob(); // memory owned by database @@ -438,26 +569,26 @@ kern_return_t ucsp_server_encodeDb(UCSP_ARGS, DbHandle db, DATA_OUT(blob)) END_IPC(DL) } -kern_return_t ucsp_server_setDbParameters(UCSP_ARGS, DbHandle db, DBParameters params) +kern_return_t ucsp_server_setDbParameters(UCSP_ARGS, IPCDbHandle db, DBParameters params) { BEGIN_IPC Server::keychain(db)->setParameters(params); END_IPC(DL) } -kern_return_t ucsp_server_getDbParameters(UCSP_ARGS, DbHandle db, DBParameters *params) +kern_return_t ucsp_server_getDbParameters(UCSP_ARGS, IPCDbHandle db, DBParameters *params) { BEGIN_IPC Server::keychain(db)->getParameters(*params); END_IPC(DL) } -kern_return_t ucsp_server_changePassphrase(UCSP_ARGS, DbHandle db, - COPY_IN(AccessCredentials, cred)) +kern_return_t ucsp_server_changePassphrase(UCSP_ARGS, IPCDbHandle db, + DATA_IN(cred)) { BEGIN_IPC - relocate(cred, credBase, credLength); - Server::keychain(db)->changePassphrase(cred); + CopyOutAccessCredentials creds(cred, credLength); + Server::keychain(db)->changePassphrase(creds); END_IPC(DL) } @@ -468,21 +599,21 @@ kern_return_t ucsp_server_lockAll (UCSP_ARGS, boolean_t) END_IPC(DL) } -kern_return_t ucsp_server_unlockDb(UCSP_ARGS, DbHandle db) +kern_return_t ucsp_server_unlockDb(UCSP_ARGS, IPCDbHandle db) { BEGIN_IPC Server::keychain(db)->unlockDb(); END_IPC(DL) } -kern_return_t ucsp_server_unlockDbWithPassphrase(UCSP_ARGS, DbHandle db, DATA_IN(passphrase)) +kern_return_t ucsp_server_unlockDbWithPassphrase(UCSP_ARGS, IPCDbHandle db, DATA_IN(passphrase)) { BEGIN_IPC Server::keychain(db)->unlockDb(DATA(passphrase)); END_IPC(DL) } -kern_return_t ucsp_server_isLocked(UCSP_ARGS, DbHandle db, boolean_t *locked) +kern_return_t ucsp_server_isLocked(UCSP_ARGS, IPCDbHandle db, boolean_t *locked) { BEGIN_IPC *locked = Server::database(db)->isLocked(); @@ -493,7 +624,7 @@ kern_return_t ucsp_server_isLocked(UCSP_ARGS, DbHandle db, boolean_t *locked) // // Key management // -kern_return_t ucsp_server_encodeKey(UCSP_ARGS, KeyHandle keyh, DATA_OUT(blob), +kern_return_t ucsp_server_encodeKey(UCSP_ARGS, IPCKeyHandle keyh, DATA_OUT(blob), boolean_t wantUid, DATA_OUT(uid)) { BEGIN_IPC @@ -513,19 +644,24 @@ kern_return_t ucsp_server_encodeKey(UCSP_ARGS, KeyHandle keyh, DATA_OUT(blob), END_IPC(CSP) } -kern_return_t ucsp_server_decodeKey(UCSP_ARGS, KeyHandle *keyh, CssmKey::Header *header, - DbHandle db, DATA_IN(blob)) +kern_return_t ucsp_server_decodeKey(UCSP_ARGS, IPCKeyHandle *keyh, DATA_OUT(keyHeader), + IPCDbHandle db, DATA_IN(blob)) { BEGIN_IPC RefPointer key = new KeychainKey(*Server::keychain(db), SSBLOB(KeyBlob, blob)); - key->returnKey(*keyh, *header); - flip(*header); + CssmKey::Header header; + KeyHandle keyHandle; + key->returnKey(keyHandle, header); + *keyh = keyHandle; + if (!copyin(&header, reinterpret_cast (xdr_CSSM_KEYHEADER), keyHeader, keyHeaderLength)) + CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR); + Server::releaseWhenDone(*keyHeader); END_IPC(CSP) } // keychain synchronization -kern_return_t ucsp_server_recodeKey(UCSP_ARGS, DbHandle oldDb, KeyHandle keyh, - DbHandle newDb, DATA_OUT(newBlob)) +kern_return_t ucsp_server_recodeKey(UCSP_ARGS, IPCDbHandle oldDb, IPCKeyHandle keyh, + IPCDbHandle newDb, DATA_OUT(newBlob)) { BEGIN_IPC // If the old key is passed in as DATA_IN(oldBlob): @@ -543,7 +679,7 @@ kern_return_t ucsp_server_recodeKey(UCSP_ARGS, DbHandle oldDb, KeyHandle keyh, END_IPC(CSP) } -kern_return_t ucsp_server_releaseKey(UCSP_ARGS, KeyHandle keyh) +kern_return_t ucsp_server_releaseKey(UCSP_ARGS, IPCKeyHandle keyh) { BEGIN_IPC RefPointer key = Server::key(keyh); @@ -551,7 +687,7 @@ kern_return_t ucsp_server_releaseKey(UCSP_ARGS, KeyHandle keyh) END_IPC(CSP) } -kern_return_t ucsp_server_queryKeySizeInBits(UCSP_ARGS, KeyHandle keyh, CSSM_KEY_SIZE *length) +kern_return_t ucsp_server_queryKeySizeInBits(UCSP_ARGS, IPCKeyHandle keyh, CSSM_KEY_SIZE *length) { BEGIN_IPC RefPointer key = Server::key(keyh); @@ -559,17 +695,17 @@ kern_return_t ucsp_server_queryKeySizeInBits(UCSP_ARGS, KeyHandle keyh, CSSM_KEY END_IPC(CSP) } -kern_return_t ucsp_server_getOutputSize(UCSP_ARGS, CONTEXT_ARGS, KeyHandle keyh, +kern_return_t ucsp_server_getOutputSize(UCSP_ARGS, DATA_IN(context), IPCKeyHandle keyh, uint32 inputSize, boolean_t encrypt, uint32 *outputSize) { BEGIN_IPC - relocate(context, contextBase, attributes, attrSize); + CopyOutContext ctx(context, contextLength); RefPointer key = Server::key(keyh); - key->database().getOutputSize(context, *key, inputSize, encrypt, *outputSize); + key->database().getOutputSize(*ctx, *key, inputSize, encrypt, *outputSize); END_IPC(CSP) } -kern_return_t ucsp_server_getKeyDigest(UCSP_ARGS, KeyHandle key, DATA_OUT(digest)) +kern_return_t ucsp_server_getKeyDigest(UCSP_ARGS, IPCKeyHandle key, DATA_OUT(digest)) { BEGIN_IPC CssmData digestData = Server::key(key)->canonicalDigest(); @@ -582,47 +718,47 @@ kern_return_t ucsp_server_getKeyDigest(UCSP_ARGS, KeyHandle key, DATA_OUT(digest // // Signatures and MACs // -kern_return_t ucsp_server_generateSignature(UCSP_ARGS, CONTEXT_ARGS, KeyHandle keyh, +kern_return_t ucsp_server_generateSignature(UCSP_ARGS, DATA_IN(context), IPCKeyHandle keyh, CSSM_ALGORITHMS signOnlyAlgorithm, DATA_IN(data), DATA_OUT(signature)) { BEGIN_IPC - relocate(context, contextBase, attributes, attrSize); + CopyOutContext ctx(context, contextLength); RefPointer key = Server::key(keyh); OutputData sigData(signature, signatureLength); - key->database().generateSignature(context, *key, signOnlyAlgorithm, + key->database().generateSignature(*ctx, *key, signOnlyAlgorithm, DATA(data), sigData); END_IPC(CSP) } -kern_return_t ucsp_server_verifySignature(UCSP_ARGS, CONTEXT_ARGS, KeyHandle keyh, +kern_return_t ucsp_server_verifySignature(UCSP_ARGS, DATA_IN(context), IPCKeyHandle keyh, CSSM_ALGORITHMS verifyOnlyAlgorithm, DATA_IN(data), DATA_IN(signature)) { BEGIN_IPC - relocate(context, contextBase, attributes, attrSize); + CopyOutContext ctx(context, contextLength); RefPointer key = Server::key(keyh); - key->database().verifySignature(context, *key, verifyOnlyAlgorithm, + key->database().verifySignature(*ctx, *key, verifyOnlyAlgorithm, DATA(data), DATA(signature)); END_IPC(CSP) } -kern_return_t ucsp_server_generateMac(UCSP_ARGS, CONTEXT_ARGS, KeyHandle keyh, +kern_return_t ucsp_server_generateMac(UCSP_ARGS, DATA_IN(context), IPCKeyHandle keyh, DATA_IN(data), DATA_OUT(mac)) { BEGIN_IPC - relocate(context, contextBase, attributes, attrSize); + CopyOutContext ctx(context, contextLength); RefPointer key = Server::key(keyh); OutputData macData(mac, macLength); - key->database().generateMac(context, *key, DATA(data), macData); + key->database().generateMac(*ctx, *key, DATA(data), macData); END_IPC(CSP) } -kern_return_t ucsp_server_verifyMac(UCSP_ARGS, CONTEXT_ARGS, KeyHandle keyh, +kern_return_t ucsp_server_verifyMac(UCSP_ARGS, DATA_IN(context), IPCKeyHandle keyh, DATA_IN(data), DATA_IN(mac)) { BEGIN_IPC - relocate(context, contextBase, attributes, attrSize); + CopyOutContext ctx(context, contextLength); RefPointer key = Server::key(keyh); - key->database().verifyMac(context, *key, DATA(data), DATA(mac)); + key->database().verifyMac(*ctx, *key, DATA(data), DATA(mac)); END_IPC(CSP) } @@ -630,25 +766,25 @@ kern_return_t ucsp_server_verifyMac(UCSP_ARGS, CONTEXT_ARGS, KeyHandle keyh, // // Encryption/Decryption // -kern_return_t ucsp_server_encrypt(UCSP_ARGS, CONTEXT_ARGS, KeyHandle keyh, +kern_return_t ucsp_server_encrypt(UCSP_ARGS, DATA_IN(context), IPCKeyHandle keyh, DATA_IN(clear), DATA_OUT(cipher)) { BEGIN_IPC - relocate(context, contextBase, attributes, attrSize); + CopyOutContext ctx(context, contextLength); RefPointer key = Server::key(keyh); OutputData cipherOut(cipher, cipherLength); - key->database().encrypt(context, *key, DATA(clear), cipherOut); + key->database().encrypt(*ctx, *key, DATA(clear), cipherOut); END_IPC(CSP) } -kern_return_t ucsp_server_decrypt(UCSP_ARGS, CONTEXT_ARGS, KeyHandle keyh, +kern_return_t ucsp_server_decrypt(UCSP_ARGS, DATA_IN(context), IPCKeyHandle keyh, DATA_IN(cipher), DATA_OUT(clear)) { BEGIN_IPC - relocate(context, contextBase, attributes, attrSize); + CopyOutContext ctx(context, contextLength); RefPointer key = Server::key(keyh); OutputData clearOut(clear, clearLength); - key->database().decrypt(context, *key, DATA(cipher), clearOut); + key->database().decrypt(*ctx, *key, DATA(cipher), clearOut); END_IPC(CSP) } @@ -656,42 +792,60 @@ kern_return_t ucsp_server_decrypt(UCSP_ARGS, CONTEXT_ARGS, KeyHandle keyh, // // Key generation // -kern_return_t ucsp_server_generateKey(UCSP_ARGS, DbHandle db, CONTEXT_ARGS, - COPY_IN(AccessCredentials, cred), COPY_IN(AclEntryPrototype, owner), - uint32 usage, uint32 attrs, KeyHandle *newKey, CssmKey::Header *newHeader) +kern_return_t ucsp_server_generateKey(UCSP_ARGS, IPCDbHandle db, DATA_IN(context), + DATA_IN(cred), DATA_IN(owner), + uint32 usage, uint32 attrs, IPCKeyHandle *newKey, DATA_OUT(keyHeader)) { BEGIN_IPC - relocate(context, contextBase, attributes, attrSize); - relocate(cred, credBase, credLength); - relocate(owner, ownerBase, ownerLength); + CopyOutContext ctx(context, contextLength); + CopyOutAccessCredentials creds(cred, credLength); + + CopyOutEntryAcl owneracl(owner, ownerLength); //@@@ preliminary interpretation - will get "type handle" RefPointer database = Server::optionalDatabase(db, attrs & CSSM_KEYATTR_PERMANENT); RefPointer key; - database->generateKey(context, cred, owner, usage, attrs, key); - key->returnKey(*newKey, *newHeader); - flip(*newHeader); + database->generateKey(*ctx, creds, owneracl, usage, attrs, key); + CssmKey::Header newHeader; + KeyHandle keyHandle; + key->returnKey(keyHandle, newHeader); + *newKey = keyHandle; + + if (!copyin(&newHeader, reinterpret_cast (xdr_CSSM_KEYHEADER), keyHeader, keyHeaderLength)) + CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR); + Server::releaseWhenDone(*keyHeader); END_IPC(CSP) } -kern_return_t ucsp_server_generateKeyPair(UCSP_ARGS, DbHandle db, CONTEXT_ARGS, - COPY_IN(AccessCredentials, cred), COPY_IN(AclEntryPrototype, owner), +kern_return_t ucsp_server_generateKeyPair(UCSP_ARGS, IPCDbHandle db, DATA_IN(context), + DATA_IN(cred), DATA_IN(owner), uint32 pubUsage, uint32 pubAttrs, uint32 privUsage, uint32 privAttrs, - KeyHandle *pubKey, CssmKey::Header *pubHeader, KeyHandle *privKey, CssmKey::Header *privHeader) + IPCKeyHandle *pubKey, DATA_OUT(pubHeader), IPCKeyHandle *privKey, DATA_OUT(privHeader)) { BEGIN_IPC - relocate(context, contextBase, attributes, attrSize); - relocate(cred, credBase, credLength); - relocate(owner, ownerBase, ownerLength); + CopyOutContext ctx(context, contextLength); + CopyOutAccessCredentials creds(cred, credLength); + CopyOutEntryAcl owneracl(owner, ownerLength); RefPointer database = Server::optionalDatabase(db, (privAttrs | pubAttrs) & CSSM_KEYATTR_PERMANENT); RefPointer pub, priv; - database->generateKey(context, cred, owner, + database->generateKey(*ctx, creds, owneracl, pubUsage, pubAttrs, privUsage, privAttrs, pub, priv); - pub->returnKey(*pubKey, *pubHeader); - flip(*pubHeader); - priv->returnKey(*privKey, *privHeader); - flip(*privHeader); + CssmKey::Header tmpPubHeader, tmpPrivHeader; + KeyHandle pubKeyHandle, privKeyHandle; + + pub->returnKey(pubKeyHandle, tmpPubHeader); + *pubKey = pubKeyHandle; + if (!copyin(&tmpPubHeader, reinterpret_cast (xdr_CSSM_KEYHEADER), pubHeader, pubHeaderLength)) + CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR); + Server::releaseWhenDone(*pubHeader); + + priv->returnKey(privKeyHandle, tmpPrivHeader); + *privKey = privKeyHandle; + if (!copyin(&tmpPrivHeader, reinterpret_cast (xdr_CSSM_KEYHEADER), privHeader, privHeaderLength)) + CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR); + Server::releaseWhenDone(*privHeader); + END_IPC(CSP) } @@ -699,47 +853,55 @@ kern_return_t ucsp_server_generateKeyPair(UCSP_ARGS, DbHandle db, CONTEXT_ARGS, // // Key wrapping and unwrapping // -kern_return_t ucsp_server_wrapKey(UCSP_ARGS, CONTEXT_ARGS, KeyHandle hWrappingKey, - COPY_IN(AccessCredentials, cred), KeyHandle hKeyToBeWrapped, - DATA_IN(descriptiveData), CssmKey *wrappedKey, DATA_OUT(keyData)) +kern_return_t ucsp_server_wrapKey(UCSP_ARGS, DATA_IN(context), IPCKeyHandle hWrappingKey, + DATA_IN(cred), IPCKeyHandle hKeyToBeWrapped, + DATA_IN(descriptiveData), DATA_OUT(wrappedKeyData)) { BEGIN_IPC - relocate(context, contextBase, attributes, attrSize); - relocate(cred, credBase, credLength); + CssmKey wrappedKey; + CopyOutContext ctx(context, contextLength); + CopyOutAccessCredentials creds(cred, credLength); RefPointer subjectKey = Server::key(hKeyToBeWrapped); RefPointer wrappingKey = Server::optionalKey(hWrappingKey); - if ((context.algorithm() == CSSM_ALGID_NONE && subjectKey->attribute(CSSM_KEYATTR_SENSITIVE)) + if ((ctx.context().algorithm() == CSSM_ALGID_NONE && subjectKey->attribute(CSSM_KEYATTR_SENSITIVE)) || !subjectKey->attribute(CSSM_KEYATTR_EXTRACTABLE)) CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK); - pickDb(subjectKey, wrappingKey)->wrapKey(context, cred, wrappingKey, *subjectKey, DATA(descriptiveData), *wrappedKey); + pickDb(subjectKey, wrappingKey)->wrapKey(*ctx, creds, wrappingKey, *subjectKey, DATA(descriptiveData), wrappedKey); + Server::releaseWhenDone(wrappedKey.keyData().data()); - // transmit key data back as a separate blob - OutputData keyDatas(keyData, keyDataLength); - keyDatas = wrappedKey->keyData(); - flip(*wrappedKey); + if (!copyin(&wrappedKey, reinterpret_cast (xdr_CSSM_KEY), wrappedKeyData, wrappedKeyDataLength)) + CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR); + + Server::releaseWhenDone(*wrappedKeyData); END_IPC(CSP) } -kern_return_t ucsp_server_unwrapKey(UCSP_ARGS, DbHandle db, CONTEXT_ARGS, - KeyHandle hWrappingKey, COPY_IN(AccessCredentials, cred), COPY_IN(AclEntryPrototype, owner), - KeyHandle hPublicKey, CssmKey wrappedKey, DATA_IN(wrappedKeyData), +kern_return_t ucsp_server_unwrapKey(UCSP_ARGS, IPCDbHandle db, DATA_IN(context), + IPCKeyHandle hWrappingKey, DATA_IN(cred), DATA_IN(owner), + IPCKeyHandle hPublicKey, DATA_IN(wrappedKeyData), CSSM_KEYUSE usage, CSSM_KEYATTR_FLAGS attrs, DATA_OUT(descriptiveData), - KeyHandle *newKey, CssmKey::Header *newHeader) + IPCKeyHandle *newKey, DATA_OUT(keyHeader)/*CssmKey::Header *newHeader*/) { BEGIN_IPC - relocate(context, contextBase, attributes, attrSize); - flip(wrappedKey); - wrappedKey.keyData() = DATA(wrappedKeyData); - relocate(cred, credBase, credLength); - relocate(owner, ownerBase, ownerLength); + CopyOutContext ctx(context, contextLength); + CopyOutKey wrappedKey(wrappedKeyData, wrappedKeyDataLength); + CopyOutAccessCredentials creds(cred, credLength); + CopyOutEntryAcl owneracl(owner, ownerLength); OutputData descriptiveDatas(descriptiveData, descriptiveDataLength); RefPointer wrappingKey = Server::optionalKey(hWrappingKey); RefPointer unwrappedKey; - pickDb(Server::optionalDatabase(db), wrappingKey)->unwrapKey(context, cred, owner, + pickDb(Server::optionalDatabase(db), wrappingKey)->unwrapKey(*ctx, creds, owneracl, wrappingKey, Server::optionalKey(hPublicKey), - usage, attrs, wrappedKey, unwrappedKey, descriptiveDatas); - unwrappedKey->returnKey(*newKey, *newHeader); - flip(*newHeader); + usage, attrs, wrappedKey.key(), unwrappedKey, descriptiveDatas); + + CssmKey::Header newHeader; + KeyHandle keyHandle; + unwrappedKey->returnKey(keyHandle, newHeader); + *newKey = keyHandle; + if (!copyin(&newHeader, reinterpret_cast (xdr_CSSM_KEYHEADER), keyHeader, keyHeaderLength)) + CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR); + Server::releaseWhenDone(*keyHeader); + END_IPC(CSP) } @@ -751,34 +913,40 @@ kern_return_t ucsp_server_unwrapKey(UCSP_ARGS, DbHandle db, CONTEXT_ARGS, // (artificial) POD CssmDeriveData handles those that are known; if you add // an algorithm with structured param, you need to add a case there. // -kern_return_t ucsp_server_deriveKey(UCSP_ARGS, DbHandle db, CONTEXT_ARGS, KeyHandle hKey, - COPY_IN(AccessCredentials, cred), COPY_IN(AclEntryPrototype, owner), - COPY_IN(CssmDeriveData, paramInput), DATA_OUT(paramOutput), - uint32 usage, uint32 attrs, KeyHandle *newKey, CssmKey::Header *newHeader) +kern_return_t ucsp_server_deriveKey(UCSP_ARGS, IPCDbHandle db, DATA_IN(context), IPCKeyHandle hKey, + DATA_IN(cred), DATA_IN(owner), + DATA_IN(paramInput), DATA_OUT(paramOutput), + uint32 usage, uint32 attrs, IPCKeyHandle *newKey, DATA_OUT(keyHeader)) { BEGIN_IPC - relocate(context, contextBase, attributes, attrSize); - relocate(cred, credBase, credLength); - relocate(owner, ownerBase, ownerLength); - relocate(paramInput, paramInputBase, paramInputLength); - if (!paramInput || paramInput->algorithm != context.algorithm()) + CopyOutContext ctx(context, contextLength); + CopyOutAccessCredentials creds(cred, credLength); + CopyOutEntryAcl owneracl(owner, ownerLength); + CopyOutDeriveData deriveParam(paramInput, paramInputLength); + if (deriveParam.algorithm() != ctx.context().algorithm()) CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR); // client layer fault RefPointer database = Server::optionalDatabase(db, attrs & CSSM_KEYATTR_PERMANENT); RefPointer key = Server::optionalKey(hKey); - CssmData *param = paramInput ? ¶mInput->baseData : NULL; - RefPointer derivedKey; + CSSM_DATA param = deriveParam.cssm_data(); + RefPointer derivedKey; pickDb(Server::optionalDatabase(db, attrs & CSSM_KEYATTR_PERMANENT), - key)->deriveKey(context, key, cred, owner, param, usage, attrs, derivedKey); - derivedKey->returnKey(*newKey, *newHeader); - flip(*newHeader); - if (param && param->length()) { - if (!param->data()) // CSP screwed up + key)->deriveKey(*ctx, key, creds, owneracl, static_cast(¶m), usage, attrs, derivedKey); + + CssmKey::Header newHeader; + KeyHandle keyHandle; + derivedKey->returnKey(keyHandle, newHeader); + *newKey = keyHandle; + + if (!copyin(&newHeader, reinterpret_cast (xdr_CSSM_KEYHEADER), keyHeader, keyHeaderLength)) + CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR); + Server::releaseWhenDone(*keyHeader); + + if (param.Length) { + if (!param.Data) // CSP screwed up CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); - if (paramInputLength) // using incoming buffer; make a copy - *param = CssmAutoData(Server::csp().allocator(), *param).release(); - OutputData(paramOutput, paramOutputLength) = *param; // return the data + OutputData(paramOutput, paramOutputLength) = CssmAutoData(Server::csp().allocator(), param).release(); } END_IPC(CSP) } @@ -787,16 +955,16 @@ kern_return_t ucsp_server_deriveKey(UCSP_ARGS, DbHandle db, CONTEXT_ARGS, KeyHan // // Random generation // -kern_return_t ucsp_server_generateRandom(UCSP_ARGS, uint32 ssid, CONTEXT_ARGS, DATA_OUT(data)) +kern_return_t ucsp_server_generateRandom(UCSP_ARGS, uint32 ssid, DATA_IN(context), DATA_OUT(data)) { BEGIN_IPC - relocate(context, contextBase, attributes, attrSize); + CopyOutContext ctx(context, contextLength); if (ssid) CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); // default version (use /dev/random) Allocator &allocator = Allocator::standard(Allocator::sensitive); - if (size_t bytes = context.getInt(CSSM_ATTRIBUTE_OUTPUT_SIZE)) { + if (size_t bytes = ctx.context().getInt(CSSM_ATTRIBUTE_OUTPUT_SIZE)) { void *buffer = allocator.malloc(bytes); Server::active().random(buffer, bytes); *data = buffer; @@ -811,72 +979,73 @@ kern_return_t ucsp_server_generateRandom(UCSP_ARGS, uint32 ssid, CONTEXT_ARGS, D // ACL management. // Watch out for the memory-management tap-dance. // -kern_return_t ucsp_server_getOwner(UCSP_ARGS, AclKind kind, KeyHandle key, - COPY_OUT(AclOwnerPrototype, ownerOut)) +kern_return_t ucsp_server_getOwner(UCSP_ARGS, AclKind kind, IPCKeyHandle key, + DATA_OUT(ownerOut)) { BEGIN_IPC AclOwnerPrototype owner; Server::aclBearer(kind, key).getOwner(owner); // allocates memory in owner - Copier owners(&owner, Allocator::standard()); // make flat copy + void *owners_data; u_int owners_length; + if (!::copyin(&owner, reinterpret_cast(xdr_CSSM_ACL_OWNER_PROTOTYPE), &owners_data, &owners_length)) + CssmError::throwMe(CSSM_ERRCODE_MEMORY_ERROR); + { ChunkFreeWalker free; walk(free, owner); } // release chunked original - *ownerOutLength = owners.length(); - flips(owners.value(), ownerOut, ownerOutBase); - Server::releaseWhenDone(owners.keep()); // throw flat copy out when done + Server::releaseWhenDone(owners_data); // throw flat copy out when done + *ownerOut = owners_data; + *ownerOutLength = owners_length; END_IPC(CSP) } -kern_return_t ucsp_server_setOwner(UCSP_ARGS, AclKind kind, KeyHandle key, - COPY_IN(AccessCredentials, cred), COPY_IN(AclOwnerPrototype, owner)) +kern_return_t ucsp_server_setOwner(UCSP_ARGS, AclKind kind, IPCKeyHandle key, + DATA_IN(cred), DATA_IN(owner)) { BEGIN_IPC - relocate(cred, credBase, credLength); - relocate(owner, ownerBase, ownerLength); - Server::aclBearer(kind, key).changeOwner(*owner, cred); + CopyOutAccessCredentials creds(cred, credLength); + CopyOutOwnerAcl owneracl(owner, ownerLength); + Server::aclBearer(kind, key).changeOwner(*owneracl, creds); END_IPC(CSP) } -kern_return_t ucsp_server_getAcl(UCSP_ARGS, AclKind kind, KeyHandle key, +kern_return_t ucsp_server_getAcl(UCSP_ARGS, AclKind kind, IPCKeyHandle key, boolean_t haveTag, const char *tag, - uint32 *countp, COPY_OUT(AclEntryInfo, acls)) + uint32 *countp, DATA_OUT(acls)) { BEGIN_IPC uint32 count; AclEntryInfo *aclList; Server::aclBearer(kind, key).getAcl(haveTag ? tag : NULL, count, aclList); - *countp = count; - Copier aclsOut(aclList, count); // make flat copy - { // release the chunked memory originals - ChunkFreeWalker free; - for (uint32 n = 0; n < count; n++) - walk(free, aclList[n]); - - // release the memory allocated for the list itself when we are done - Allocator::standard().free (aclList); - } + CSSM_ACL_ENTRY_INFO_ARRAY aclsArray = { count, aclList }; + void *acls_data; u_int acls_length; + if (!::copyin(&aclsArray, reinterpret_cast(xdr_CSSM_ACL_ENTRY_INFO_ARRAY), &acls_data, &acls_length)) + CssmError::throwMe(CSSM_ERRCODE_MEMORY_ERROR); - // set result (note: this is *almost* flips(), but on an array) - *aclsLength = aclsOut.length(); - *acls = *aclsBase = aclsOut; - if (flipClient()) { - FlipWalker w; - for (uint32 n = 0; n < count; n++) - walk(w, (*acls)[n]); - w.doFlips(); - Flippers::flip(*aclsBase); + { // release the chunked memory originals + ChunkFreeWalker free; + for (uint32 n = 0; n < count; n++) + walk(free, aclList[n]); + + // release the memory allocated for the list itself when we are done + Allocator::standard().free (aclList); } - Server::releaseWhenDone(aclsOut.keep()); + + + *countp = count; // XXX/cs count becomes part of the blob + *aclsLength = acls_length; + *acls = acls_data; + Server::releaseWhenDone(acls_data); END_IPC(CSP) } -kern_return_t ucsp_server_changeAcl(UCSP_ARGS, AclKind kind, KeyHandle key, - COPY_IN(AccessCredentials, cred), CSSM_ACL_EDIT_MODE mode, CSSM_ACL_HANDLE handle, - COPY_IN(AclEntryInput, acl)) +kern_return_t ucsp_server_changeAcl(UCSP_ARGS, AclKind kind, IPCKeyHandle key, + DATA_IN(cred), CSSM_ACL_EDIT_MODE mode, IPCGenericHandle handle, + DATA_IN(acl)) { BEGIN_IPC - relocate(cred, credBase, credLength); - relocate(acl, aclBase, aclLength); - Server::aclBearer(kind, key).changeAcl(AclEdit(mode, handle, acl), cred); + CopyOutAccessCredentials creds(cred, credLength); + CopyOutAclEntryInput entryacl(acl, aclLength); + + Server::aclBearer(kind, key).changeAcl(AclEdit(mode, handle, entryacl), creds); END_IPC(CSP) } @@ -884,10 +1053,10 @@ kern_return_t ucsp_server_changeAcl(UCSP_ARGS, AclKind kind, KeyHandle key, // // Login/Logout // -kern_return_t ucsp_server_login(UCSP_ARGS, COPY_IN(AccessCredentials, cred), DATA_IN(name)) +kern_return_t ucsp_server_login(UCSP_ARGS, DATA_IN(cred), DATA_IN(name)) { BEGIN_IPC - relocate(cred, credBase, credLength); + CopyOutAccessCredentials creds(cred, credLength); CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); END_IPC(CSP) } @@ -903,7 +1072,7 @@ kern_return_t ucsp_server_logout(UCSP_ARGS) // // Miscellaneous CSP-related calls // -kern_return_t ucsp_server_getStatistics(UCSP_ARGS, uint32 ssid, CSPOperationalStatistics *statistics) +kern_return_t ucsp_server_getStatistics(UCSP_ARGS, uint32 ssid, CSSM_CSP_OPERATIONAL_STATISTICS *statistics) { BEGIN_IPC CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); @@ -935,8 +1104,8 @@ kern_return_t ucsp_server_selfVerify(UCSP_ARGS, uint32 ssid) // // Passthrough calls (separate for CSP and DL passthroughs) // -kern_return_t ucsp_server_cspPassThrough(UCSP_ARGS, uint32 ssid, uint32 id, CONTEXT_ARGS, - KeyHandle hKey, DATA_IN(inData), DATA_OUT(outData)) +kern_return_t ucsp_server_cspPassThrough(UCSP_ARGS, uint32 ssid, uint32 id, DATA_IN(context), + IPCKeyHandle hKey, DATA_IN(inData), DATA_OUT(outData)) { BEGIN_IPC CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); @@ -957,20 +1126,25 @@ kern_return_t ucsp_server_dlPassThrough(UCSP_ARGS, uint32 ssid, uint32 id, // ExtractMasterKey looks vaguely like a key derivation operation, and is in fact // presented by the CSPDL's CSSM layer as such. // -kern_return_t ucsp_server_extractMasterKey(UCSP_ARGS, DbHandle db, CONTEXT_ARGS, DbHandle sourceDb, - COPY_IN(AccessCredentials, cred), COPY_IN(AclEntryPrototype, owner), - uint32 usage, uint32 attrs, KeyHandle *newKey, CssmKey::Header *newHeader) +kern_return_t ucsp_server_extractMasterKey(UCSP_ARGS, IPCDbHandle db, DATA_IN(context), IPCDbHandle sourceDb, + DATA_IN(cred), DATA_IN(owner), + uint32 usage, uint32 attrs, IPCKeyHandle *newKey, DATA_OUT(keyHeader)) { BEGIN_IPC - context.postIPC(contextBase, attributes); - relocate(cred, credBase, credLength); - relocate(owner, ownerBase, ownerLength); + CopyOutAccessCredentials creds(cred, credLength); + CopyOutEntryAcl owneracl(owner, ownerLength); + CopyOutContext ctx(context, contextLength); RefPointer keychain = Server::keychain(sourceDb); RefPointer masterKey = keychain->extractMasterKey( *Server::optionalDatabase(db, attrs & CSSM_KEYATTR_PERMANENT), - cred, owner, usage, attrs); - masterKey->returnKey(*newKey, *newHeader); - flip(*newHeader); + creds, owneracl, usage, attrs); + KeyHandle keyHandle; + CssmKey::Header header; + masterKey->returnKey(keyHandle, header); + *newKey = keyHandle; + if (!copyin(&header, reinterpret_cast (xdr_CSSM_KEYHEADER), keyHeader, keyHeaderLength)) + CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR); + Server::releaseWhenDone(*keyHeader); END_IPC(CSP) } @@ -979,18 +1153,36 @@ kern_return_t ucsp_server_extractMasterKey(UCSP_ARGS, DbHandle db, CONTEXT_ARGS, // Authorization subsystem support // kern_return_t ucsp_server_authorizationCreate(UCSP_ARGS, - COPY_IN(AuthorizationItemSet, inRights), + void *inRights, mach_msg_type_number_t inRightsLength, uint32 flags, - COPY_IN(AuthorizationItemSet, inEnvironment), + void *inEnvironment, mach_msg_type_number_t inEnvironmentLength, AuthorizationBlob *authorization) { BEGIN_IPC - relocate(inRights, inRightsBase, inRightsLength); - relocate(inEnvironment, inEnvironmentBase, inEnvironmentLength); - Authorization::AuthItemSet rights(inRights), environment(inEnvironment); + AuthorizationItemSet *authrights = NULL, *authenvironment = NULL; + + if (inRights && !copyout_AuthorizationItemSet(inRights, inRightsLength, &authrights)) + CssmError::throwMe(errAuthorizationInternal); // allocation error probably + + if (inEnvironment && !copyout_AuthorizationItemSet(inEnvironment, inEnvironmentLength, &authenvironment)) + { + free(authrights); + CssmError::throwMe(errAuthorizationInternal); // allocation error probably + } + + Authorization::AuthItemSet rights(authrights), environment(authenvironment); *rcode = connection.process().session().authCreate(rights, environment, flags, *authorization, auditToken); + + // @@@ safe-guard against code throw()ing in here + + if (authrights) + free(authrights); + + if (authenvironment) + free(authenvironment); + END_IPC(CSSM) } @@ -1004,24 +1196,43 @@ kern_return_t ucsp_server_authorizationRelease(UCSP_ARGS, kern_return_t ucsp_server_authorizationCopyRights(UCSP_ARGS, AuthorizationBlob authorization, - COPY_IN(AuthorizationItemSet, inRights), + void *inRights, mach_msg_type_number_t inRightsLength, uint32 flags, - COPY_IN(AuthorizationItemSet, inEnvironment), - COPY_OUT(AuthorizationItemSet, result)) + void *inEnvironment, mach_msg_type_number_t inEnvironmentLength, + void **result, mach_msg_type_number_t *resultLength) { BEGIN_IPC - relocate(inRights, inRightsBase, inRightsLength); - relocate(inEnvironment, inEnvironmentBase, inEnvironmentLength); - Authorization::AuthItemSet rights(inRights), environment(inEnvironment), grantedRights; - *rcode = connection.process().session().authGetRights(authorization, - rights, environment, flags, grantedRights); + AuthorizationItemSet *authrights = NULL, *authenvironment = NULL; + + if (inRights && !copyout_AuthorizationItemSet(inRights, inRightsLength, &authrights)) + CssmError::throwMe(errAuthorizationInternal); // allocation error probably + + if (inEnvironment && !copyout_AuthorizationItemSet(inEnvironment, inEnvironmentLength, &authenvironment)) + { + free(authrights); + CssmError::throwMe(errAuthorizationInternal); // allocation error probably + } + + Authorization::AuthItemSet rights(authrights), environment(authenvironment), grantedRights; + *rcode = Session::authGetRights(authorization, rights, environment, flags, grantedRights); + + // @@@ safe-guard against code throw()ing in here + + if (authrights) + free(authrights); + + if (authenvironment) + free(authenvironment); + if (result && resultLength) { - size_t resultSize; - grantedRights.copy(*result, resultSize); - *resultLength = resultSize; - *resultBase = *result; - flips(*result, result, resultBase); + AuthorizationItemSet *copyout = grantedRights.copy(); + if (!copyin_AuthorizationItemSet(copyout, result, resultLength)) + { + free(copyout); + CssmError::throwMe(errAuthorizationInternal); + } + free(copyout); Server::releaseWhenDone(*result); } END_IPC(CSSM) @@ -1030,20 +1241,23 @@ kern_return_t ucsp_server_authorizationCopyRights(UCSP_ARGS, kern_return_t ucsp_server_authorizationCopyInfo(UCSP_ARGS, AuthorizationBlob authorization, AuthorizationString tag, - COPY_OUT(AuthorizationItemSet, info)) + void **info, mach_msg_type_number_t *infoLength) { BEGIN_IPC Authorization::AuthItemSet infoSet; - *info = *infoBase = NULL; + *info = NULL; *infoLength = 0; *rcode = connection.process().session().authGetInfo(authorization, tag[0] ? tag : NULL, infoSet); - if (*rcode == noErr) { - size_t infoSize; - infoSet.copy(*info, infoSize); - *infoLength = infoSize; - *infoBase = *info; - flips(*info, info, infoBase); + if (*rcode == noErr) + { + AuthorizationItemSet *copyout = infoSet.copy(); + if (!copyin_AuthorizationItemSet(copyout, info, infoLength)) + { + free(copyout); + CssmError::throwMe(errAuthorizationInternal); + } + free(copyout); Server::releaseWhenDone(*info); } END_IPC(CSSM) @@ -1125,25 +1339,13 @@ kern_return_t ucsp_server_setSessionUserPrefs(UCSP_ARGS, SecuritySessionId sessi // // Notification core subsystem // -kern_return_t ucsp_server_requestNotification(UCSP_ARGS, mach_port_t receiver, uint32 domain, uint32 events) -{ - BEGIN_IPC - connection.process().requestNotifications(receiver, domain, events); - END_IPC(CSSM) -} - -kern_return_t ucsp_server_stopNotification(UCSP_ARGS, mach_port_t receiver) -{ - BEGIN_IPC - connection.process().stopNotifications(receiver); - END_IPC(CSSM) -} -kern_return_t ucsp_server_postNotification(mach_port_t serverPort, uint32 domain, uint32 event, DATA_IN(data)) +kern_return_t ucsp_server_postNotification(UCSP_ARGS, uint32 domain, uint32 event, + DATA_IN(data), uint32 sequence) { - BEGIN_IPCS - Listener::notify(domain, event, DATA(data)); - END_IPCS() + BEGIN_IPC + Listener::notify(domain, event, sequence, DATA(data)); + END_IPC(CSSM) } @@ -1244,3 +1446,59 @@ kern_return_t ucsp_server_childCheckIn(mach_port_t serverPort, ServerChild::checkIn(servicePort, TaskPort(taskPort).pid()); END_IPCS(mach_port_deallocate(mach_task_self(), taskPort)) } + + +// +// Code Signing Hosting registration. +// Note that the Code Signing Proxy facility (implementing the "cshosting" +// IPC protocol) is elsewhere. +// +kern_return_t ucsp_server_registerHosting(UCSP_ARGS, mach_port_t hostingPort, uint32 flags) +{ + BEGIN_IPC + connection.process().registerCodeSigning(hostingPort, flags); + END_IPC(CSSM) +} + +kern_return_t ucsp_server_hostingPort(UCSP_ARGS, pid_t hostPid, mach_port_t *hostingPort) +{ + BEGIN_IPC + if (RefPointer process = Server::active().findPid(hostPid)) + *hostingPort = process->hostingPort(); + else + *hostingPort = MACH_PORT_NULL; + secdebug("hosting", "hosting port for for pid=%d is port %d", hostPid, *hostingPort); + END_IPC(CSSM) +} + + +kern_return_t ucsp_server_setGuest(UCSP_ARGS, SecGuestRef guest, SecCSFlags flags) +{ + BEGIN_IPC + connection.guestRef(guest, flags); + END_IPC(CSSM) +} + + +kern_return_t ucsp_server_createGuest(UCSP_ARGS, SecGuestRef host, + uint32_t status, const char *path, DATA_IN(attributes), SecCSFlags flags, SecGuestRef *newGuest) +{ + BEGIN_IPC + *newGuest = connection.process().createGuest(host, status, path, DATA(attributes), flags); + END_IPC(CSSM) +} + +kern_return_t ucsp_server_setGuestStatus(UCSP_ARGS, SecGuestRef guest, + uint32_t status, DATA_IN(attributes)) +{ + BEGIN_IPC + connection.process().setGuestStatus(guest, status, DATA(attributes)); + END_IPC(CSSM) +} + +kern_return_t ucsp_server_removeGuest(UCSP_ARGS, SecGuestRef host, SecGuestRef guest) +{ + BEGIN_IPC + connection.process().removeGuest(host, guest); + END_IPC(CSSM) +} diff --git a/src/transwalkers.cpp b/src/transwalkers.cpp deleted file mode 100644 index 2a3055a..0000000 --- a/src/transwalkers.cpp +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -// -// transwalkers - server side transition data walking support -// -// These are data walker operators for securely marshaling and unmarshaling -// data structures across IPC. They are also in charge of fixing byte order -// inconsistencies between server and clients. -// -#include - - -using LowLevelMemoryUtilities::increment; -using LowLevelMemoryUtilities::difference; - - -bool flipClient() -{ - return Server::process().byteFlipped(); -} - - -// -// CheckingRelocateWalkers -// -CheckingReconstituteWalker::CheckingReconstituteWalker(void *ptr, void *base, size_t size, bool flip) - : mBase(base), mFlip(flip) -{ - if (mFlip) - Flippers::flip(mBase); // came in reversed; fix for base use - mOffset = difference(ptr, mBase); - mLimit = increment(mBase, size); -} - - -// -// Relocation support -// -void relocate(Context &context, void *base, Context::Attr *attrs, uint32 attrSize) -{ - flip(context); - CheckingReconstituteWalker relocator(attrs, base, attrSize, flipClient()); - context.ContextAttributes = attrs; // fix context->attr vector link - for (uint32 n = 0; n < context.attributesInUse(); n++) - walk(relocator, context[n]); -} - - -// -// Outbound flipping support -// -FlipWalker::~FlipWalker() -{ - for (set::const_iterator it = mFlips.begin(); it != mFlips.end(); it++) - delete it->impl; -} - -void FlipWalker::doFlips(bool active) -{ - if (active) { - secdebug("flipwalkers", "starting outbound flips"); - for (set::const_iterator it = mFlips.begin(); it != mFlips.end(); it++) - it->impl->flip(); - secdebug("flipwalkers", "outbound flips done"); - } -} - - -// -// Choose a Database from a choice of two sources, giving preference -// to persistent stores and to earlier sources. -// -Database *pickDb(Database *db1, Database *db2) -{ - // persistent db1 always wins - if (db1 && !db1->transient()) - return db1; - - // persistent db2 is next choice - if (db2 && !db2->transient()) - return db2; - - // pick any existing transient database - if (db1) - return db1; - if (db2) - return db2; - - // none at all. use the canonical transient store - return Server::optionalDatabase(noDb); -} - - - -void fixDbAttributes (CssmDbAttributeData &data) -{ - /* - NOTE TO FUTURE MAINTAINERS OF THIS CODE: - - This code is called by two different routines; the relocation walker on the input attributes, and flips - on the output attributtes. This is bad, because the relocation walker flips the Info data structure, - and flips does not. We could fix this in flips, but flips is a template and does different things - depending on what its parameters are. As a result, the best place to do this is here. - */ - - // pull this data out first, so that it is unperverted once the flip occurs - unsigned limit = data.size (); - unsigned format = data.format (); - CssmData* values = data.values (); - - // flip if it is safe to do so - if (format > CSSM_DB_ATTRIBUTE_FORMAT_COMPLEX) // is the format screwed up? - { - flip (data.info ()); - limit = data.size (); - format = data.format (); - values = data.values (); - } - - unsigned i; - - for (i = 0; i < limit; ++i) - { - switch (format) - { - case CSSM_DB_ATTRIBUTE_FORMAT_UINT32: - Flippers::flip(*(uint32*) values[i].data ()); - break; - - case CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32: - { - CssmData& d = values[i]; - int numValues = d.length() / sizeof (UInt32); - int j; - UInt32* v = (UInt32*) d.data(); - for (j = 0; j < numValues; ++j) - { - Flippers::flip (v[j]); - } - } - break; - } - } -} - - - -void fixDbAttributes (CssmQuery &query) -{ - unsigned i; - unsigned numItems = query.size (); - for (i = 0; i < numItems; ++i) - { - fixDbAttributes(query.predicates()[i].attribute()); - } -} - - - -void fixDbAttributes (CssmDbRecordAttributeData &data) -{ - unsigned i; - unsigned numItems = data.size (); - for (i = 0; i < numItems; ++i) - { - fixDbAttributes(data.attributes()[i]); - } -} diff --git a/src/transwalkers.h b/src/transwalkers.h deleted file mode 100644 index e9476a7..0000000 --- a/src/transwalkers.h +++ /dev/null @@ -1,313 +0,0 @@ -/* - * Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -// -// transwalkers - server side transition data walking support -// -// These are data walker operators for securely marshaling and unmarshaling -// data structures across IPC. They are also in charge of fixing byte order -// inconsistencies between server and clients. -// -#ifndef _H_TRANSWALKERS -#define _H_TRANSWALKERS - -#include -#include "flippers.h" -#include "server.h" -#include - -using LowLevelMemoryUtilities::increment; -using LowLevelMemoryUtilities::difference; - - -// -// Should we flip data? -// This looks at the current client's process information (a thread-global state) -// to determine flip status. Valid (only) within BEGIN_IPC/END_IPC brackets. -// -bool flipClient(); - - -// -// A CheckingReconstituteWalker is a variant of an ordinary ReconstituteWalker -// that checks object pointers and sizes against the incoming block limits. -// It throws an exception if incoming data has pointers outside the incoming block. -// This avoids trouble inside of securityd caused (by bug or malice) -// from someone spoofing the client access side. -// -class CheckingReconstituteWalker { -private: - void check(void *addr, size_t size) - { - if (addr < mBase || increment(addr, size) > mLimit) - CssmError::throwMe(CSSM_ERRCODE_INVALID_POINTER); - } - -public: - CheckingReconstituteWalker(void *ptr, void *base, size_t size, bool flip); - - template - void operator () (T &obj, size_t size = sizeof(T)) - { - check(increment(&obj, -mOffset), size); - if (mFlip) - Flippers::flip(obj); - } - - template - void operator () (T * &addr, size_t size = sizeof(T)) - { - DEBUGWALK("checkreconst:ptr"); - if (addr) { - // process the pointer - void *p = addr; - blob(p, size); - addr = reinterpret_cast(p); - - // now flip the contents - if (mFlip) - Flippers::flip(*addr); - } - } - - template - void blob(T * &addr, size_t size) - { - DEBUGWALK("checkreconst:blob"); - if (addr) { - // flip the address (the pointer itself) - if (mFlip) { - secdebug("flippers", "flipping %s@%p", Debug::typeName(addr).c_str(), addr); - Flippers::flip(addr); - } - - // check the address against the transmitted bounds - check(addr, size); - - // relocate it - addr = increment(addr, mOffset); - } - } - - static const bool needsRelinking = true; - static const bool needsSize = false; - -private: - void *mBase; // old base address - void *mLimit; // old last byte address + 1 - off_t mOffset; // relocation offset - bool mFlip; // apply byte order flipping -}; - - -// -// Fix DBAttributes, which have to be processed specially -// -void fixDbAttributes (CssmDbAttributeData &data); -void fixDbAttributes (CssmQuery &query); -void fixDbAttributes (CssmDbRecordAttributeData &data); - -template -void fixDbAttributes(T &n) {} // handle the default case - - -// -// Process an incoming (IPC) data blob of type T. -// This relocates pointers to fit in the local address space, -// and fixes byte order issues as needed. -// -template -void relocate(T *obj, T *base, size_t size) -{ - if (obj) { - if (base == NULL) // invalid, could confuse walkers - CssmError::throwMe(CSSM_ERRCODE_INVALID_POINTER); - CheckingReconstituteWalker relocator(obj, base, size, - Server::process().byteFlipped()); - walk(relocator, base); - - // resolve weird type interdependency in DB_ATTRIBUTE_DATA - if (Server::process().byteFlipped()) - fixDbAttributes(*obj); - } -} - - -// -// Special handling for incoming CSSM contexts. -// -void relocate(Context &context, void *base, Context::Attr *attrs, uint32 attrSize); - - -// -// A FlipWalker is a walker operator that collects its direct invocations -// into a set of memory objects. These objects can then collectively be -// byte-flipped (exactly once :-) at the flick of a method. -// -class FlipWalker { -private: - struct Base { - virtual ~Base() { } - virtual void flip() const = 0; - }; - - template - struct FlipRef : public Base { - T &obj; - FlipRef(T &s) : obj(s) { } - void flip() const { Flippers::flip(obj); } - }; - - template - struct FlipPtr : public Base { - T * &obj; - FlipPtr(T * &s) : obj(s) { } - void flip() const { Flippers::flip(*obj); Flippers::flip(obj); } - }; - - template - struct FlipBlob : public Base { - T * &obj; - FlipBlob(T * &s) : obj(s) { } - void flip() const { Flippers::flip(obj); } - }; - - struct Flipper { - Base *impl; - Flipper(Base *p) : impl(p) { } - bool operator < (const Flipper &other) const - { return impl < other.impl; } - }; - -public: - ~FlipWalker(); - void doFlips(bool active = true); - - template - void operator () (T &obj, size_t = sizeof(T)) - { mFlips.insert(new FlipRef(obj)); } - - template - T *operator () (T * &addr, size_t size = sizeof(T)) - { mFlips.insert(new FlipPtr(addr)); return addr; } - - template - void blob(T * &addr, size_t size) - { mFlips.insert(new FlipBlob(addr)); } - - static const bool needsRelinking = true; - static const bool needsSize = true; - -private: - set mFlips; -}; - - -// -// A raw flip, conditioned on the client's flip state -// -template -void flip(T &addr) -{ - if (flipClient()) { - secdebug("flippers", "raw flipping %s", Debug::typeName(addr).c_str()); - Flippers::flip(addr); - } -} - - -void flipCssmDbAttributeData (CssmDbRecordAttributeData *value, CssmDbRecordAttributeData **&addr, CssmDbRecordAttributeData **&base); - -// -// Take an object at value, flip it, and return appropriately flipped -// addr/base pointers ready to be returned through IPC. -// Note that this doesn't set the outgoing length (aka 'fooLength') field. -// -template -void flips(T *value, T ** &addr, T ** &base) -{ - *addr = *base = value; - if (flipClient()) { - // resolve weird type inter-dependency in DB_ATTRIBUTE_DATA - if (value) - fixDbAttributes(*value); - FlipWalker w; // collector - walk(w, value); // collect all flippings needed - w.doFlips(); // execute flips (flips value but leaves addr alone) - Flippers::flip(*base); // flip base (so it arrives right side up) - } -} - -// -// Take a DATA type RPC argument purportedly representing a Blob of some kind, -// turn it into a Blob, and fail properly if it's not kosher. -// -template -const BlobType *makeBlob(const CssmData &blobData, CSSM_RETURN error = CSSM_ERRCODE_INVALID_DATA) -{ - if (!blobData.data() || blobData.length() < sizeof(BlobType)) - CssmError::throwMe(error); - const BlobType *blob = static_cast(blobData.data()); - if (blob->totalLength != blobData.length()) - CssmError::throwMe(error); - return blob; -} - - -// -// An OutputData object will take memory allocated within securityd, -// hand it to the MIG return-output parameters, and schedule it to be released -// after the MIG reply has been sent. It will also get rid of it in case of -// error. -// -class OutputData : public CssmData { -public: - OutputData(void **outP, mach_msg_type_number_t *outLength) - : mData(*outP), mLength(*outLength) { } - ~OutputData() - { mData = data(); mLength = length(); Server::releaseWhenDone(mData); } - - void operator = (const CssmData &source) - { CssmData::operator = (source); } - -private: - void * &mData; - mach_msg_type_number_t &mLength; -}; - - -// -// Choose a Database from a choice of two sources, giving preference -// to persistent stores and to earlier sources. -// -Database *pickDb(Database *db1, Database *db2); - -static inline Database *dbOf(Key *key) { return key ? &key->database() : NULL; } - -inline Database *pickDb(Key *k1, Key *k2) { return pickDb(dbOf(k1), dbOf(k2)); } -inline Database *pickDb(Database *db1, Key *k2) { return pickDb(db1, dbOf(k2)); } -inline Database *pickDb(Key *k1, Database *db2) { return pickDb(dbOf(k1), db2); } - - -#endif //_H_TRANSWALKERS -- 2.45.2