]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. | |
3 | * | |
4 | * The contents of this file constitute Original Code as defined in and are | |
5 | * subject to the Apple Public Source License Version 1.2 (the 'License'). | |
6 | * You may not use this file except in compliance with the License. Please obtain | |
7 | * a copy of the License at http://www.apple.com/publicsource and read it before | |
8 | * using this file. | |
9 | * | |
10 | * This Original Code and all software distributed under the License are | |
11 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS | |
12 | * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT | |
13 | * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR | |
14 | * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the | |
15 | * specific language governing rights and limitations under the License. | |
16 | */ | |
17 | ||
18 | ||
19 | // | |
20 | // SSCSPDLSession.cpp - Security Server CSP/DL session. | |
21 | // | |
22 | #include "SSCSPDLSession.h" | |
23 | ||
24 | #include "CSPDLPlugin.h" | |
25 | #include "SSKey.h" | |
26 | ||
27 | ||
28 | #ifndef SECURITYSERVER_ACL_EDITS | |
29 | ||
30 | #include <Security/aclclient.h> | |
31 | #include <Security/Access.h> | |
32 | #include <Security/TrustedApplication.h> | |
33 | ||
34 | // | |
35 | // ClientSessionKey - Lightweight wrapper for a KeyHandle that is also an CssmClient::AclBearer | |
36 | // | |
37 | class ClientSessionKey: public CssmClient::AclBearer | |
38 | { | |
39 | public: | |
40 | ClientSessionKey(SecurityServer::ClientSession &clientSession, SecurityServer::KeyHandle keyHandle); | |
41 | ~ClientSessionKey(); | |
42 | ||
43 | // Acl manipulation | |
44 | virtual void getAcl(AutoAclEntryInfoList &aclInfos, | |
45 | const char *selectionTag = NULL) const; | |
46 | virtual void changeAcl(const CSSM_ACL_EDIT &aclEdit, | |
47 | const CSSM_ACCESS_CREDENTIALS *cred = NULL); | |
48 | ||
49 | // Acl owner manipulation | |
50 | virtual void getOwner(AutoAclOwnerPrototype &owner) const; | |
51 | virtual void changeOwner(const CSSM_ACL_OWNER_PROTOTYPE &newOwner, | |
52 | const CSSM_ACCESS_CREDENTIALS *cred = NULL); | |
53 | ||
54 | ||
55 | private: | |
56 | SecurityServer::ClientSession &mClientSession; | |
57 | SecurityServer::KeyHandle mKeyHandle; | |
58 | }; | |
59 | ||
60 | #endif //!SECURITYSERVER_ACL_EDITS | |
61 | ||
62 | ||
63 | using namespace SecurityServer; | |
64 | ||
65 | // | |
66 | // SSCSPDLSession -- Security Server CSP session | |
67 | // | |
68 | SSCSPDLSession::SSCSPDLSession() | |
69 | { | |
70 | } | |
71 | ||
72 | ||
73 | // | |
74 | // Reference Key management | |
75 | // | |
76 | void | |
77 | SSCSPDLSession::makeReferenceKey(SSCSPSession &session, KeyHandle inKeyHandle, | |
78 | CssmKey &outKey, SSDatabase &inSSDatabase, | |
79 | uint32 inKeyAttr, const CssmData *inKeyLabel) | |
80 | { | |
81 | new SSKey(session, inKeyHandle, outKey, inSSDatabase, inKeyAttr, | |
82 | inKeyLabel); | |
83 | } | |
84 | ||
85 | SSKey & | |
86 | SSCSPDLSession::lookupKey(const CssmKey &inKey) | |
87 | { | |
88 | /* for now we only allow ref keys */ | |
89 | if(inKey.blobType() != CSSM_KEYBLOB_REFERENCE) { | |
90 | CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); | |
91 | } | |
92 | ||
93 | /* fetch key (this is just mapping the value in inKey.KeyData to an SSKey) */ | |
94 | SSKey &theKey = find<SSKey>(inKey); | |
95 | ||
96 | #ifdef someday | |
97 | /* | |
98 | * Make sure caller hasn't changed any crucial header fields. | |
99 | * Some fields were changed by makeReferenceKey, so make a local copy.... | |
100 | */ | |
101 | CSSM_KEYHEADER localHdr = cssmKey.KeyHeader; | |
102 | get binKey-like thing from SSKey, maybe SSKey should keep a copy of | |
103 | hdr...but that's' not supersecure....; | |
104 | ||
105 | localHdr.BlobType = binKey->mKeyHeader.BlobType; | |
106 | localHdr.Format = binKey->mKeyHeader.Format; | |
107 | if(memcmp(&localHdr, &binKey->mKeyHeader, sizeof(CSSM_KEYHEADER))) { | |
108 | CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_REFERENCE); | |
109 | } | |
110 | #endif | |
111 | return theKey; | |
112 | } | |
113 | ||
114 | // Notification we receive when the acl on a key has changed. We should write it back to disk if it's persistant. | |
115 | void | |
116 | SSCSPDLSession::didChangeKeyAcl(SecurityServer::ClientSession &clientSession, | |
117 | KeyHandle keyHandle, CSSM_ACL_AUTHORIZATION_TAG tag) | |
118 | { | |
119 | #ifndef SECURITYSERVER_ACL_EDITS | |
120 | { | |
121 | // The user checked to don't ask again checkbox in the rogue app alert. Let's edit the ACL for this key and add the calling application (ourself) to it. | |
122 | secdebug("keyacl", "SSCSPDLSession::didChangeKeyAcl(keyHandle: %lu tag: %lu)", keyHandle, tag); | |
123 | ClientSessionKey csKey(clientSession, keyHandle); // the underlying key | |
124 | KeychainCore::SecPointer<KeychainCore::Access> access = new KeychainCore::Access(csKey); // extract access rights | |
125 | KeychainCore::SecPointer<KeychainCore::TrustedApplication> thisApp = new KeychainCore::TrustedApplication; | |
126 | access->addApplicationToRight(tag, thisApp.get()); // add this app | |
127 | access->setAccess(csKey, true); // commit | |
128 | } | |
129 | #endif // !SECURITYSERVER_ACL_EDITS | |
130 | ||
131 | SSKey *theKey = NULL; | |
132 | ||
133 | { | |
134 | // Lookup the SSKey for the KeyHandle | |
135 | StLock<Mutex> _(mKeyMapLock); | |
136 | KeyMap::const_iterator it; | |
137 | KeyMap::const_iterator end = mKeyMap.end(); | |
138 | for (it = mKeyMap.begin(); it != end; ++it) | |
139 | { | |
140 | SSKey *aKey = dynamic_cast<SSKey *>(it->second); | |
141 | if (aKey->optionalKeyHandle() == keyHandle) | |
142 | { | |
143 | // Write the key to disk if it's persistant. | |
144 | theKey = aKey; | |
145 | break; | |
146 | } | |
147 | } | |
148 | } | |
149 | ||
150 | if (theKey) | |
151 | { | |
152 | theKey->didChangeAcl(); | |
153 | } | |
154 | else | |
155 | { | |
156 | // @@@ Should we really throw here or just continue without updating the ACL? In reality this should never happen, so let's at least log it and throw. | |
157 | secdebug("keyacl", "SSCSPDLSession::didChangeKeyAcl() keyHandle: %lu not found in map", keyHandle); | |
158 | CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_REFERENCE); | |
159 | } | |
160 | } | |
161 | ||
162 | void | |
163 | SSCSPDLSession::didChangeKeyAclCallback(void *context, SecurityServer::ClientSession &clientSession, | |
164 | SecurityServer::KeyHandle key, CSSM_ACL_AUTHORIZATION_TAG tag) | |
165 | { | |
166 | reinterpret_cast<SSCSPDLSession *>(context)->didChangeKeyAcl(clientSession, key, tag); | |
167 | } | |
168 | ||
169 | #ifndef SECURITYSERVER_ACL_EDITS | |
170 | // | |
171 | // ClientSessionKey - Lightweight wrapper for a KeyHandle that is also an CssmClient::AclBearer | |
172 | // | |
173 | ClientSessionKey::ClientSessionKey(ClientSession &clientSession, SecurityServer::KeyHandle keyHandle) : | |
174 | mClientSession(clientSession), | |
175 | mKeyHandle(keyHandle) | |
176 | { | |
177 | } | |
178 | ||
179 | ClientSessionKey::~ClientSessionKey() | |
180 | { | |
181 | } | |
182 | ||
183 | void | |
184 | ClientSessionKey::getAcl(AutoAclEntryInfoList &aclInfos, | |
185 | const char *selectionTag) const | |
186 | { | |
187 | secdebug("keyacl", "ClientSessionKey::getAcl() keyHandle: %lu", mKeyHandle); | |
188 | aclInfos.allocator(mClientSession.returnAllocator); | |
189 | mClientSession.getKeyAcl(mKeyHandle, selectionTag, | |
190 | *static_cast<uint32 *>(aclInfos), | |
191 | *reinterpret_cast<AclEntryInfo **>(static_cast<CSSM_ACL_ENTRY_INFO_PTR *>(aclInfos))); | |
192 | } | |
193 | ||
194 | void | |
195 | ClientSessionKey::changeAcl(const CSSM_ACL_EDIT &aclEdit, | |
196 | const CSSM_ACCESS_CREDENTIALS *cred) | |
197 | { | |
198 | secdebug("keyacl", "ClientSessionKey::changeAcl() keyHandle: %lu", mKeyHandle); | |
199 | mClientSession.changeKeyAcl(mKeyHandle, AccessCredentials::overlay(*cred), AclEdit::overlay(aclEdit)); | |
200 | } | |
201 | ||
202 | void | |
203 | ClientSessionKey::getOwner(AutoAclOwnerPrototype &owner) const | |
204 | { | |
205 | secdebug("keyacl", "ClientSessionKey::getOwner() keyHandle: %lu", mKeyHandle); | |
206 | owner.allocator(mClientSession.returnAllocator); | |
207 | mClientSession.getKeyOwner(mKeyHandle, | |
208 | *reinterpret_cast<AclOwnerPrototype *>(static_cast<CSSM_ACL_OWNER_PROTOTYPE *>(owner))); | |
209 | } | |
210 | ||
211 | void | |
212 | ClientSessionKey::changeOwner(const CSSM_ACL_OWNER_PROTOTYPE &newOwner, | |
213 | const CSSM_ACCESS_CREDENTIALS *cred) | |
214 | { | |
215 | secdebug("keyacl", "ClientSessionKey::changeOwner() keyHandle: %lu", mKeyHandle); | |
216 | mClientSession.changeKeyOwner(mKeyHandle, AccessCredentials::overlay(*cred), AclOwnerPrototype::overlay(newOwner)); | |
217 | } | |
218 | ||
219 | #endif // !SECURITYSERVER_ACL_EDITS |