diff options
Diffstat (limited to 'mDNSResponder/mDNSMacOSX/PreferencePane/ddnswriteconfig.m')
-rw-r--r-- | mDNSResponder/mDNSMacOSX/PreferencePane/ddnswriteconfig.m | 462 |
1 files changed, 0 insertions, 462 deletions
diff --git a/mDNSResponder/mDNSMacOSX/PreferencePane/ddnswriteconfig.m b/mDNSResponder/mDNSMacOSX/PreferencePane/ddnswriteconfig.m deleted file mode 100644 index 8e64fc46..00000000 --- a/mDNSResponder/mDNSMacOSX/PreferencePane/ddnswriteconfig.m +++ /dev/null @@ -1,462 +0,0 @@ -/* - File: ddnswriteconfig.m - - Abstract: Setuid root tool invoked by Preference Pane to perform - privileged accesses to system configuration preferences and the system keychain. - Invoked by PrivilegedOperations.c. - - Copyright: (c) Copyright 2005 Apple Computer, Inc. All rights reserved. - - Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. - ("Apple") in consideration of your agreement to the following terms, and your - use, installation, modification or redistribution of this Apple software - constitutes acceptance of these terms. If you do not agree with these terms, - please do not use, install, modify or redistribute this Apple software. - - In consideration of your agreement to abide by the following terms, and subject - to these terms, Apple grants you a personal, non-exclusive license, under Apple's - copyrights in this original Apple software (the "Apple Software"), to use, - reproduce, modify and redistribute the Apple Software, with or without - modifications, in source and/or binary forms; provided that if you redistribute - the Apple Software in its entirety and without modifications, you must retain - this notice and the following text and disclaimers in all such redistributions of - the Apple Software. Neither the name, trademarks, service marks or logos of - Apple Computer, Inc. may be used to endorse or promote products derived from the - Apple Software without specific prior written permission from Apple. Except as - expressly stated in this notice, no other rights or licenses, express or implied, - are granted by Apple herein, including but not limited to any patent rights that - may be infringed by your derivative works or by other works in which the Apple - Software may be incorporated. - - The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO - WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED - WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN - COMBINATION WITH YOUR PRODUCTS. - - IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION - OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT - (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN - ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - - -#import "PrivilegedOperations.h" -#import "ConfigurationRights.h" - -#import <stdio.h> -#import <stdint.h> -#import <stdlib.h> -#import <unistd.h> -#import <fcntl.h> -#import <errno.h> -#import <sys/types.h> -#import <sys/stat.h> -#import <sys/mman.h> -#import <mach-o/dyld.h> -#import <dns_sd.h> -#import <AssertMacros.h> -#import <Security/Security.h> -#import <CoreServices/CoreServices.h> -#import <CoreFoundation/CoreFoundation.h> -#import <SystemConfiguration/SystemConfiguration.h> -#import <Foundation/Foundation.h> - - -static AuthorizationRef gAuthRef = 0; - -static OSStatus -WriteArrayToDynDNS(CFStringRef arrayKey, CFArrayRef domainArray) -{ - SCPreferencesRef store; - OSStatus err = noErr; - CFDictionaryRef origDict; - CFMutableDictionaryRef dict = NULL; - Boolean result; - CFStringRef scKey = CFSTR("/System/Network/DynamicDNS"); - - - // Add domain to the array member ("arrayKey") of the DynamicDNS dictionary - // Will replace duplicate, at head of list - // At this point, we only support a single-item list - store = SCPreferencesCreate(NULL, CFSTR("com.apple.preference.bonjour"), NULL); - require_action(store != NULL, SysConfigErr, err=paramErr;); - require_action(true == SCPreferencesLock( store, true), LockFailed, err=coreFoundationUnknownErr;); - - origDict = SCPreferencesPathGetValue(store, scKey); - if (origDict) - { - dict = CFDictionaryCreateMutableCopy(NULL, 0, origDict); - } - - if (!dict) - { - dict = CFDictionaryCreateMutable(NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - } - require_action( dict != NULL, NoDict, err=memFullErr;); - - if (CFArrayGetCount(domainArray) > 0) - { - CFDictionarySetValue(dict, arrayKey, domainArray); - } - else - { - CFDictionaryRemoveValue(dict, arrayKey); - } - - result = SCPreferencesPathSetValue(store, scKey, dict); - require_action(result, SCError, err=kernelPrivilegeErr;); - - result = SCPreferencesCommitChanges(store); - require_action(result, SCError, err=kernelPrivilegeErr;); - result = SCPreferencesApplyChanges(store); - require_action(result, SCError, err=kernelPrivilegeErr;); - -SCError: - CFRelease(dict); -NoDict: - SCPreferencesUnlock(store); -LockFailed: - CFRelease(store); -SysConfigErr: - return err; -} - - -static int -readTaggedBlock(int fd, u_int32_t *pTag, u_int32_t *pLen, char **ppBuff) -// Read tag, block len and block data from stream and return. Dealloc *ppBuff via free(). -{ - ssize_t num; - u_int32_t tag, len; // Don't use ssize_t because that's different on 32- vs. 64-bit - int result = 0; - - num = read(fd, &tag, sizeof tag); - require_action(num == sizeof tag, GetTagFailed, result = -1;); - num = read(fd, &len, sizeof len); - require_action(num == sizeof len, GetLenFailed, result = -1;); - - *ppBuff = (char*) malloc( len); - require_action(*ppBuff != NULL, AllocFailed, result = -1;); - - num = read(fd, *ppBuff, len); - if (num == (ssize_t)len) - { - *pTag = tag; - *pLen = len; - } - else - { - free(*ppBuff); - result = -1; - } - -AllocFailed: -GetLenFailed: -GetTagFailed: - return result; -} - - - -static int -SetAuthInfo( int fd) -{ - int result = 0; - u_int32_t tag, len; - char *p; - - result = readTaggedBlock( fd, &tag, &len, &p); - require( result == 0, ReadParamsFailed); - require( len == sizeof(AuthorizationExternalForm), ReadParamsFailed); - require( len == kAuthorizationExternalFormLength, ReadParamsFailed); - - if (gAuthRef != 0) - { - (void) AuthorizationFree(gAuthRef, kAuthorizationFlagDefaults); - gAuthRef = 0; - } - - result = AuthorizationCreateFromExternalForm((AuthorizationExternalForm*) p, &gAuthRef); - - free( p); -ReadParamsFailed: - return result; -} - - -static int -HandleWriteDomain(int fd, int domainType) -{ - CFArrayRef domainArray; - CFDataRef domainData; - int result = 0; - u_int32_t tag, len; - char *p; - - AuthorizationItem scAuth = { UPDATE_SC_RIGHT, 0, NULL, 0 }; - AuthorizationRights authSet = { 1, &scAuth }; - - if (noErr != (result = AuthorizationCopyRights(gAuthRef, &authSet, NULL, (AuthorizationFlags)0, NULL))) - return result; - - result = readTaggedBlock(fd, &tag, &len, &p); - require(result == 0, ReadParamsFailed); - - domainData = CFDataCreate(NULL, (UInt8 *)p, len); - domainArray = (CFArrayRef)[NSUnarchiver unarchiveObjectWithData:(NSData *)domainData]; - CFRelease(domainData); - free(p); - - if (domainType) - { - result = WriteArrayToDynDNS(SC_DYNDNS_REGDOMAINS_KEY, domainArray); - } - else - { - result = WriteArrayToDynDNS(SC_DYNDNS_BROWSEDOMAINS_KEY, domainArray); - } - -ReadParamsFailed: - return result; -} - - -static int -HandleWriteHostname(int fd) -{ - CFArrayRef domainArray; - CFDataRef domainData; - int result = 0; - u_int32_t tag, len; - char *p; - - AuthorizationItem scAuth = { UPDATE_SC_RIGHT, 0, NULL, 0 }; - AuthorizationRights authSet = { 1, &scAuth }; - - if (noErr != (result = AuthorizationCopyRights(gAuthRef, &authSet, NULL, (AuthorizationFlags) 0, NULL))) - return result; - - result = readTaggedBlock(fd, &tag, &len, &p); - require(result == 0, ReadParamsFailed); - - domainData = CFDataCreate(NULL, (const UInt8 *)p, len); - domainArray = (CFArrayRef)[NSUnarchiver unarchiveObjectWithData:(NSData *)domainData]; - result = WriteArrayToDynDNS(SC_DYNDNS_HOSTNAMES_KEY, domainArray); - CFRelease(domainData); - free(p); - -ReadParamsFailed: - return result; -} - - -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(int fd) -// Create a new entry in system keychain, or replace existing -{ - CFDataRef secretData; - CFDictionaryRef secretDictionary; - CFStringRef keyNameString; - CFStringRef domainString; - CFStringRef secretString; - SecKeychainItemRef item = NULL; - int result = 0; - u_int32_t tag, len; - char *p; - char keyname[kDNSServiceMaxDomainName]; - char domain[kDNSServiceMaxDomainName]; - char secret[kDNSServiceMaxDomainName]; - - AuthorizationItem kcAuth = { EDIT_SYS_KEYCHAIN_RIGHT, 0, NULL, 0 }; - AuthorizationRights authSet = { 1, &kcAuth }; - - if (noErr != (result = AuthorizationCopyRights(gAuthRef, &authSet, NULL, (AuthorizationFlags)0, NULL))) - return result; - - result = readTaggedBlock(fd, &tag, &len, &p); - require_noerr(result, ReadParamsFailed); - - secretData = CFDataCreate(NULL, (UInt8 *)p, len); - secretDictionary = (CFDictionaryRef)[NSUnarchiver unarchiveObjectWithData:(NSData *)secretData]; - CFRelease(secretData); - free(p); - - keyNameString = (CFStringRef)CFDictionaryGetValue(secretDictionary, SC_DYNDNS_KEYNAME_KEY); - assert(keyNameString != NULL); - - domainString = (CFStringRef)CFDictionaryGetValue(secretDictionary, SC_DYNDNS_DOMAIN_KEY); - assert(domainString != NULL); - - secretString = (CFStringRef)CFDictionaryGetValue(secretDictionary, SC_DYNDNS_SECRET_KEY); - assert(secretString != NULL); - - 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); - } - -ReadParamsFailed: - return result; -} - - -int main( int argc, char **argv) -/* argv[0] is the exec path; argv[1] is a fd for input data; argv[2]... are operation codes. - The tool supports the following operations: - V -- exit with status PRIV_OP_TOOL_VERS - A -- read AuthInfo from input pipe - Wd -- write registration domain to dynamic store - Wb -- write browse domain to dynamic store - Wh -- write hostname to dynamic store - Wk -- write keychain entry for given account name -*/ -{ - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - int commFD = -1, iArg, result = 0; - - if ( 0 != seteuid( 0)) - return -1; - - if ( argc == 3 && 0 == strcmp( argv[2], "V")) - return PRIV_OP_TOOL_VERS; - - if ( argc > 1) - { - commFD = strtol( argv[1], NULL, 0); - lseek( commFD, 0, SEEK_SET); - } - for ( iArg = 2; iArg < argc && result == 0; iArg++) - { - if ( 0 == strcmp( "A", argv[ iArg])) // get auth info - { - result = SetAuthInfo( commFD); - } - else if ( 0 == strcmp( "Wd", argv[ iArg])) // Write registration domain - { - result = HandleWriteDomain( commFD, 1); - } - else if ( 0 == strcmp( "Wb", argv[ iArg])) // Write browse domain - { - result = HandleWriteDomain( commFD, 0); - } - else if ( 0 == strcmp( "Wh", argv[ iArg])) // Write hostname - { - result = HandleWriteHostname( commFD); - } - else if ( 0 == strcmp( "Wk", argv[ iArg])) // Write keychain entry - { - result = SetKeychainEntry( commFD); - } - } - [pool release]; - return result; -} - -// Note: The C preprocessor stringify operator ('#') makes a string from its argument, without macro expansion -// e.g. If "version" is #define'd to be "4", then STRINGIFY_AWE(version) will return the string "version", not "4" -// To expand "version" to its value before making the string, use STRINGIFY(version) instead -#define STRINGIFY_ARGUMENT_WITHOUT_EXPANSION(s) #s -#define STRINGIFY(s) STRINGIFY_ARGUMENT_WITHOUT_EXPANSION(s) - -// NOT static -- otherwise the compiler may optimize it out -// The "@(#) " pattern is a special prefix the "what" command looks for -const char VersionString_SCCS[] = "@(#) ddnswriteconfig " STRINGIFY(mDNSResponderVersion) " (" __DATE__ " " __TIME__ ")"; - -#if _BUILDING_XCODE_PROJECT_ -// If the process crashes, then this string will be magically included in the automatically-generated crash log -const char *__crashreporter_info__ = VersionString_SCCS + 5; -asm(".desc ___crashreporter_info__, 0x10"); -#endif |