summaryrefslogtreecommitdiffstats
path: root/mDNSResponder/mDNSMacOSX/PreferencePane/BonjourPrefTool/BonjourPrefTool.m
diff options
context:
space:
mode:
Diffstat (limited to 'mDNSResponder/mDNSMacOSX/PreferencePane/BonjourPrefTool/BonjourPrefTool.m')
-rw-r--r--mDNSResponder/mDNSMacOSX/PreferencePane/BonjourPrefTool/BonjourPrefTool.m158
1 files changed, 158 insertions, 0 deletions
diff --git a/mDNSResponder/mDNSMacOSX/PreferencePane/BonjourPrefTool/BonjourPrefTool.m b/mDNSResponder/mDNSMacOSX/PreferencePane/BonjourPrefTool/BonjourPrefTool.m
new file mode 100644
index 00000000..c0d7bb9e
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/PreferencePane/BonjourPrefTool/BonjourPrefTool.m
@@ -0,0 +1,158 @@
+/*
+ *
+ * Copyright (c) 2016 Apple Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import "BonjourPrefTool.h"
+#import "BonjourSCStore.h"
+#import <Security/Security.h>
+#import <dns_sd.h>
+
+#define DYNDNS_KEYCHAIN_DESCRIPTION "Dynamic DNS Key"
+
+#pragma mark - Keychain Funcs
+
+static SecAccessRef
+MyMakeUidAccess(uid_t uid)
+{
+ // make the "uid/gid" ACL subject
+ // this is a CSSM_LIST_ELEMENT chain
+ CSSM_ACL_PROCESS_SUBJECT_SELECTOR selector = {
+ CSSM_ACL_PROCESS_SELECTOR_CURRENT_VERSION, // selector version
+ CSSM_ACL_MATCH_UID, // set mask: match uids (only)
+ uid, // uid to match
+ 0 // gid (not matched here)
+ };
+ CSSM_LIST_ELEMENT subject2 = { NULL, 0, 0, {{0,0,0}} };
+ subject2.Element.Word.Data = (UInt8 *)&selector;
+ subject2.Element.Word.Length = sizeof(selector);
+ CSSM_LIST_ELEMENT subject1 = { &subject2, CSSM_ACL_SUBJECT_TYPE_PROCESS, CSSM_LIST_ELEMENT_WORDID, {{0,0,0}} };
+
+
+ // rights granted (replace with individual list if desired)
+ CSSM_ACL_AUTHORIZATION_TAG rights[] = {
+ CSSM_ACL_AUTHORIZATION_ANY // everything
+ };
+ // owner component (right to change ACL)
+ CSSM_ACL_OWNER_PROTOTYPE owner = {
+ // TypedSubject
+ { CSSM_LIST_TYPE_UNKNOWN, &subject1, &subject2 },
+ // Delegate
+ false
+ };
+ // ACL entries (any number, just one here)
+ CSSM_ACL_ENTRY_INFO acls =
+ {
+ // CSSM_ACL_ENTRY_PROTOTYPE
+ {
+ { CSSM_LIST_TYPE_UNKNOWN, &subject1, &subject2 }, // TypedSubject
+ false, // Delegate
+ { sizeof(rights) / sizeof(rights[0]), rights }, // Authorization rights for this entry
+ { { 0, 0 }, { 0, 0 } }, // CSSM_ACL_VALIDITY_PERIOD
+ "" // CSSM_STRING EntryTag
+ },
+ // CSSM_ACL_HANDLE
+ 0
+ };
+
+ SecAccessRef a = NULL;
+ (void) SecAccessCreateFromOwnerAndACL(&owner, 1, &acls, &a);
+ return a;
+}
+
+static OSStatus
+MyAddDynamicDNSPassword(SecKeychainRef keychain, SecAccessRef a, UInt32 serviceNameLength, const char *serviceName,
+ UInt32 accountNameLength, const char *accountName, UInt32 passwordLength, const void *passwordData)
+{
+ char * description = DYNDNS_KEYCHAIN_DESCRIPTION;
+ UInt32 descriptionLength = strlen(DYNDNS_KEYCHAIN_DESCRIPTION);
+ UInt32 type = 'ddns';
+ UInt32 creator = 'ddns';
+ UInt32 typeLength = sizeof(type);
+ UInt32 creatorLength = sizeof(creator);
+ OSStatus err;
+
+ // set up attribute vector (each attribute consists of {tag, length, pointer})
+ SecKeychainAttribute attrs[] = { { kSecLabelItemAttr, serviceNameLength, (char *)serviceName },
+ { kSecAccountItemAttr, accountNameLength, (char *)accountName },
+ { kSecServiceItemAttr, serviceNameLength, (char *)serviceName },
+ { kSecDescriptionItemAttr, descriptionLength, (char *)description },
+ { kSecTypeItemAttr, typeLength, (UInt32 *)&type },
+ { kSecCreatorItemAttr, creatorLength, (UInt32 *)&creator } };
+ SecKeychainAttributeList attributes = { sizeof(attrs) / sizeof(attrs[0]), attrs };
+
+ err = SecKeychainItemCreateFromContent(kSecGenericPasswordItemClass, &attributes, passwordLength, passwordData, keychain, a, NULL);
+ return err;
+}
+
+static int
+SetKeychainEntry(NSDictionary * secretDictionary)
+// Create a new entry in system keychain, or replace existing
+{
+ CFStringRef keyNameString;
+ CFStringRef domainString;
+ CFStringRef secretString;
+ SecKeychainItemRef item = NULL;
+ int result = 0;
+ char keyname[kDNSServiceMaxDomainName];
+ char domain[kDNSServiceMaxDomainName];
+ char secret[kDNSServiceMaxDomainName];
+
+ keyNameString = (__bridge CFStringRef)[secretDictionary objectForKey:(NSString *)SC_DYNDNS_KEYNAME_KEY];
+ require(keyNameString != NULL, exit);
+
+ domainString = (__bridge CFStringRef)[secretDictionary objectForKey:(NSString *)SC_DYNDNS_DOMAIN_KEY];
+ require(domainString != NULL, exit);
+
+ secretString = (__bridge CFStringRef)[secretDictionary objectForKey:(NSString *)SC_DYNDNS_SECRET_KEY];
+ require(secretString != NULL, exit);
+
+ CFStringGetCString(keyNameString, keyname, kDNSServiceMaxDomainName, kCFStringEncodingUTF8);
+ CFStringGetCString(domainString, domain, kDNSServiceMaxDomainName, kCFStringEncodingUTF8);
+ CFStringGetCString(secretString, secret, kDNSServiceMaxDomainName, kCFStringEncodingUTF8);
+
+ result = SecKeychainSetPreferenceDomain(kSecPreferencesDomainSystem);
+ if (result == noErr)
+ {
+ result = SecKeychainFindGenericPassword(NULL, strlen(domain), domain, 0, NULL, 0, NULL, &item);
+ if (result == noErr)
+ {
+ result = SecKeychainItemDelete(item);
+ if (result != noErr) fprintf(stderr, "SecKeychainItemDelete returned %d\n", result);
+ }
+
+ result = MyAddDynamicDNSPassword(NULL, MyMakeUidAccess(0), strlen(domain), domain, strlen(keyname)+1, keyname, strlen(secret)+1, secret);
+ if (result != noErr) fprintf(stderr, "MyAddDynamicDNSPassword returned %d\n", result);
+ if (item) CFRelease(item);
+ }
+
+exit:
+ return result;
+}
+
+
+@implementation BonjourPrefTool
+
+- (void) setKeychainEntry:(NSDictionary *_Nonnull)secretDictionary withStatus:(void (^ _Nonnull)(OSStatus))status
+{
+ OSStatus result;
+
+ result = SetKeychainEntry (secretDictionary);
+// NSLog(@"setKeychainEntry: %@ result: %d", secretDictionary, result);
+
+ status (result);
+}
+
+@end