1/*
2 * Copyright (C) 2013 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#import "config.h"
27
28#import "ArgumentCodersCF.h"
29#import "SandboxUtilities.h"
30#import "XPCServiceEntryPoint.h"
31
32#if __has_include(<xpc/private.h>)
33#import <xpc/private.h>
34#else
35extern "C" xpc_object_t xpc_connection_copy_entitlement_value(xpc_connection_t connection, const char *entitlement);
36extern "C" mach_port_t xpc_dictionary_copy_mach_send(xpc_object_t, const char*);
37#endif
38
39namespace WebKit {
40
41XPCServiceInitializerDelegate::~XPCServiceInitializerDelegate()
42{
43}
44
45bool XPCServiceInitializerDelegate::checkEntitlements()
46{
47#if PLATFORM(MAC)
48    if (!isClientSandboxed())
49        return true;
50
51    // FIXME: Once we're 100% sure that a process can't access the network we can get rid of this requirement for all processes.
52    if (!hasEntitlement("com.apple.security.network.client")) {
53        NSLog(@"Application does not have the 'com.apple.security.network.client' entitlement.");
54        return false;
55    }
56#endif
57#if PLATFORM(IOS)
58    auto value = IPC::adoptXPC(xpc_connection_copy_entitlement_value(m_connection.get(), "keychain-access-groups"));
59    if (value && xpc_get_type(value.get()) == XPC_TYPE_ARRAY) {
60        xpc_array_apply(value.get(), ^bool(size_t index, xpc_object_t object) {
61            if (xpc_get_type(object) == XPC_TYPE_STRING && !strcmp(xpc_string_get_string_ptr(object), "com.apple.identities")) {
62                IPC::setAllowsDecodingSecKeyRef(true);
63                return false;
64            }
65            return true;
66        });
67    }
68#endif
69
70    return true;
71}
72
73bool XPCServiceInitializerDelegate::getConnectionIdentifier(IPC::Connection::Identifier& identifier)
74{
75    identifier = IPC::Connection::Identifier(xpc_dictionary_copy_mach_send(m_initializerMessage, "server-port"), m_connection);
76    return true;
77}
78
79bool XPCServiceInitializerDelegate::getClientIdentifier(String& clientIdentifier)
80{
81    clientIdentifier = xpc_dictionary_get_string(m_initializerMessage, "client-identifier");
82    if (clientIdentifier.isEmpty())
83        return false;
84    return true;
85}
86
87bool XPCServiceInitializerDelegate::getClientProcessName(String& clientProcessName)
88{
89    clientProcessName = xpc_dictionary_get_string(m_initializerMessage, "ui-process-name");
90    if (clientProcessName.isEmpty())
91        return false;
92    return true;
93}
94
95bool XPCServiceInitializerDelegate::getExtraInitializationData(HashMap<String, String>&)
96{
97    return true;
98}
99
100bool XPCServiceInitializerDelegate::hasEntitlement(const char* entitlement)
101{
102    auto value = IPC::adoptXPC(xpc_connection_copy_entitlement_value(m_connection.get(), entitlement));
103    if (!value)
104        return false;
105
106    return xpc_get_type(value.get()) == XPC_TYPE_BOOL && xpc_bool_get_value(value.get());
107}
108
109bool XPCServiceInitializerDelegate::isClientSandboxed()
110{
111    return processIsSandboxed(xpc_connection_get_pid(m_connection.get()));
112}
113
114} // namespace WebKit
115