VirtualBox

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

Last change on this file since 100765 was 100108, checked in by vboxsync, 18 months ago

*: Fix build issues when setting VBOX_WITH_WARNINGS_AS_ERRORS=1 on darwin.arm64 and make it a default, bugref:10469

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.4 KB
Line 
1/* $Id: RTCrStoreCreateSnapshotById-darwin.cpp 100108 2023-06-07 20:05: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/* HACK ALERT! Shut up those deprecated messages on SecKeychainSearchCreateFromAttributes and SecKeychainSearchCopyNext. */
49#include <CoreFoundation/CoreFoundation.h>
50#undef DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
51#define DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
52
53#include <Security/Security.h>
54
55
56/**
57 * Checks the trust settings of the certificate.
58 *
59 * @returns true if not out-right distructed, otherwise false.
60 * @param hCert The certificate.
61 * @param enmTrustDomain The trust settings domain to check relative to.
62 */
63static bool rtCrStoreIsDarwinCertTrustworthy(SecCertificateRef hCert, SecTrustSettingsDomain enmTrustDomain)
64{
65 bool fResult = true;
66 CFArrayRef hTrustSettings;
67 OSStatus orc = SecTrustSettingsCopyTrustSettings(hCert, enmTrustDomain, &hTrustSettings);
68 if (orc == noErr)
69 {
70 CFIndex const cTrustSettings = CFArrayGetCount(hTrustSettings);
71 for (CFIndex i = 0; i < cTrustSettings; i++)
72 {
73 CFDictionaryRef hDict = (CFDictionaryRef)CFArrayGetValueAtIndex(hTrustSettings, i);
74 AssertContinue(CFGetTypeID(hDict) == CFDictionaryGetTypeID());
75
76 CFNumberRef hNum = (CFNumberRef)CFDictionaryGetValue(hDict, kSecTrustSettingsResult);
77 if (hNum)
78 {
79 AssertContinue(CFGetTypeID(hNum) == CFNumberGetTypeID());
80 SInt32 iNum;
81 if (CFNumberGetValue(hNum, kCFNumberSInt32Type, &iNum))
82 {
83 if (iNum == kSecTrustSettingsResultDeny)
84 {
85 fResult = false;
86 break;
87 }
88 }
89 /* No need to release hNum (get rule). */
90 }
91 /* No need to release hDict (get rule). */
92 }
93 CFRelease(hTrustSettings);
94 }
95 else if (orc != errSecItemNotFound)
96 {
97 AssertFailed();
98 fResult = false;
99 }
100 return fResult;
101}
102
103
104static int rtCrStoreAddCertsFromNativeKeychain(RTCRSTORE hStore, SecKeychainRef hKeychain, SecTrustSettingsDomain enmTrustDomain,
105 int rc, PRTERRINFO pErrInfo)
106{
107 /** @todo The SecKeychainSearchCreateFromAttributes and
108 * SecKeychainSearchCopyNext APIs have been officially deprecated since 10.7
109 * according to the header files. However, the perferred API,
110 * SecItemCopyMatching (and possibly SecTrustCopyAnchorCertificates) would
111 * require a larger rewrite here and that's just not worth it right now. We can
112 * do that should these APIs be removed (unlikely given the amount of grep hits
113 * in the public 10.15.3 sources). */
114
115 /*
116 * Enumerate the certificates in the keychain.
117 */
118 RT_GCC_NO_WARN_DEPRECATED_BEGIN
119 SecKeychainSearchRef hSearch;
120 OSStatus orc = SecKeychainSearchCreateFromAttributes(hKeychain, kSecCertificateItemClass, NULL, &hSearch);
121 if (orc == noErr)
122 {
123 SecKeychainItemRef hItem;
124 while ((orc = SecKeychainSearchCopyNext(hSearch, &hItem)) == noErr)
125 {
126 Assert(CFGetTypeID(hItem) == SecCertificateGetTypeID());
127 SecCertificateRef hCert = (SecCertificateRef)hItem;
128
129 /*
130 * Check if the current certificate is at all trusted, skip it if it's isn't.
131 */
132 if (rtCrStoreIsDarwinCertTrustworthy(hCert, enmTrustDomain))
133 {
134 /*
135 * Get the certificate data.
136 */
137 CFDataRef hEncodedCert = SecCertificateCopyData(hCert);
138 Assert(hEncodedCert);
139 if (hEncodedCert)
140 {
141 CFIndex cbEncoded = CFDataGetLength(hEncodedCert);
142 const uint8_t *pbEncoded = CFDataGetBytePtr(hEncodedCert);
143
144 RTERRINFOSTATIC StaticErrInfo;
145 int rc2 = RTCrStoreCertAddEncoded(hStore, RTCRCERTCTX_F_ENC_X509_DER | RTCRCERTCTX_F_ADD_IF_NOT_FOUND,
146 pbEncoded, cbEncoded, RTErrInfoInitStatic(&StaticErrInfo));
147 if (RT_FAILURE(rc2))
148 {
149 if (RTErrInfoIsSet(&StaticErrInfo.Core))
150 RTErrInfoAddF(pErrInfo, -rc2, " %s", StaticErrInfo.Core.pszMsg);
151 else
152 RTErrInfoAddF(pErrInfo, -rc2, " %Rrc adding cert", rc2);
153 rc = -rc2;
154 }
155
156 CFRelease(hEncodedCert);
157 }
158 }
159
160 CFRelease(hItem);
161 }
162 if (orc != errSecItemNotFound)
163 rc = RTErrInfoAddF(pErrInfo, -VERR_SEARCH_ERROR,
164 " SecKeychainSearchCopyNext failed with %#x", orc);
165 CFRelease(hSearch);
166 }
167 else
168 rc = RTErrInfoAddF(pErrInfo, -VERR_SEARCH_ERROR,
169 " SecKeychainSearchCreateFromAttributes failed with %#x", orc);
170 RT_GCC_NO_WARN_DEPRECATED_END
171 return rc;
172}
173
174
175static int rtCrStoreAddCertsFromNativeKeychainFile(RTCRSTORE hStore, const char *pszKeychain,
176 SecTrustSettingsDomain enmTrustDomain,
177 int rc, PRTERRINFO pErrInfo)
178{
179 /*
180 * Open the keychain and call common worker to do the job.
181 */
182 SecKeychainRef hKeychain;
183
184 RT_GCC_NO_WARN_DEPRECATED_BEGIN
185 OSStatus orc = SecKeychainOpen(pszKeychain, &hKeychain); /* Deprecated since 12.0 */
186 RT_GCC_NO_WARN_DEPRECATED_END
187 if (orc == noErr)
188 {
189 rc = rtCrStoreAddCertsFromNativeKeychain(hStore, hKeychain, enmTrustDomain, rc, pErrInfo);
190
191 CFRelease(hKeychain);
192 }
193 else if (RTFileExists(pszKeychain))
194 rc = RTErrInfoAddF(pErrInfo, -VERR_OPEN_FAILED, " SecKeychainOpen failed with %#x on '%s'", orc, pszKeychain);
195 return rc;
196}
197
198
199static int rtCrStoreAddCertsFromNativeKeystoreDomain(RTCRSTORE hStore, SecPreferencesDomain enmDomain,
200 SecTrustSettingsDomain enmTrustDomain,
201 int rc, PRTERRINFO pErrInfo)
202{
203 /*
204 * Get a list of keystores for this domain and call common worker on each.
205 */
206 CFArrayRef hKeychains;
207 OSStatus orc = SecKeychainCopyDomainSearchList(enmDomain, &hKeychains);
208 if (orc == noErr)
209 {
210 CFIndex const cEntries = CFArrayGetCount(hKeychains);
211 for (CFIndex i = 0; i < cEntries; i++)
212 {
213 SecKeychainRef hKeychain = (SecKeychainRef)CFArrayGetValueAtIndex(hKeychains, i);
214 Assert(CFGetTypeID(hKeychain) == SecKeychainGetTypeID());
215 CFRetain(hKeychain);
216
217 rc = rtCrStoreAddCertsFromNativeKeychain(hStore, hKeychain, enmTrustDomain, rc, pErrInfo);
218
219 CFRelease(hKeychain);
220 }
221
222 CFRelease(hKeychains);
223 }
224 else
225 rc = RTErrInfoAddF(pErrInfo, -VERR_SEARCH_ERROR,
226 " SecKeychainCopyDomainSearchList failed with %#x on %d", orc, enmDomain);
227 return rc;
228}
229
230
231RTDECL(int) RTCrStoreCreateSnapshotById(PRTCRSTORE phStore, RTCRSTOREID enmStoreId, PRTERRINFO pErrInfo)
232{
233 AssertReturn(enmStoreId > RTCRSTOREID_INVALID && enmStoreId < RTCRSTOREID_END, VERR_INVALID_PARAMETER);
234
235 /*
236 * Create an empty in-memory store.
237 */
238 RTCRSTORE hStore;
239 int rc = RTCrStoreCreateInMem(&hStore, 128);
240 if (RT_SUCCESS(rc))
241 {
242 *phStore = hStore;
243
244 /*
245 * Load the certificates corresponding to the given virtual store ID.
246 */
247 switch (enmStoreId)
248 {
249 case RTCRSTOREID_USER_TRUSTED_CAS_AND_CERTIFICATES:
250 rc = rtCrStoreAddCertsFromNativeKeystoreDomain(hStore, kSecPreferencesDomainUser,
251 kSecTrustSettingsDomainUser, rc, pErrInfo);
252 break;
253
254 case RTCRSTOREID_SYSTEM_TRUSTED_CAS_AND_CERTIFICATES:
255 rc = rtCrStoreAddCertsFromNativeKeystoreDomain(hStore, kSecPreferencesDomainSystem,
256 kSecTrustSettingsDomainSystem, rc, pErrInfo);
257 rc = rtCrStoreAddCertsFromNativeKeychainFile(hStore,
258 "/System/Library/Keychains/SystemRootCertificates.keychain",
259 kSecTrustSettingsDomainSystem, rc, pErrInfo);
260 break;
261
262 default:
263 AssertFailed(); /* implement me */
264 }
265 }
266 else
267 RTErrInfoSet(pErrInfo, rc, "RTCrStoreCreateInMem failed");
268 return rc;
269}
270RT_EXPORT_SYMBOL(RTCrStoreCreateSnapshotById);
271
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