Include security origin in the service worker process name
[WebKit-https.git] / Source / WebKit / Shared / EntryPointUtilities / mac / XPCService / XPCServiceEntryPoint.mm
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 #import <WebCore/Process.h>
32
33 using namespace WebCore;
34
35 namespace WebKit {
36
37 XPCServiceInitializerDelegate::~XPCServiceInitializerDelegate()
38 {
39 }
40
41 bool XPCServiceInitializerDelegate::checkEntitlements()
42 {
43 #if PLATFORM(MAC)
44     if (!isClientSandboxed())
45         return true;
46
47     // FIXME: Once we're 100% sure that a process can't access the network we can get rid of this requirement for all processes.
48     if (!hasEntitlement("com.apple.security.network.client")) {
49         NSLog(@"Application does not have the 'com.apple.security.network.client' entitlement.");
50         return false;
51     }
52 #endif
53 #if PLATFORM(IOS)
54     auto value = adoptOSObject(xpc_connection_copy_entitlement_value(m_connection.get(), "keychain-access-groups"));
55     if (value && xpc_get_type(value.get()) == XPC_TYPE_ARRAY) {
56         xpc_array_apply(value.get(), ^bool(size_t index, xpc_object_t object) {
57             if (xpc_get_type(object) == XPC_TYPE_STRING && !strcmp(xpc_string_get_string_ptr(object), "com.apple.identities")) {
58                 IPC::setAllowsDecodingSecKeyRef(true);
59                 return false;
60             }
61             return true;
62         });
63     }
64 #endif
65
66     return true;
67 }
68
69 bool XPCServiceInitializerDelegate::getConnectionIdentifier(IPC::Connection::Identifier& identifier)
70 {
71     mach_port_t port = xpc_dictionary_copy_mach_send(m_initializerMessage, "server-port");
72     if (port == MACH_PORT_NULL)
73         return false;
74
75     identifier = IPC::Connection::Identifier(port, m_connection);
76     return true;
77 }
78
79 bool 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
87 bool XPCServiceInitializerDelegate::getProcessIdentifier(ProcessIdentifier& identifier)
88 {
89     String processIdentifierString = xpc_dictionary_get_string(m_initializerMessage, "process-identifier");
90     if (processIdentifierString.isEmpty())
91         return false;
92
93     bool ok;
94     auto parsedIdentifier = processIdentifierString.toUInt64Strict(&ok);
95     if (!ok)
96         return false;
97
98     identifier = makeObjectIdentifier<ProcessIdentifierType>(parsedIdentifier);
99     return true;
100 }
101
102 bool XPCServiceInitializerDelegate::getClientProcessName(String& clientProcessName)
103 {
104     clientProcessName = xpc_dictionary_get_string(m_initializerMessage, "ui-process-name");
105     if (clientProcessName.isEmpty())
106         return false;
107     return true;
108 }
109
110 bool XPCServiceInitializerDelegate::getExtraInitializationData(HashMap<String, String>& extraInitializationData)
111 {
112     xpc_object_t extraDataInitializationDataObject = xpc_dictionary_get_value(m_initializerMessage, "extra-initialization-data");
113
114     String inspectorProcess = xpc_dictionary_get_string(extraDataInitializationDataObject, "inspector-process");
115     if (!inspectorProcess.isEmpty())
116         extraInitializationData.add(ASCIILiteral("inspector-process"), inspectorProcess);
117
118 #if ENABLE(SERVICE_WORKER)
119     String serviceWorkerProcess = xpc_dictionary_get_string(extraDataInitializationDataObject, "service-worker-process");
120     if (!serviceWorkerProcess.isEmpty())
121         extraInitializationData.add(ASCIILiteral("service-worker-process"), serviceWorkerProcess);
122 #endif
123
124     String securityOrigin = xpc_dictionary_get_string(extraDataInitializationDataObject, "security-origin");
125     if (!securityOrigin.isEmpty())
126         extraInitializationData.add(ASCIILiteral("security-origin"), securityOrigin);
127
128     if (!isClientSandboxed()) {
129         String userDirectorySuffix = xpc_dictionary_get_string(extraDataInitializationDataObject, "user-directory-suffix");
130         if (!userDirectorySuffix.isEmpty())
131             extraInitializationData.add(ASCIILiteral("user-directory-suffix"), userDirectorySuffix);
132     }
133
134     String alwaysRunsAtBackgroundPriority = xpc_dictionary_get_string(extraDataInitializationDataObject, "always-runs-at-background-priority");
135     if (!alwaysRunsAtBackgroundPriority.isEmpty())
136         extraInitializationData.add(ASCIILiteral("always-runs-at-background-priority"), alwaysRunsAtBackgroundPriority);
137
138     return true;
139 }
140
141 bool XPCServiceInitializerDelegate::hasEntitlement(const char* entitlement)
142 {
143     auto value = adoptOSObject(xpc_connection_copy_entitlement_value(m_connection.get(), entitlement));
144     if (!value)
145         return false;
146
147     return xpc_get_type(value.get()) == XPC_TYPE_BOOL && xpc_bool_get_value(value.get());
148 }
149
150 bool XPCServiceInitializerDelegate::isClientSandboxed()
151 {
152     return connectedProcessIsSandboxed(m_connection.get());
153 }
154
155 void XPCServiceExit(OSObjectPtr<xpc_object_t>&& priorityBoostMessage)
156 {
157     // Make sure to destroy the priority boost message to avoid leaking a transaction.
158     priorityBoostMessage = nullptr;
159     // Balances the xpc_transaction_begin() in XPCServiceInitializer.
160     xpc_transaction_end();
161     xpc_transaction_exit_clean();
162 }
163
164 } // namespace WebKit