1/* 2 * Copyright (C) 2013 University of Szeged 3 * Copyright (C) 2013 Renata Hodovan <reni@inf.u-szeged.hu> 4 * Copyright (C) 2010 Apple Inc. All rights reserved. 5 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 18 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 26 * THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#include "config.h" 30#include "WebProcess.h" 31 32#include "WebKit2Initialize.h" 33#include <QGuiApplication> 34#include <QList> 35#include <QNetworkProxyFactory> 36#include <QString> 37#include <QStringList> 38#include <QUrl> 39#include <WebCore/RunLoop.h> 40#include <errno.h> 41 42#ifndef NDEBUG 43#if !OS(WINDOWS) 44#include <unistd.h> 45#endif 46#endif 47 48#ifndef NDEBUG 49#include <QDebug> 50#endif 51 52#if OS(DARWIN) && !USE(UNIX_DOMAIN_SOCKETS) 53#include <servers/bootstrap.h> 54 55extern "C" kern_return_t bootstrap_look_up2(mach_port_t, const name_t, mach_port_t*, pid_t, uint64_t); 56#endif 57 58#if ENABLE(SUID_SANDBOX_LINUX) 59#include "SandboxEnvironmentLinux.h" 60#include <sys/wait.h> 61#endif 62 63using namespace WebCore; 64 65namespace WebKit { 66#ifndef NDEBUG 67#if OS(WINDOWS) 68static void sleep(unsigned seconds) 69{ 70 ::Sleep(seconds * 1000); 71} 72#endif 73#endif 74 75class EnvHttpProxyFactory : public QNetworkProxyFactory 76{ 77public: 78 EnvHttpProxyFactory() { } 79 80 bool initializeFromEnvironment(); 81 82 QList<QNetworkProxy> queryProxy(const QNetworkProxyQuery& query = QNetworkProxyQuery()); 83 84private: 85 QList<QNetworkProxy> m_httpProxy; 86 QList<QNetworkProxy> m_httpsProxy; 87}; 88 89bool EnvHttpProxyFactory::initializeFromEnvironment() 90{ 91 bool wasSetByEnvironment = false; 92 93 QUrl proxyUrl = QUrl::fromUserInput(QString::fromLocal8Bit(qgetenv("http_proxy"))); 94 if (proxyUrl.isValid() && !proxyUrl.host().isEmpty()) { 95 int proxyPort = (proxyUrl.port() > 0) ? proxyUrl.port() : 8080; 96 m_httpProxy << QNetworkProxy(QNetworkProxy::HttpProxy, proxyUrl.host(), proxyPort); 97 wasSetByEnvironment = true; 98 } else 99 m_httpProxy << QNetworkProxy::NoProxy; 100 101 proxyUrl = QUrl::fromUserInput(QString::fromLocal8Bit(qgetenv("https_proxy"))); 102 if (proxyUrl.isValid() && !proxyUrl.host().isEmpty()) { 103 int proxyPort = (proxyUrl.port() > 0) ? proxyUrl.port() : 8080; 104 m_httpsProxy << QNetworkProxy(QNetworkProxy::HttpProxy, proxyUrl.host(), proxyPort); 105 wasSetByEnvironment = true; 106 } else 107 m_httpsProxy << QNetworkProxy::NoProxy; 108 109 return wasSetByEnvironment; 110} 111 112QList<QNetworkProxy> EnvHttpProxyFactory::queryProxy(const QNetworkProxyQuery& query) 113{ 114 QString protocol = query.protocolTag().toLower(); 115 bool localHost = false; 116 117 if (!query.peerHostName().compare(QLatin1String("localhost"), Qt::CaseInsensitive) || !query.peerHostName().compare(QLatin1String("127.0.0.1"), Qt::CaseInsensitive)) 118 localHost = true; 119 if (protocol == QLatin1String("http") && !localHost) 120 return m_httpProxy; 121 if (protocol == QLatin1String("https") && !localHost) 122 return m_httpsProxy; 123 124 QList<QNetworkProxy> proxies; 125 proxies << QNetworkProxy::NoProxy; 126 return proxies; 127} 128 129static void initializeProxy() 130{ 131 QList<QNetworkProxy> proxylist = QNetworkProxyFactory::systemProxyForQuery(); 132 if (proxylist.count() == 1) { 133 QNetworkProxy proxy = proxylist.first(); 134 if (proxy == QNetworkProxy::NoProxy || proxy == QNetworkProxy::DefaultProxy) { 135 EnvHttpProxyFactory* proxyFactory = new EnvHttpProxyFactory(); 136 if (proxyFactory->initializeFromEnvironment()) { 137 QNetworkProxyFactory::setApplicationProxyFactory(proxyFactory); 138 return; 139 } 140 } 141 } 142 QNetworkProxyFactory::setUseSystemConfiguration(true); 143} 144 145#if ENABLE(SUID_SANDBOX_LINUX) 146pid_t chrootMe() 147{ 148 // Get the file descriptor of the socketpair. 149 char* sandboxSocketDescriptorString = getenv(SANDBOX_DESCRIPTOR); 150 if (!sandboxSocketDescriptorString) 151 return -1; 152 153 char* firstInvalidCharacter; 154 long int sandboxSocketDescriptor = strtol(sandboxSocketDescriptorString, &firstInvalidCharacter, 10); 155 if (*firstInvalidCharacter != '\0') { 156 fprintf(stderr, "The socket descriptor of sandbox is not valid.\n"); 157 return -1; 158 } 159 160 // Get the PID of the setuid helper. 161 char* sandboxHelperPIDString = getenv(SANDBOX_HELPER_PID); 162 pid_t sandboxHelperPID = -1; 163 164 // If no PID is available, the default of -1 will do. 165 if (sandboxHelperPIDString) { 166 errno = 0; 167 sandboxHelperPID = strtol(sandboxHelperPIDString, &firstInvalidCharacter, 10); 168 if (*firstInvalidCharacter != '\0') { 169 fprintf(stderr, "The PID of sandbox is not valid.\n"); 170 return -1; 171 } 172 } 173 174 // Send the chrootMe message to the helper. 175 char sandboxMeMessage = MSG_CHROOTME; 176 ssize_t numberOfCharacters = write(sandboxSocketDescriptor, &sandboxMeMessage, 1); 177 if (numberOfCharacters != 1) { 178 fprintf(stderr, "ChrootMe msg failed to write: %s.\n", strerror(errno)); 179 return -1; 180 } 181 182 // Read the acknowledgement message from the helper. 183 numberOfCharacters = read(sandboxSocketDescriptor, &sandboxMeMessage, 1); 184 if (numberOfCharacters != 1 || sandboxMeMessage != MSG_CHROOTED) { 185 fprintf(stderr, "Couldn't read the confirmation message: %s.\n", strerror(errno)); 186 return -1; 187 } 188 close(sandboxSocketDescriptor); 189 190 // Wait for the helper process. 191 int expectedPID = waitpid(sandboxHelperPID, 0, 0); 192 if (expectedPID != -1 && (sandboxHelperPID == -1 || expectedPID == sandboxHelperPID)) 193 return expectedPID; 194 fprintf(stderr, "Couldn't wait for the helper process: %s\n", strerror(errno)); 195 return -1; 196} 197#endif 198 199Q_DECL_EXPORT int WebProcessMainQt(QGuiApplication* app) 200{ 201#if ENABLE(SUID_SANDBOX_LINUX) 202 pid_t helper = chrootMe(); 203 if (helper == -1) { 204 fprintf(stderr, "Asking for chroot failed.\n"); 205 return -1; 206 } 207#endif 208 initializeProxy(); 209 210 InitializeWebKit2(); 211 212 // Create the connection. 213 if (app->arguments().size() <= 1) { 214 qDebug() << "Error: wrong number of arguments."; 215 return 1; 216 } 217 218#if OS(DARWIN) 219 QString serviceName = app->arguments().value(1); 220 221 // Get the server port. 222 mach_port_t identifier; 223 kern_return_t kr = bootstrap_look_up2(bootstrap_port, serviceName.toUtf8().data(), &identifier, 0, 0); 224 if (kr) { 225 printf("bootstrap_look_up2 result: %x", kr); 226 return 2; 227 } 228#else 229 bool wasNumber = false; 230 qulonglong id = app->arguments().at(1).toULongLong(&wasNumber, 10); 231 if (!wasNumber) { 232 qDebug() << "Error: connection identifier wrong."; 233 return 1; 234 } 235 CoreIPC::Connection::Identifier identifier; 236#if OS(WINDOWS) 237 // Convert to HANDLE 238 identifier = reinterpret_cast<CoreIPC::Connection::Identifier>(id); 239#else 240 // Convert to int 241 identifier = static_cast<CoreIPC::Connection::Identifier>(id); 242#endif 243#endif 244 245 246 WebKit::ChildProcessInitializationParameters parameters; 247 parameters.connectionIdentifier = identifier; 248 249 WebKit::WebProcess::shared().initialize(parameters); 250 251 RunLoop::run(); 252 253 // FIXME: Do more cleanup here. 254 delete app; 255 256 return 0; 257} 258 259} 260