]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSMacOSX/PreferencePane/BonjourPrefTool/BonjourPrefTool.m
mDNSResponder-1096.60.2.tar.gz
[apple/mdnsresponder.git] / mDNSMacOSX / PreferencePane / BonjourPrefTool / BonjourPrefTool.m
1 /*
2 *
3 * Copyright (c) 2016 Apple Inc. All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 #import "BonjourPrefTool.h"
19 #import "BonjourSCStore.h"
20 #import <Security/Security.h>
21 #import <dns_sd.h>
22
23 #define DYNDNS_KEYCHAIN_DESCRIPTION "Dynamic DNS Key"
24
25 #pragma mark - Keychain Funcs
26
27 static SecAccessRef
28 MyMakeUidAccess(uid_t uid)
29 {
30 // make the "uid/gid" ACL subject
31 // this is a CSSM_LIST_ELEMENT chain
32 CSSM_ACL_PROCESS_SUBJECT_SELECTOR selector = {
33 CSSM_ACL_PROCESS_SELECTOR_CURRENT_VERSION, // selector version
34 CSSM_ACL_MATCH_UID, // set mask: match uids (only)
35 uid, // uid to match
36 0 // gid (not matched here)
37 };
38 CSSM_LIST_ELEMENT subject2 = { NULL, 0, 0, {{0,0,0}} };
39 subject2.Element.Word.Data = (UInt8 *)&selector;
40 subject2.Element.Word.Length = sizeof(selector);
41 CSSM_LIST_ELEMENT subject1 = { &subject2, CSSM_ACL_SUBJECT_TYPE_PROCESS, CSSM_LIST_ELEMENT_WORDID, {{0,0,0}} };
42
43
44 // rights granted (replace with individual list if desired)
45 CSSM_ACL_AUTHORIZATION_TAG rights[] = {
46 CSSM_ACL_AUTHORIZATION_ANY // everything
47 };
48 // owner component (right to change ACL)
49 CSSM_ACL_OWNER_PROTOTYPE owner = {
50 // TypedSubject
51 { CSSM_LIST_TYPE_UNKNOWN, &subject1, &subject2 },
52 // Delegate
53 false
54 };
55 // ACL entries (any number, just one here)
56 CSSM_ACL_ENTRY_INFO acls =
57 {
58 // CSSM_ACL_ENTRY_PROTOTYPE
59 {
60 { CSSM_LIST_TYPE_UNKNOWN, &subject1, &subject2 }, // TypedSubject
61 false, // Delegate
62 { sizeof(rights) / sizeof(rights[0]), rights }, // Authorization rights for this entry
63 { { 0, 0 }, { 0, 0 } }, // CSSM_ACL_VALIDITY_PERIOD
64 "" // CSSM_STRING EntryTag
65 },
66 // CSSM_ACL_HANDLE
67 0
68 };
69
70 SecAccessRef a = NULL;
71 (void) SecAccessCreateFromOwnerAndACL(&owner, 1, &acls, &a);
72 return a;
73 }
74
75 static OSStatus
76 MyAddDynamicDNSPassword(SecKeychainRef keychain, SecAccessRef a, UInt32 serviceNameLength, const char *serviceName,
77 UInt32 accountNameLength, const char *accountName, UInt32 passwordLength, const void *passwordData)
78 {
79 char * description = DYNDNS_KEYCHAIN_DESCRIPTION;
80 UInt32 descriptionLength = strlen(DYNDNS_KEYCHAIN_DESCRIPTION);
81 UInt32 type = 'ddns';
82 UInt32 creator = 'ddns';
83 UInt32 typeLength = sizeof(type);
84 UInt32 creatorLength = sizeof(creator);
85 OSStatus err;
86
87 // set up attribute vector (each attribute consists of {tag, length, pointer})
88 SecKeychainAttribute attrs[] = { { kSecLabelItemAttr, serviceNameLength, (char *)serviceName },
89 { kSecAccountItemAttr, accountNameLength, (char *)accountName },
90 { kSecServiceItemAttr, serviceNameLength, (char *)serviceName },
91 { kSecDescriptionItemAttr, descriptionLength, (char *)description },
92 { kSecTypeItemAttr, typeLength, (UInt32 *)&type },
93 { kSecCreatorItemAttr, creatorLength, (UInt32 *)&creator } };
94 SecKeychainAttributeList attributes = { sizeof(attrs) / sizeof(attrs[0]), attrs };
95
96 err = SecKeychainItemCreateFromContent(kSecGenericPasswordItemClass, &attributes, passwordLength, passwordData, keychain, a, NULL);
97 return err;
98 }
99
100 static int
101 SetKeychainEntry(NSDictionary * secretDictionary)
102 // Create a new entry in system keychain, or replace existing
103 {
104 CFStringRef keyNameString;
105 CFStringRef domainString;
106 CFStringRef secretString;
107 SecKeychainItemRef item = NULL;
108 int result = 0;
109 char keyname[kDNSServiceMaxDomainName];
110 char domain[kDNSServiceMaxDomainName];
111 char secret[kDNSServiceMaxDomainName];
112
113 keyNameString = (__bridge CFStringRef)[secretDictionary objectForKey:(NSString *)SC_DYNDNS_KEYNAME_KEY];
114 require(keyNameString != NULL, exit);
115
116 domainString = (__bridge CFStringRef)[secretDictionary objectForKey:(NSString *)SC_DYNDNS_DOMAIN_KEY];
117 require(domainString != NULL, exit);
118
119 secretString = (__bridge CFStringRef)[secretDictionary objectForKey:(NSString *)SC_DYNDNS_SECRET_KEY];
120 require(secretString != NULL, exit);
121
122 CFStringGetCString(keyNameString, keyname, kDNSServiceMaxDomainName, kCFStringEncodingUTF8);
123 CFStringGetCString(domainString, domain, kDNSServiceMaxDomainName, kCFStringEncodingUTF8);
124 CFStringGetCString(secretString, secret, kDNSServiceMaxDomainName, kCFStringEncodingUTF8);
125
126 result = SecKeychainSetPreferenceDomain(kSecPreferencesDomainSystem);
127 if (result == noErr)
128 {
129 result = SecKeychainFindGenericPassword(NULL, strlen(domain), domain, 0, NULL, 0, NULL, &item);
130 if (result == noErr)
131 {
132 result = SecKeychainItemDelete(item);
133 if (result != noErr) fprintf(stderr, "SecKeychainItemDelete returned %d\n", result);
134 }
135
136 result = MyAddDynamicDNSPassword(NULL, MyMakeUidAccess(0), strlen(domain), domain, strlen(keyname)+1, keyname, strlen(secret)+1, secret);
137 if (result != noErr) fprintf(stderr, "MyAddDynamicDNSPassword returned %d\n", result);
138 if (item) CFRelease(item);
139 }
140
141 exit:
142 return result;
143 }
144
145
146 @implementation BonjourPrefTool
147
148 - (void) setKeychainEntry:(NSDictionary *_Nonnull)secretDictionary withStatus:(void (^ _Nonnull)(OSStatus))status
149 {
150 OSStatus result;
151
152 result = SetKeychainEntry (secretDictionary);
153 // NSLog(@"setKeychainEntry: %@ result: %d", secretDictionary, result);
154
155 status (result);
156 }
157
158 @end