1/*
2 * Copyright (c) 2007-2009,2013-2014 Apple 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
26#include <stdio.h>
27#include <CoreFoundation/CoreFoundation.h>
28#include <Security/SecTask.h>
29#include <Security/SecEntitlements.h>
30#include <AssertMacros.h>
31#include <TargetConditionals.h>
32#include <sys/sysctl.h>
33
34#include "utilities/SecCFRelease.h"
35
36#include "sectask_regressions.h"
37
38/* IPC stuff:
39
40 This is a hack to get our own audittoken:
41 We send a simple request with no argument to our mach port.
42 The mach port callback copy the audittoken to a global.
43 */
44
45#include <mach/mach.h>
46#include <mach/message.h>
47#include "sectask_ipc.h"
48
49static audit_token_t g_self_audittoken = {{0}};
50
51kern_return_t sectask_server_request(mach_port_t receiver,
52        audit_token_t auditToken);
53kern_return_t sectask_server_request(mach_port_t receiver,
54        audit_token_t auditToken)
55{
56    memcpy(&g_self_audittoken, &auditToken, sizeof(g_self_audittoken));
57
58    CFRunLoopStop(CFRunLoopGetCurrent());
59
60    return 0;
61}
62
63extern boolean_t sectask_ipc_server(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP);
64
65union max_msg_size_union {
66    union __RequestUnion__sectask_client_sectask_ipc_subsystem reply;
67};
68
69static uint8_t reply_buffer[sizeof(union max_msg_size_union) + MAX_TRAILER_SIZE];
70
71static void server_callback(CFMachPortRef port, void *msg, CFIndex size, void *info)
72{
73    mach_msg_header_t *message = (mach_msg_header_t *)msg;
74    mach_msg_header_t *reply = (mach_msg_header_t *)reply_buffer;
75
76    sectask_ipc_server(message, reply);
77
78}
79
80static
81void init_self_audittoken(void)
82{
83    /* create a mach port and an event source */
84    CFMachPortRef server_port = CFMachPortCreate (NULL, server_callback, NULL, false);
85    CFRunLoopSourceRef server_source = CFMachPortCreateRunLoopSource(NULL, server_port, 0/*order*/);
86
87    /* add the source to the current run loop */
88    CFRunLoopAddSource(CFRunLoopGetCurrent(), server_source, kCFRunLoopDefaultMode);
89    CFRelease(server_source);
90
91    /* Send the request */
92    sectask_client_request(CFMachPortGetPort(server_port));
93
94    /* Run the loop to process the message */
95    CFRunLoopRun();
96
97    /* done */
98    CFRelease(server_port);
99
100}
101
102static
103CFStringRef copyProcName(pid_t pid) {
104    const char *task_name;
105    int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
106    struct kinfo_proc kp;
107    size_t len = sizeof(kp);
108    if (sysctl(mib, 4, &kp, &len, NULL, 0) == -1 || len == 0)
109        task_name = strerror(errno);
110    else
111        task_name = kp.kp_proc.p_comm;
112    return CFStringCreateWithCString(kCFAllocatorDefault, task_name, kCFStringEncodingASCII);
113}
114
115/* Actual test code */
116
117int sectask_10_sectask_self(int argc, char *const *argv)
118{
119    SecTaskRef task=NULL;
120    CFStringRef appId=NULL;
121    CFStringRef signingIdentifier=NULL;
122    plan_tests(6);
123
124    ok(task=SecTaskCreateFromSelf(kCFAllocatorDefault), "SecTaskCreateFromSelf");
125    require(task, out);
126
127    /* TODO: remove the todo once xcode signs simulator binaries */
128SKIP: {
129#if TARGET_IPHONE_SIMULATOR
130        todo("no entitlements in the simulator binaries yet, until <rdar://problem/12194625>");
131#endif
132        ok(appId=SecTaskCopyValueForEntitlement(task, kSecEntitlementApplicationIdentifier, NULL), "SecTaskCopyValueForEntitlement");
133        skip("appId is NULL", 1, appId);
134        ok(CFEqual(appId, CFSTR("com.apple.security.regressions")), "Application Identifier match");
135
136        ok(signingIdentifier=SecTaskCopySigningIdentifier(task, NULL), "SecTaskCopySigningIdentifier");
137        ok(CFEqual(signingIdentifier, CFBundleGetIdentifier(CFBundleGetMainBundle())), "CodeSigning Identifier match");
138    }
139
140    pid_t pid = getpid();
141    CFStringRef name = copyProcName(pid);
142    CFStringRef expected = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@[%d]"), name, pid);
143    CFStringRef desc = CFCopyDescription(task);
144    ok(CFEqual(desc, expected), "task-description expected: %@ got: %@", expected,  desc);
145    CFReleaseSafe(name);
146    CFReleaseSafe(desc);
147    CFReleaseSafe(expected);
148
149out:
150    CFReleaseSafe(task);
151    CFReleaseSafe(appId);
152    CFReleaseSafe(signingIdentifier);
153
154    return 0;
155}
156
157int sectask_11_sectask_audittoken(int argc, char *const *argv)
158{
159    SecTaskRef task=NULL;
160    CFStringRef appId=NULL;
161    CFStringRef signingIdentifier=NULL;
162
163    plan_tests(6);
164
165    init_self_audittoken();
166
167    ok(task=SecTaskCreateWithAuditToken(kCFAllocatorDefault, g_self_audittoken), "SecTaskCreateFromAuditToken");
168    require(task, out);
169
170    /* TODO: remove the todo once xcode signs simulator binaries */
171SKIP: {
172#if TARGET_IPHONE_SIMULATOR
173    todo("no entitlements in the simulator binaries yet, until <rdar://problem/12194625>");
174#endif
175    ok(appId=SecTaskCopyValueForEntitlement(task, kSecEntitlementApplicationIdentifier, NULL), "SecTaskCopyValueForEntitlement");
176    skip("appId is NULL", 1, appId);
177    ok(CFEqual(appId, CFSTR("com.apple.security.regressions")), "Application Identifier match");
178    ok(signingIdentifier=SecTaskCopySigningIdentifier(task, NULL), "SecTaskCopySigningIdentifier");
179    ok(CFEqual(signingIdentifier, CFBundleGetIdentifier(CFBundleGetMainBundle())), "CodeSigning Identifier match");
180}
181
182    pid_t pid = getpid();
183    CFStringRef name = copyProcName(pid);
184    CFStringRef expected = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@[%d]"), name, pid);
185    CFStringRef desc = CFCopyDescription(task);
186    ok(CFEqual(desc, expected), "task-description expected: %@ got: %@", expected,  desc);
187
188    CFReleaseSafe(name);
189    CFReleaseSafe(desc);
190    CFReleaseSafe(expected);
191
192out:
193    CFReleaseSafe(task);
194    CFReleaseSafe(appId);
195    CFReleaseSafe(signingIdentifier);
196
197    return 0;
198}
199