]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSMacOSX/mdns_objects/mdns_managed_defaults.c
mDNSResponder-1310.80.1.tar.gz
[apple/mdnsresponder.git] / mDNSMacOSX / mdns_objects / mdns_managed_defaults.c
1 /*
2 * Copyright (c) 2020 Apple Inc. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * https://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "mdns_managed_defaults.h"
18
19 #include "mdns_helpers.h"
20
21 #include <CoreUtils/CoreUtils.h>
22
23 //======================================================================================================================
24 // MARK: - Internals
25
26 // Managed defaults is currently only for iOS-like OSes.
27 #if !defined(TARGET_OS_IOS_LIKE_DEVICE)
28 #error "TARGET_OS_IOS_LIKE_DEVICE is not defined"
29 #endif
30
31 MDNS_LOG_CATEGORY_DEFINE(managed_defaults, "managed_defaults");
32
33 //======================================================================================================================
34 // MARK: - Local Prototypes
35
36 #if TARGET_OS_IOS_LIKE_DEVICE
37 static CFURLRef
38 _mdns_managed_defaults_create_domain_url(const char *domain, OSStatus *out_error);
39
40 static CFReadStreamRef
41 _mdns_managed_defaults_create_opened_read_stream(CFURLRef url, OSStatus *out_error);
42
43 static CFDictionaryRef
44 _mdns_managed_defaults_create_dictionary_from_stream(CFReadStreamRef stream, OSStatus *out_error);
45 #endif
46
47 static int64_t
48 _mdns_managed_defaults_get_int64(CFDictionaryRef defaults, CFStringRef key, OSStatus *out_error);
49
50 #define _assign_null_safe(PTR, VALUE) \
51 do { \
52 if ((PTR)) { \
53 *(PTR) = (VALUE); \
54 } \
55 } while(0)
56
57 //======================================================================================================================
58 // MARK: - Public Functions
59
60 #if TARGET_OS_IOS_LIKE_DEVICE
61 CFDictionaryRef
62 mdns_managed_defaults_create(const char * const domain, OSStatus * const out_error)
63 {
64 CFDictionaryRef result = NULL;
65 OSStatus err, tmp_err;
66 CFURLRef url = _mdns_managed_defaults_create_domain_url(domain, &tmp_err);
67 require_action_quiet(url, exit, err = tmp_err; os_log_error(_mdns_managed_defaults_log(),
68 "Failed to create URL -- domain: %{public}s, error: %{mdns:err}ld", domain, (long)err));
69
70 CFReadStreamRef stream = _mdns_managed_defaults_create_opened_read_stream(url, &tmp_err);
71 require_action_quiet(stream, exit, err = tmp_err; os_log_error(_mdns_managed_defaults_log(),
72 "Failed to create read stream -- url: %{public}@, error: %{mdns:err}ld", url, (long)err));
73
74 CFDictionaryRef plist = _mdns_managed_defaults_create_dictionary_from_stream(stream, &tmp_err);
75 ForgetCF(&stream);
76 require_action_quiet(plist, exit, err = tmp_err; os_log_error(_mdns_managed_defaults_log(),
77 "Failed to create dictionary -- url: %{public}@, error: %{mdns:err}ld", url, (long)err));
78
79 result = plist;
80 err = kNoErr;
81
82 exit:
83 ForgetCF(&url);
84 _assign_null_safe(out_error, err);
85 return result;
86 }
87 #else
88 CFDictionaryRef
89 mdns_managed_defaults_create(__unused const char * const domain, OSStatus * const out_error)
90 {
91 os_log_info(_mdns_managed_defaults_log(), "Managed defaults is not supported on this OS");
92 _assign_null_safe(out_error, kUnsupportedErr);
93 return NULL;
94 }
95 #endif // TARGET_OS_IOS_LIKE_DEVICE
96
97 //======================================================================================================================
98
99 int
100 mdns_managed_defaults_get_int_clamped(const CFDictionaryRef defaults, const CFStringRef key, const int fallback_value,
101 OSStatus * const out_error)
102 {
103 int result;
104 OSStatus err;
105 const int64_t value = _mdns_managed_defaults_get_int64(defaults, key, &err);
106 require_noerr_action_quiet(err, exit, result = fallback_value);
107
108 result = (int)Clamp(value, INT_MIN, INT_MAX);
109
110 exit:
111 _assign_null_safe(out_error, err);
112 return result;
113 }
114
115 //======================================================================================================================
116 // MARK: - Private Functions
117
118 #if TARGET_OS_IOS_LIKE_DEVICE
119 static CFURLRef
120 _mdns_managed_defaults_create_domain_url(const char * const domain, OSStatus * const out_error)
121 {
122 OSStatus err;
123 CFURLRef result = NULL;
124 char *path_cstr = NULL;
125 asprintf(&path_cstr, "/Library/Managed Preferences/mobile/%s.plist", domain);
126 require_action_quiet(path_cstr, exit, err = kNoMemoryErr);
127
128 CFStringRef path = CFStringCreateWithCStringNoCopy(NULL, path_cstr, kCFStringEncodingUTF8, kCFAllocatorMalloc);
129 require_action_quiet(path, exit, ForgetMem(&path_cstr); err = kNoResourcesErr);
130 path_cstr = NULL;
131
132 CFURLRef url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, path, kCFURLPOSIXPathStyle, false);
133 ForgetCF(&path);
134 require_action_quiet(url, exit, err = kNoResourcesErr);
135
136 result = url;
137 err = kNoErr;
138
139 exit:
140 _assign_null_safe(out_error, err);
141 return result;
142 }
143
144 //======================================================================================================================
145
146 static CFReadStreamRef
147 _mdns_managed_defaults_create_opened_read_stream(const CFURLRef url, OSStatus * const out_error)
148 {
149 OSStatus err;
150 CFReadStreamRef result = NULL;
151 CFReadStreamRef stream = CFReadStreamCreateWithFile(kCFAllocatorDefault, url);
152 require_action_quiet(stream, exit, err = kNoResourcesErr);
153
154 const Boolean ok = CFReadStreamOpen(stream);
155 require_action_quiet(ok, exit, ForgetCF(&stream); err = kOpenErr);
156
157 result = stream;
158 err = kNoErr;
159
160 exit:
161 _assign_null_safe(out_error, err);
162 return result;
163 }
164
165 //======================================================================================================================
166
167 static OSStatus
168 _mdns_get_cferror_code(CFErrorRef error);
169
170 static CFDictionaryRef
171 _mdns_managed_defaults_create_dictionary_from_stream(const CFReadStreamRef stream, OSStatus * const out_error)
172 {
173 OSStatus err;
174 CFErrorRef error = NULL;
175 CFDictionaryRef result = NULL;
176 CFPropertyListRef plist = CFPropertyListCreateWithStream(NULL, stream, 0, kCFPropertyListImmutable, NULL, &error);
177 require_action_quiet(plist, exit, err = _mdns_get_cferror_code(error); os_log_error(_mdns_managed_defaults_log(),
178 "CFPropertyListCreateWithStream failed: %{public}@", error));
179 require_action_quiet(CFIsType(plist, CFDictionary), exit, ForgetCF(&plist); err = kTypeErr);
180
181 result = plist;
182 err = kNoErr;
183
184 exit:
185 ForgetCF(&error);
186 _assign_null_safe(out_error, err);
187 return result;
188 }
189
190 static OSStatus
191 _mdns_get_cferror_code(const CFErrorRef error)
192 {
193 return (error ? ((OSStatus)CFErrorGetCode(error)) : kUnknownErr);
194 }
195 #endif // TARGET_OS_IOS_LIKE_DEVICE
196
197 //======================================================================================================================
198
199 static int64_t
200 _mdns_managed_defaults_get_int64(const CFDictionaryRef defaults, const CFStringRef key, OSStatus * const out_error)
201 {
202 OSStatus err;
203 int64_t result = 0;
204 const CFNumberRef number = CFDictionaryGetValue(defaults, key);
205 require_action_quiet(number != NULL, exit, err = kNotFoundErr);
206 require_action_quiet(CFIsType(number, CFNumber), exit, err = kTypeErr);
207 require_action_quiet(!CFNumberIsFloatType(number), exit, err = kTypeErr);
208
209 int64_t value;
210 const Boolean ok = CFNumberGetValue(number, kCFNumberSInt64Type, &value);
211 require_action_quiet(ok, exit, err = kUnknownErr);
212
213 result = value;
214 err = kNoErr;
215
216 exit:
217 _assign_null_safe(out_error, err);
218 return result;
219 }