1/* 2 * Copyright (c) 2006-2007 Apple Computer, Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24// 25// csreq - code requirement munging tool for Code Signing 26// 27#include "cs_utils.h" 28#include <Security/CodeSigning.h> 29#include <Security/SecRequirementPriv.h> 30 31using namespace UnixPlusPlus; 32 33 34// 35// Command-line arguments and options 36// 37const char *requirement = NULL; // requirement input 38const char *output = NULL; // output file 39 40static enum { 41 outputCheck, 42 outputText, 43 outputBinary 44} outputType = outputCheck; 45 46static SecCSFlags reqType = kSecCSParseRequirement | kSecCSParseRequirementSet; 47 48 49// 50// Local functions 51// 52static void usage(); 53static SecCSFlags type(const char *t); 54 55 56// 57// Command-line options 58// 59enum { 60 optType 61}; 62 63const struct option options[] = { 64 { "binary", required_argument, NULL, 'b' }, 65 { "check", no_argument, NULL, 'c' }, 66 { "requirements", required_argument, NULL, 'r' }, 67 { "text", no_argument, NULL, 't' }, 68 { "type", required_argument, NULL, optType }, 69 { "verbose", optional_argument, NULL, 'v' }, 70 { } 71}; 72 73 74// 75// codesign [options] bundle-path 76// 77int main(int argc, char *argv[]) 78{ 79 try { 80 //extern int optind; 81 extern char *optarg; 82 int arg, argslot; 83 while (argslot = -1, 84 (arg = getopt_long(argc, argv, "b:ctr:v", options, &argslot)) != -1) 85 switch (arg) { 86 case 'b': 87 outputType = outputBinary; 88 output = optarg; 89 break; 90 case 't': 91 outputType = outputText; 92 break; 93 case 'r': 94 requirement = optarg; 95 break; 96 case 'v': 97 if (argslot < 0) // -v 98 verbose++; 99 else if (optarg) 100 verbose = atoi(optarg); // --verbose=level 101 else 102 verbose++; // --verbose 103 break; 104 105 case optType: 106 reqType = type(optarg); 107 break; 108 109 case '?': 110 usage(); 111 } 112 113 if (requirement == NULL) 114 usage(); 115 116 CFRef<CFTypeRef> req = readRequirement(requirement, reqType); 117 assert(req); 118 119 switch (outputType) { 120 case outputCheck: 121 note(1, "valid"); 122 break; 123 case outputText: 124 { 125 CFRef<CFStringRef> text; 126 MacOSError::check(SecRequirementsCopyString(req, kSecCSDefaultFlags, &text.aref())); 127 string result = cfString(text); 128 if (result.empty()) // empty requirement set 129 result = "/* no requirements in set */\n"; 130 else if (result[result.length()-1] != '\n') 131 result += '\n'; 132 printf("%s", result.c_str()); 133 break; 134 } 135 case outputBinary: 136 { 137 CFRef<CFDataRef> data; 138 if (CFGetTypeID(req) == SecRequirementGetTypeID()) 139 MacOSError::check(SecRequirementCopyData(SecRequirementRef(req.get()), kSecCSDefaultFlags, &data.aref())); 140 else if (CFGetTypeID(req) == CFDataGetTypeID()) 141 data = CFDataRef(req.get()); 142 if (data) 143 AutoFileDesc(output, O_WRONLY | O_TRUNC | O_CREAT).writeAll(CFDataGetBytePtr(data), CFDataGetLength(data)); 144 break; 145 } 146 break; 147 } 148 149 exit(exitSuccess); 150 } catch (...) { 151 diagnose(NULL, exitFailure); 152 } 153} 154 155static void usage() __attribute__((__noreturn__)); 156 157static void usage() 158{ 159 fprintf(stderr, 160 "Usage: csreq [-v] -r requirement # check\n" 161 " csreq [-v] -r requirement -t # text output\n" 162 " csreq [-v] -r requirement -b output # binary output\n" 163 ); 164 exit(exitUsage); 165} 166 167static SecCSFlags type(const char *t) 168{ 169 if (!strncmp("requirement", t, strlen(t))) 170 return kSecCSParseRequirement; 171 else if (!strncmp("internal", t, strlen(t))) 172 return kSecCSParseRequirementSet; 173 else if (!strncmp("group", t, strlen(t))) 174 return kSecCSParseRequirementSet; 175 else if (!strncmp("auto", t, strlen(t))) 176 return kSecCSParseRequirement | kSecCSParseRequirementSet; 177 else { 178 fprintf(stderr, "%s: invalid type\n", t); 179 usage(); 180 } 181} 182