2 * Copyright (c) 2002-2004 Apple Computer, Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
25 // Policy.cpp - Working with Policies
27 #include <security_keychain/Policies.h>
28 #include <security_utilities/debugging.h>
29 #include <Security/oidsalg.h>
30 #include <sys/param.h>
32 /* Oids longer than this are considered invalid. */
33 #define MAX_OID_SIZE 32
35 //%%FIXME: need to use a common copy of this utility function
36 CFStringRef
SecDERItemCopyOIDDecimalRepresentation(uint8
*oid
, size_t oidLen
)
39 return CFSTR("<NULL>");
41 if (oidLen
> MAX_OID_SIZE
)
42 return CFSTR("Oid too long");
44 CFMutableStringRef result
= CFStringCreateMutable(kCFAllocatorDefault
, 0);
46 // The first two levels are encoded into one byte, since the root level
47 // has only 3 nodes (40*x + y). However if x = joint-iso-itu-t(2) then
48 // y may be > 39, so we have to add special-case handling for this.
49 uint32_t x
= oid
[0] / 40;
50 uint32_t y
= oid
[0] % 40;
53 // Handle special case for large y if x = 2
57 CFStringAppendFormat(result
, NULL
, CFSTR("%u.%u"), x
, y
);
60 for (x
= 1; x
< oidLen
; ++x
)
62 value
= (value
<< 7) | (oid
[x
] & 0x7F);
63 /* @@@ value may not span more than 4 bytes. */
64 /* A max number of 20 values is allowed. */
67 CFStringAppendFormat(result
, NULL
, CFSTR(".%lu"), value
);
75 using namespace KeychainCore
;
77 Policy::Policy(TP supportingTp
, const CssmOid
&policyOid
)
79 mOid(Allocator::standard(), policyOid
),
80 mValue(Allocator::standard()),
81 mAuxValue(Allocator::standard())
83 // value is as yet unimplemented
84 secdebug("policy", "Policy() this %p", this);
87 Policy::~Policy() throw()
89 secdebug("policy", "~Policy() this %p", this);
92 void Policy::setValue(const CssmData
&value
)
94 StLock
<Mutex
>_(mMutex
);
98 // Certain policy values may contain an embedded pointer. Ask me how I feel about that.
99 if (mOid
== CSSMOID_APPLE_TP_SSL
||
100 mOid
== CSSMOID_APPLE_TP_EAP
||
101 mOid
== CSSMOID_APPLE_TP_IP_SEC
||
102 mOid
== CSSMOID_APPLE_TP_APPLEID_SHARING
)
104 CSSM_APPLE_TP_SSL_OPTIONS
*opts
= (CSSM_APPLE_TP_SSL_OPTIONS
*)value
.data();
105 if (opts
->Version
== CSSM_APPLE_TP_SSL_OPTS_VERSION
)
107 if (opts
->ServerNameLen
> 0)
109 // Copy auxiliary data, then update the embedded pointer to reference our copy
110 mAuxValue
.copy(const_cast<char*>(opts
->ServerName
), opts
->ServerNameLen
);
111 mValue
.get().interpretedAs
<CSSM_APPLE_TP_SSL_OPTIONS
>()->ServerName
=
112 reinterpret_cast<char*>(mAuxValue
.data());
116 // Clear the embedded pointer!
117 mValue
.get().interpretedAs
<CSSM_APPLE_TP_SSL_OPTIONS
>()->ServerName
=
118 reinterpret_cast<char*>(NULL
);
122 else if (mOid
== CSSMOID_APPLE_TP_SMIME
||
123 mOid
== CSSMOID_APPLE_TP_ICHAT
)
125 CSSM_APPLE_TP_SMIME_OPTIONS
*opts
= (CSSM_APPLE_TP_SMIME_OPTIONS
*)value
.data();
126 if (opts
->Version
== CSSM_APPLE_TP_SMIME_OPTS_VERSION
)
128 if (opts
->SenderEmailLen
> 0)
130 // Copy auxiliary data, then update the embedded pointer to reference our copy
131 mAuxValue
.copy(const_cast<char*>(opts
->SenderEmail
), opts
->SenderEmailLen
);
132 mValue
.get().interpretedAs
<CSSM_APPLE_TP_SMIME_OPTIONS
>()->SenderEmail
=
133 reinterpret_cast<char*>(mAuxValue
.data());
137 // Clear the embedded pointer!
138 mValue
.get().interpretedAs
<CSSM_APPLE_TP_SMIME_OPTIONS
>()->SenderEmail
=
139 reinterpret_cast<char*>(NULL
);
145 void Policy::setProperties(CFDictionaryRef properties
)
147 // Set the policy value based on the provided dictionary keys.
148 if (mOid
== CSSMOID_APPLE_TP_SSL
||
149 mOid
== CSSMOID_APPLE_TP_EAP
||
150 mOid
== CSSMOID_APPLE_TP_IP_SEC
||
151 mOid
== CSSMOID_APPLE_TP_APPLEID_SHARING
)
153 CSSM_APPLE_TP_SSL_OPTIONS options
= { CSSM_APPLE_TP_SSL_OPTS_VERSION
, 0, NULL
, 0 };
155 CFStringRef nameStr
= NULL
;
156 if (CFDictionaryGetValueIfPresent(properties
, (const void *)kSecPolicyName
, (const void **)&nameStr
)) {
157 buf
= (char *)malloc(MAXPATHLEN
);
159 if (CFStringGetCString(nameStr
, buf
, MAXPATHLEN
, kCFStringEncodingUTF8
)) {
160 options
.ServerName
= buf
;
161 options
.ServerNameLen
= strlen(buf
)+1; // include terminating null
165 CFBooleanRef clientRef
= NULL
;
166 if (CFDictionaryGetValueIfPresent(properties
, (const void *)kSecPolicyClient
, (const void **)&clientRef
)
167 && CFBooleanGetValue(clientRef
) == true)
168 options
.Flags
|= CSSM_APPLE_TP_SSL_CLIENT
;
170 const CssmData
value((uint8
*)&options
, sizeof(options
));
171 this->setValue(value
);
175 else if (mOid
== CSSMOID_APPLE_TP_SMIME
||
176 mOid
== CSSMOID_APPLE_TP_ICHAT
)
178 CSSM_APPLE_TP_SMIME_OPTIONS options
= { CSSM_APPLE_TP_SMIME_OPTS_VERSION
, 0, 0, NULL
};
180 CFStringRef nameStr
= NULL
;
181 if (CFDictionaryGetValueIfPresent(properties
, (const void *)kSecPolicyName
, (const void **)&nameStr
)) {
182 buf
= (char *)malloc(MAXPATHLEN
);
184 if (CFStringGetCString(nameStr
, buf
, MAXPATHLEN
, kCFStringEncodingUTF8
)) {
185 options
.SenderEmail
= buf
;
186 options
.SenderEmailLen
= strlen(buf
)+1; // include terminating null
190 CFBooleanRef kuRef
= NULL
;
191 if (CFDictionaryGetValueIfPresent(properties
, (const void *)kSecPolicyKU_DigitalSignature
, (const void **)&kuRef
)
192 && CFBooleanGetValue(kuRef
) == true)
193 options
.IntendedUsage
|= CE_KU_DigitalSignature
;
194 if (CFDictionaryGetValueIfPresent(properties
, (const void *)kSecPolicyKU_NonRepudiation
, (const void **)&kuRef
)
195 && CFBooleanGetValue(kuRef
) == true)
196 options
.IntendedUsage
|= CE_KU_NonRepudiation
;
197 if (CFDictionaryGetValueIfPresent(properties
, (const void *)kSecPolicyKU_KeyEncipherment
, (const void **)&kuRef
)
198 && CFBooleanGetValue(kuRef
) == true)
199 options
.IntendedUsage
|= CE_KU_KeyEncipherment
;
200 if (CFDictionaryGetValueIfPresent(properties
, (const void *)kSecPolicyKU_DataEncipherment
, (const void **)&kuRef
)
201 && CFBooleanGetValue(kuRef
) == true)
202 options
.IntendedUsage
|= CE_KU_DataEncipherment
;
203 if (CFDictionaryGetValueIfPresent(properties
, (const void *)kSecPolicyKU_KeyAgreement
, (const void **)&kuRef
)
204 && CFBooleanGetValue(kuRef
) == true)
205 options
.IntendedUsage
|= CE_KU_KeyAgreement
;
206 if (CFDictionaryGetValueIfPresent(properties
, (const void *)kSecPolicyKU_KeyCertSign
, (const void **)&kuRef
)
207 && CFBooleanGetValue(kuRef
) == true)
208 options
.IntendedUsage
|= CE_KU_KeyCertSign
;
209 if (CFDictionaryGetValueIfPresent(properties
, (const void *)kSecPolicyKU_CRLSign
, (const void **)&kuRef
)
210 && CFBooleanGetValue(kuRef
) == true)
211 options
.IntendedUsage
|= CE_KU_CRLSign
;
212 if (CFDictionaryGetValueIfPresent(properties
, (const void *)kSecPolicyKU_EncipherOnly
, (const void **)&kuRef
)
213 && CFBooleanGetValue(kuRef
) == true)
214 options
.IntendedUsage
|= CE_KU_EncipherOnly
;
215 if (CFDictionaryGetValueIfPresent(properties
, (const void *)kSecPolicyKU_DecipherOnly
, (const void **)&kuRef
)
216 && CFBooleanGetValue(kuRef
) == true)
217 options
.IntendedUsage
|= CE_KU_DecipherOnly
;
219 const CssmData
value((uint8
*)&options
, sizeof(options
));
220 this->setValue(value
);
227 CFDictionaryRef
Policy::properties()
229 // Builds and returns a dictionary which the caller must release.
230 CSSM_DATA value
= this->value();
231 CFMutableDictionaryRef properties
= CFDictionaryCreateMutable(NULL
, 0,
232 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
233 if (!properties
) return NULL
;
236 CFStringRef oidStr
= SecDERItemCopyOIDDecimalRepresentation((uint8
*)mOid
.data(), mOid
.length());
238 CFDictionarySetValue(properties
, (const void *)kSecPolicyOid
, (const void *)oidStr
);
244 CFStringRef nameStr
= CFStringCreateWithBytes(NULL
,
245 (const UInt8
*)reinterpret_cast<char*>(mAuxValue
.data()),
246 (CFIndex
)mAuxValue
.length(), kCFStringEncodingUTF8
, false);
248 CFDictionarySetValue(properties
, (const void *)kSecPolicyName
, (const void *)nameStr
);
255 if (mOid
== CSSMOID_APPLE_TP_SSL
||
256 mOid
== CSSMOID_APPLE_TP_EAP
||
257 mOid
== CSSMOID_APPLE_TP_IP_SEC
||
258 mOid
== CSSMOID_APPLE_TP_APPLEID_SHARING
)
260 CSSM_APPLE_TP_SSL_OPTIONS
*opts
= (CSSM_APPLE_TP_SSL_OPTIONS
*)mValue
.data();
261 if (opts
->Flags
& CSSM_APPLE_TP_SSL_CLIENT
) {
262 CFDictionarySetValue(properties
, (const void *)kSecPolicyClient
, (const void *)kCFBooleanTrue
);
267 // key usage flags (currently only for S/MIME and iChat policies)
269 if (mOid
== CSSMOID_APPLE_TP_SMIME
||
270 mOid
== CSSMOID_APPLE_TP_ICHAT
)
272 CSSM_APPLE_TP_SMIME_OPTIONS
*opts
= (CSSM_APPLE_TP_SMIME_OPTIONS
*)mValue
.data();
273 CE_KeyUsage usage
= opts
->IntendedUsage
;
274 if (usage
& CE_KU_DigitalSignature
)
275 CFDictionarySetValue(properties
, (const void *)kSecPolicyKU_DigitalSignature
, (const void *)kCFBooleanTrue
);
276 if (usage
& CE_KU_NonRepudiation
)
277 CFDictionarySetValue(properties
, (const void *)kSecPolicyKU_NonRepudiation
, (const void *)kCFBooleanTrue
);
278 if (usage
& CE_KU_KeyEncipherment
)
279 CFDictionarySetValue(properties
, (const void *)kSecPolicyKU_KeyEncipherment
, (const void *)kCFBooleanTrue
);
280 if (usage
& CE_KU_DataEncipherment
)
281 CFDictionarySetValue(properties
, (const void *)kSecPolicyKU_DataEncipherment
, (const void *)kCFBooleanTrue
);
282 if (usage
& CE_KU_KeyAgreement
)
283 CFDictionarySetValue(properties
, (const void *)kSecPolicyKU_KeyAgreement
, (const void *)kCFBooleanTrue
);
284 if (usage
& CE_KU_KeyCertSign
)
285 CFDictionarySetValue(properties
, (const void *)kSecPolicyKU_KeyCertSign
, (const void *)kCFBooleanTrue
);
286 if (usage
& CE_KU_CRLSign
)
287 CFDictionarySetValue(properties
, (const void *)kSecPolicyKU_CRLSign
, (const void *)kCFBooleanTrue
);
288 if (usage
& CE_KU_EncipherOnly
)
289 CFDictionarySetValue(properties
, (const void *)kSecPolicyKU_EncipherOnly
, (const void *)kCFBooleanTrue
);
290 if (usage
& CE_KU_DecipherOnly
)
291 CFDictionarySetValue(properties
, (const void *)kSecPolicyKU_DecipherOnly
, (const void *)kCFBooleanTrue
);
298 bool Policy::operator < (const Policy
& other
) const
301 return oid() < other
.oid() ||
302 oid() == other
.oid() && value() < other
.value();
305 bool Policy::operator == (const Policy
& other
) const
307 return oid() == other
.oid() && value() == other
.value();
310 bool Policy::equal(SecCFObject
&other
)
312 return (*this) == (const Policy
&)other
;