/* * Copyright (c) 2009 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. The rights granted to you under the License * may not be used to create, or enable the creation or redistribution of, * unlawful or unlicensed copies of an Apple operating system, or to * circumvent, violate, or enable the circumvention or violation of, any * terms of an Apple operating system software license agreement. * * Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ #include #include #include #define kCFBundleGetInfoStringKey CFSTR("CFBundleGetInfoString") #define kNSHumanReadableCopyrightKey CFSTR("NSHumanReadableCopyright") const char *gProgname = NULL; static void usage(void); static void printFormat(void); static char *convert_cfstring(CFStringRef the_string); /****************************************************************************** ******************************************************************************/ static void usage(void) { printf("usage: %s [path to kext]\n\n" "This program validates the copyright string in a kext's info " "dictionary.\n\n", gProgname); printFormat(); } /****************************************************************************** ******************************************************************************/ static void printFormat(void) { fprintf(stderr, "The copyright string should be contained in the NSHumanReadableCopyright key.\n" "It should be of the format:\n" "\tCopyright © [year(s) of publication] Apple Inc. All rights reserved.\n\n" "where [year(s) of publication] is a comma-separated list of years and/or\n" "year ranges, e.g., 2004, 2006-2008. Years must be four digits. Year ranges\n" "may not contain spaces and must use four digits for both years.\n\n" "The following are examples of valid copyright strings:\n" "\tCopyright © 2008 Apple Inc. All rights reserved.\n" "\tCopyright © 2004-2008 Apple Inc. All rights reserved.\n" "\tCopyright © 1998,2000-2002,2004,2006-2008 Apple Inc. All rights reserved.\n"); } /****************************************************************************** ******************************************************************************/ char * convert_cfstring(CFStringRef the_string) { char *result = NULL; CFDataRef the_data = NULL; const UInt8 *data_bytes = NULL; char *converted_string = NULL; u_long converted_len = 0; u_long bytes_copied = 0; the_data = CFStringCreateExternalRepresentation(kCFAllocatorDefault, the_string, kCFStringEncodingUTF8, 0); if (!the_data) { fprintf(stderr, "Failed to convert string\n"); goto finish; } data_bytes = CFDataGetBytePtr(the_data); if (!data_bytes) { fprintf(stderr, "Failed to get converted string bytes\n"); goto finish; } converted_len = strlen((const char *)data_bytes) + 1; // +1 for nul converted_string = malloc(converted_len); if (!converted_string) { fprintf(stderr, "Failed to allocate memory\n"); goto finish; } bytes_copied = strlcpy(converted_string, (const char *) data_bytes, converted_len) + 1; // +1 for nul if (bytes_copied != converted_len) { fprintf(stderr, "Failed to copy converted string\n"); goto finish; } result = converted_string; finish: if (the_data) { CFRelease(the_data); } return result; } /****************************************************************************** ******************************************************************************/ int main(int argc, const char *argv[]) { int result = 1; boolean_t infoCopyrightIsValid = false; boolean_t readableCopyrightIsValid = false; CFURLRef anURL = NULL; // must release CFBundleRef aBundle = NULL; // must release CFDictionaryRef aDict = NULL; // do not release CFStringRef infoCopyrightString = NULL; // do not release CFStringRef readableCopyrightString = NULL; // do not release char *infoStr = NULL; // must free char *readableStr = NULL; // must free gProgname = argv[0]; if (argc != 2) { usage(); goto finish; } anURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (const UInt8 *) argv[1], strlen(argv[1]), /* isDirectory */ FALSE); if (!anURL) { fprintf(stderr, "Can't create path from %s\n", argv[1]); goto finish; } aBundle = CFBundleCreate(kCFAllocatorDefault, anURL); if (!aBundle) { fprintf(stderr, "Can't create bundle at path %s\n", argv[1]); goto finish; } aDict = CFBundleGetInfoDictionary(aBundle); if (!aDict) { fprintf(stderr, "Can't get info dictionary from bundle\n"); goto finish; } infoCopyrightString = CFDictionaryGetValue(aDict, kCFBundleGetInfoStringKey); readableCopyrightString = CFDictionaryGetValue(aDict, kNSHumanReadableCopyrightKey); if (!infoCopyrightString && !readableCopyrightString) { fprintf(stderr, "This kext does not have a value for NSHumanReadableCopyright"); goto finish; } if (infoCopyrightString) { fprintf(stderr, "Warning: This kext has a value for CFBundleGetInfoString.\n" "This key is obsolete, and may be removed from the kext's Info.plist.\n" "It has been replaced by CFBundleVersion and NSHumanReadableCopyright.\n\n"); infoStr = convert_cfstring(infoCopyrightString); if (!infoStr) { goto finish; } infoCopyrightIsValid = kxld_validate_copyright_string(infoStr); } if (readableCopyrightString) { readableStr = convert_cfstring(readableCopyrightString); if (!readableStr) { goto finish; } readableCopyrightIsValid = kxld_validate_copyright_string(readableStr); } if (!readableCopyrightIsValid) { if (infoCopyrightIsValid) { fprintf(stderr, "Warning: The copyright string in NSHumanReadableCopyright is invalid,\n" "but the string in CFBundleGetInfoString is valid. CFBundleGetInfoString is\n" "obsolete. Please migrate your copyright string to NSHumanReadableCopyright.\n\n"); } else { fprintf(stderr, "Error: There is no valid copyright string for this kext.\n\n"); printFormat(); goto finish; } } result = 0; finish: if (anURL) { CFRelease(anURL); } if (aBundle) { CFRelease(aBundle); } if (infoStr) { free(infoStr); } if (readableStr) { free(readableStr); } return result; }