VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/darwin/RTCrStoreCreateSnapshotById-darwin.cpp@ 103914

Last change on this file since 103914 was 102997, checked in by vboxsync, 10 months ago

IPRT: Shut up some deprecated function warnings with macOS SDK 13.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.9 KB
Line 
1/* $Id: RTCrStoreCreateSnapshotById-darwin.cpp 102997 2024-01-23 10:10:13Z vboxsync $ */
2/** @file
3 * IPRT - RTCrStoreCreateSnapshotById, Darwin.
4 */
5
6/*
7 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#include <iprt/crypto/store.h>
42#include "internal/iprt.h"
43
44#include <iprt/assert.h>
45#include <iprt/err.h>
46#include <iprt/file.h>
47
48
49/* HACK ALERT! Shut up those deprecated messages on SecKeychainSearchCreateFromAttributes and SecKeychainSearchCopyNext
50 with older SDKs version (newer requires RT_GCC_NO_WARN_DEPRECATED_BEGIN). */
51#include <CoreFoundation/CoreFoundation.h>
52#undef DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
53#define DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
54
55/* The SecKeychainCopyDomainSearchList and others API are also deprecated since 10.0.
56 See https://developer.apple.com/documentation/technotes/tn3137-on-mac-keychains for some info.
57 We use RT_GCC_NO_WARN_DEPRECATED_BEGIN to silence these. */
58
59#include <Security/Security.h>
60
61
62/**
63 * Checks the trust settings of the certificate.
64 *
65 * @returns true if not out-right distructed, otherwise false.
66 * @param hCert The certificate.
67 * @param enmTrustDomain The trust settings domain to check relative to.
68 */
69static bool rtCrStoreIsDarwinCertTrustworthy(SecCertificateRef hCert, SecTrustSettingsDomain enmTrustDomain)
70{
71 bool fResult = true;
72 CFArrayRef hTrustSettings;
73 OSStatus orc = SecTrustSettingsCopyTrustSettings(hCert, enmTrustDomain, &hTrustSettings);
74 if (orc == noErr)
75 {
76 CFIndex const cTrustSettings = CFArrayGetCount(hTrustSettings);
77 for (CFIndex i = 0; i < cTrustSettings; i++)
78 {
79 CFDictionaryRef hDict = (CFDictionaryRef)CFArrayGetValueAtIndex(hTrustSettings, i);
80 AssertContinue(CFGetTypeID(hDict) == CFDictionaryGetTypeID());
81
82 CFNumberRef hNum = (CFNumberRef)CFDictionaryGetValue(hDict, kSecTrustSettingsResult);
83 if (hNum)
84 {
85 AssertContinue(CFGetTypeID(hNum) == CFNumberGetTypeID());
86 SInt32 iNum;
87 if (CFNumberGetValue(hNum, kCFNumberSInt32Type, &iNum))
88 {
89 if (iNum == kSecTrustSettingsResultDeny)
90 {
91 fResult = false;
92 break;
93 }
94 }
95 /* No need to release hNum (get rule). */
96 }
97 /* No need to release hDict (get rule). */
98 }
99 CFRelease(hTrustSettings);
100 }
101 else if (orc != errSecItemNotFound)
102 {
103 AssertFailed();
104 fResult = false;
105 }
106 return fResult;
107}
108
109
110static int rtCrStoreAddCertsFromNativeKeychain(RTCRSTORE hStore, SecKeychainRef hKeychain, SecTrustSettingsDomain enmTrustDomain,
111 int rc, PRTERRINFO pErrInfo)
112{
113 /** @todo The SecKeychainSearchCreateFromAttributes and
114 * SecKeychainSearchCopyNext APIs have been officially deprecated since 10.7
115 * according to the header files. However, the perferred API,
116 * SecItemCopyMatching (and possibly SecTrustCopyAnchorCertificates) would
117 * require a larger rewrite here and that's just not worth it right now. We can
118 * do that should these APIs be removed (unlikely given the amount of grep hits
119 * in the public 10.15.3 sources). */
120
121 /*
122 * Enumerate the certificates in the keychain.
123 */
124 RT_GCC_NO_WARN_DEPRECATED_BEGIN
125 SecKeychainSearchRef hSearch;
126 OSStatus orc = SecKeychainSearchCreateFromAttributes(hKeychain, kSecCertificateItemClass, NULL, &hSearch);
127 if (orc == noErr)
128 {
129 SecKeychainItemRef hItem;
130 while ((orc = SecKeychainSearchCopyNext(hSearch, &hItem)) == noErr)
131 {
132 Assert(CFGetTypeID(hItem) == SecCertificateGetTypeID());
133 SecCertificateRef hCert = (SecCertificateRef)hItem;
134
135 /*
136 * Check if the current certificate is at all trusted, skip it if it's isn't.
137 */
138 if (rtCrStoreIsDarwinCertTrustworthy(hCert, enmTrustDomain))
139 {
140 /*
141 * Get the certificate data.
142 */
143 CFDataRef hEncodedCert = SecCertificateCopyData(hCert);
144 Assert(hEncodedCert);
145 if (hEncodedCert)
146 {
147 CFIndex cbEncoded = CFDataGetLength(hEncodedCert);
148 const uint8_t *pbEncoded = CFDataGetBytePtr(hEncodedCert);
149
150 RTERRINFOSTATIC StaticErrInfo;
151 int rc2 = RTCrStoreCertAddEncoded(hStore, RTCRCERTCTX_F_ENC_X509_DER | RTCRCERTCTX_F_ADD_IF_NOT_FOUND,
152 pbEncoded, cbEncoded, RTErrInfoInitStatic(&StaticErrInfo));
153 if (RT_FAILURE(rc2))
154 {
155 if (RTErrInfoIsSet(&StaticErrInfo.Core))
156 RTErrInfoAddF(pErrInfo, -rc2, " %s", StaticErrInfo.Core.pszMsg);
157 else
158 RTErrInfoAddF(pErrInfo, -rc2, " %Rrc adding cert", rc2);
159 rc = -rc2;
160 }
161
162 CFRelease(hEncodedCert);
163 }
164 }
165
166 CFRelease(hItem);
167 }
168 if (orc != errSecItemNotFound)
169 rc = RTErrInfoAddF(pErrInfo, -VERR_SEARCH_ERROR,
170 " SecKeychainSearchCopyNext failed with %#x", orc);
171 CFRelease(hSearch);
172 }
173 else
174 rc = RTErrInfoAddF(pErrInfo, -VERR_SEARCH_ERROR,
175 " SecKeychainSearchCreateFromAttributes failed with %#x", orc);
176 RT_GCC_NO_WARN_DEPRECATED_END
177 return rc;
178}
179
180
181static int rtCrStoreAddCertsFromNativeKeychainFile(RTCRSTORE hStore, const char *pszKeychain,
182 SecTrustSettingsDomain enmTrustDomain,
183 int rc, PRTERRINFO pErrInfo)
184{
185 /*
186 * Open the keychain and call common worker to do the job.
187 */
188 SecKeychainRef hKeychain;
189
190 RT_GCC_NO_WARN_DEPRECATED_BEGIN
191 OSStatus orc = SecKeychainOpen(pszKeychain, &hKeychain); /* Deprecated since 12.0 */
192 RT_GCC_NO_WARN_DEPRECATED_END
193 if (orc == noErr)
194 {
195 rc = rtCrStoreAddCertsFromNativeKeychain(hStore, hKeychain, enmTrustDomain, rc, pErrInfo);
196
197 CFRelease(hKeychain);
198 }
199 else if (RTFileExists(pszKeychain))
200 rc = RTErrInfoAddF(pErrInfo, -VERR_OPEN_FAILED, " SecKeychainOpen failed with %#x on '%s'", orc, pszKeychain);
201 return rc;
202}
203
204
205static int rtCrStoreAddCertsFromNativeKeystoreDomain(RTCRSTORE hStore, SecPreferencesDomain enmDomain,
206 SecTrustSettingsDomain enmTrustDomain,
207 int rc, PRTERRINFO pErrInfo)
208{
209 /*
210 * Get a list of keystores for this domain and call common worker on each.
211 */
212 CFArrayRef hKeychains;
213 RT_GCC_NO_WARN_DEPRECATED_BEGIN
214 OSStatus orc = SecKeychainCopyDomainSearchList(enmDomain, &hKeychains);
215 RT_GCC_NO_WARN_DEPRECATED_END
216 if (orc == noErr)
217 {
218 CFIndex const cEntries = CFArrayGetCount(hKeychains);
219 for (CFIndex i = 0; i < cEntries; i++)
220 {
221 SecKeychainRef hKeychain = (SecKeychainRef)CFArrayGetValueAtIndex(hKeychains, i);
222 RT_GCC_NO_WARN_DEPRECATED_BEGIN
223 Assert(CFGetTypeID(hKeychain) == SecKeychainGetTypeID());
224 RT_GCC_NO_WARN_DEPRECATED_END
225 CFRetain(hKeychain);
226
227 rc = rtCrStoreAddCertsFromNativeKeychain(hStore, hKeychain, enmTrustDomain, rc, pErrInfo);
228
229 CFRelease(hKeychain);
230 }
231
232 CFRelease(hKeychains);
233 }
234 else
235 rc = RTErrInfoAddF(pErrInfo, -VERR_SEARCH_ERROR,
236 " SecKeychainCopyDomainSearchList failed with %#x on %d", orc, enmDomain);
237 return rc;
238}
239
240
241RTDECL(int) RTCrStoreCreateSnapshotById(PRTCRSTORE phStore, RTCRSTOREID enmStoreId, PRTERRINFO pErrInfo)
242{
243 AssertReturn(enmStoreId > RTCRSTOREID_INVALID && enmStoreId < RTCRSTOREID_END, VERR_INVALID_PARAMETER);
244
245 /*
246 * Create an empty in-memory store.
247 */
248 RTCRSTORE hStore;
249 int rc = RTCrStoreCreateInMem(&hStore, 128);
250 if (RT_SUCCESS(rc))
251 {
252 *phStore = hStore;
253
254 /*
255 * Load the certificates corresponding to the given virtual store ID.
256 */
257 switch (enmStoreId)
258 {
259 case RTCRSTOREID_USER_TRUSTED_CAS_AND_CERTIFICATES:
260 rc = rtCrStoreAddCertsFromNativeKeystoreDomain(hStore, kSecPreferencesDomainUser,
261 kSecTrustSettingsDomainUser, rc, pErrInfo);
262 break;
263
264 case RTCRSTOREID_SYSTEM_TRUSTED_CAS_AND_CERTIFICATES:
265 rc = rtCrStoreAddCertsFromNativeKeystoreDomain(hStore, kSecPreferencesDomainSystem,
266 kSecTrustSettingsDomainSystem, rc, pErrInfo);
267 rc = rtCrStoreAddCertsFromNativeKeychainFile(hStore,
268 "/System/Library/Keychains/SystemRootCertificates.keychain",
269 kSecTrustSettingsDomainSystem, rc, pErrInfo);
270 break;
271
272 default:
273 AssertFailed(); /* implement me */
274 }
275 }
276 else
277 RTErrInfoSet(pErrInfo, rc, "RTCrStoreCreateInMem failed");
278 return rc;
279}
280RT_EXPORT_SYMBOL(RTCrStoreCreateSnapshotById);
281
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette