QT_BEGIN_NAMESPACE

static bool isHostExcluded(CFDictionaryRef dict, const QString &host)
{
    if (host.isEmpty())
        return true;

    bool isSimple = !host.contains(QLatin1Char('.')) && !host.contains(QLatin1Char(':'));
    CFNumberRef excludeSimples;
    if (isSimple &&
        (excludeSimples = (CFNumberRef)CFDictionaryGetValue(dict, kSCPropNetProxiesExcludeSimpleHostnames))) {
        int enabled;
        if (CFNumberGetValue(excludeSimples, kCFNumberIntType, &enabled) && enabled)
            return true;
    }

    QHostAddress ipAddress;
    bool isIpAddress = ipAddress.setAddress(host);

    // not a simple host name
    // does it match the list of exclusions?
    CFArrayRef exclusionList = (CFArrayRef)CFDictionaryGetValue(dict, kSCPropNetProxiesExceptionsList);
    if (!exclusionList)
        return false;

    CFIndex size = CFArrayGetCount(exclusionList);
    for (CFIndex i = 0; i < size; ++i) {
        CFStringRef cfentry = (CFStringRef)CFArrayGetValueAtIndex(exclusionList, i);
        QString entry = QCFString::toQString(cfentry);

        if (isIpAddress && ipAddress.isInSubnet(QHostAddress::parseSubnet(entry))) {
            return true;        // excluded
        } else {
            // do wildcard matching
            QRegExp rx(entry, Qt::CaseInsensitive, QRegExp::Wildcard);
            if (rx.exactMatch(host))
                return true;
        }
    }

    // host was not excluded
    return false;
}
Beispiel #2
0
bool ProxyConfPrivate::isHostExcluded(const QString &host)
{
    if (host.isEmpty())
        return true;

    if (ignore_hosts.isEmpty())
        return false;

    QHostAddress ipAddress;
    bool isIpAddress = ipAddress.setAddress(host);

    foreach (QVariant h, ignore_hosts) {
        QString entry = h.toString();
        if (isIpAddress && ipAddress.isInSubnet(QHostAddress::parseSubnet(entry))) {
            return true;  // excluded
        } else {
            // do wildcard matching
            QRegExp rx(entry, Qt::CaseInsensitive, QRegExp::Wildcard);
            if (rx.exactMatch(host))
                return true;
        }
    }
Beispiel #3
0
void ServerPool::SelectDefaultListen(bool force)
{
    if (!force)
    {
        QReadLocker rlock(&naLock);
        if (!naList_4.isEmpty() || !naList_6.isEmpty())
            // lists are already populated, do nothing
            return;
    }

    QWriteLocker wlock(&naLock);
    naList_4.clear();
    naList_6.clear();

    // populate stored IPv4 and IPv6 addresses
    QHostAddress config_v4(gCoreContext->resolveSettingAddress(
                                           "BackendServerIP",
                                           QString(),
                                           gCoreContext->ResolveIPv4, true));
    bool v4IsSet = config_v4.isNull() ? true : false;
#if !defined(QT_NO_IPV6)
    QHostAddress config_v6(gCoreContext->resolveSettingAddress(
                                           "BackendServerIP6",
                                           QString(),
                                           gCoreContext->ResolveIPv6, true));
    bool v6IsSet = config_v6.isNull() ? true : false;
#endif
    bool allowLinkLocal = gCoreContext->GetNumSetting("AllowLinkLocal", true) > 0;

    // loop through all available interfaces
    QList<QNetworkInterface> IFs = QNetworkInterface::allInterfaces();
    QList<QNetworkInterface>::const_iterator qni;
    for (qni = IFs.begin(); qni != IFs.end(); ++qni)
    {
        if ((qni->flags() & QNetworkInterface::IsRunning) == 0)
            continue;

        QList<QNetworkAddressEntry> IPs = qni->addressEntries();
        QList<QNetworkAddressEntry>::iterator qnai;
        for (qnai = IPs.begin(); qnai != IPs.end(); ++qnai)
        {
            QHostAddress ip = qnai->ip();
#if !defined(QT_NO_IPV6)
            if (ip.protocol() == QAbstractSocket::IPv4Protocol)
            {
#endif
                if (naList_4.contains(*qnai))
                    // already defined, skip
                    continue;

                else if (!config_v4.isNull() && (ip == config_v4))
                {
                    // IPv4 address is defined, add it
                    LOG(VB_GENERAL, LOG_DEBUG,
                        QString("Adding BackendServerIP to address list."));
                    naList_4.append(*qnai);
                    v4IsSet = true;

                }

                else if (ip == QHostAddress::LocalHost)
                {
                    // always listen on LocalHost
                    LOG(VB_GENERAL, LOG_DEBUG,
                        QString("Adding IPv4 loopback to address list."));
                    naList_4.append(*qnai);
                    if (!v4IsSet && (config_v4 == ip))
                        v4IsSet = true;
                }

                else if (ip.isInSubnet(kLinkLocal) && allowLinkLocal)
                {
                    // optionally listen on linklocal
                    // the next clause will enable it anyway if no IP address
                    // has been set
                    LOG(VB_GENERAL, LOG_DEBUG,
                            QString("Adding link-local '%1' to address list.")
                                .arg(PRETTYIP_(ip)));
                    naList_4.append(*qnai);
                }

                else if (config_v4.isNull())
                {
                    // IPv4 address is not defined, populate one
                    // restrict autoconfiguration to RFC1918 private networks
                    static QPair<QHostAddress, int>
                       privNet1 = QHostAddress::parseSubnet("10.0.0.0/8"),
                       privNet2 = QHostAddress::parseSubnet("172.16.0.0/12"),
                       privNet3 = QHostAddress::parseSubnet("192.168.0.0/16");

                    if (ip.isInSubnet(privNet1) || ip.isInSubnet(privNet2) ||
                        ip.isInSubnet(privNet3))
                    {
                        LOG(VB_GENERAL, LOG_DEBUG,
                                QString("Adding '%1' to address list.")
                                    .arg(PRETTYIP_(ip)));
                        naList_4.append(*qnai);
                    }
                    else if (ip.isInSubnet(kLinkLocal))
                    {
                        LOG(VB_GENERAL, LOG_DEBUG,
                            QString("Adding link-local '%1' to address list.")
                                    .arg(PRETTYIP_(ip)));
                        naList_4.append(*qnai);
                    }
                    else
                        LOG(VB_GENERAL, LOG_DEBUG, QString("Skipping "
                           "non-private address during IPv4 autoselection: %1")
                                    .arg(PRETTYIP_(ip)));
                }

                else
                    LOG(VB_GENERAL, LOG_DEBUG, QString("Skipping address: %1")
                                .arg(PRETTYIP_(ip)));

#if !defined(QT_NO_IPV6)
            }
            else
            {
                if (ip.isInSubnet(kLinkLocal6))
                {
                    // set scope id for link local address
                    ip.setScopeId(qni->name());
                    qnai->setIp(ip);
                }

                if (naList_6.contains(*qnai))
                    // already defined, skip
                    continue;

                else if ((!config_v6.isNull()) && (ip == config_v6))
                {
                // IPv6 address is defined, add it
                    LOG(VB_GENERAL, LOG_DEBUG,
                        QString("Adding BackendServerIP6 to address list."));
                    naList_6.append(*qnai);
                    v6IsSet = true;
                }

                else if (ip == QHostAddress::LocalHostIPv6)
                {
                // always listen on LocalHost
                    LOG(VB_GENERAL, LOG_DEBUG,
                            QString("Adding IPv6 loopback to address list."));
                    naList_6.append(*qnai);
                    if (!v6IsSet && (config_v6 == ip))
                        v6IsSet = true;
                }

                else if (ip.isInSubnet(kLinkLocal6) && allowLinkLocal)
                {
                    // optionally listen on linklocal
                    // the next clause will enable it anyway if no IP address
                    // has been set
                    LOG(VB_GENERAL, LOG_DEBUG,
                            QString("Adding link-local '%1' to address list.")
                                .arg(ip.toString()));
                    naList_6.append(*qnai);
                }

                else if (config_v6.isNull())
                {
                    if (ip.isInSubnet(kLinkLocal6))
                        LOG(VB_GENERAL, LOG_DEBUG,
                            QString("Adding link-local '%1' to address list.")
                                .arg(PRETTYIP_(ip)));
                    else
                        LOG(VB_GENERAL, LOG_DEBUG,
                            QString("Adding '%1' to address list.")
                                .arg(PRETTYIP_(ip)));

                    naList_6.append(*qnai);
                }

                else
                    LOG(VB_GENERAL, LOG_DEBUG, QString("Skipping address: %1")
                                .arg(PRETTYIP_(ip)));
            }
#endif
        }
    }

    if (!v4IsSet && (config_v4 != QHostAddress::LocalHost)
                 && !naList_4.isEmpty())
    {
        LOG(VB_GENERAL, LOG_CRIT, LOC + QString("Host is configured to listen "
                "on %1, but address is not used on any local network "
                "interfaces.").arg(config_v4.toString()));
    }

#if !defined(QT_NO_IPV6)
    if (!v6IsSet && (config_v6 != QHostAddress::LocalHostIPv6)
                 && !naList_6.isEmpty())
    {
        LOG(VB_GENERAL, LOG_CRIT, LOC + QString("Host is configured to listen "
                "on %1, but address is not used on any local network "
                "interfaces.").arg(PRETTYIP_(config_v6)));
    }
#endif

    // NOTE: there is no warning for the case where both defined addresses
    //       are localhost, and neither are found. however this would also
    //       mean there is no configured network at all, and should be
    //       sufficiently rare a case as to not worry about it.
}
Beispiel #4
0
void ServerPool::SelectDefaultListen(bool force)
{
    if (!force)
    {
        QReadLocker rlock(&naLock);
        if (!naList_4.isEmpty() || !naList_6.isEmpty())
            // lists are already populated, do nothing
            return;
    }

    QWriteLocker wlock(&naLock);
    naList_4.clear();
    naList_6.clear();

    // populate stored IPv4 and IPv6 addresses
    // if address is not defined, QHostAddress will be invalid and Null
    QHostAddress config_v4(gCoreContext->GetSetting("BackendServerIP"));
    bool v4IsSet = config_v4.isNull() ? true : false;
#if !defined(QT_NO_IPV6)
    QHostAddress config_v6(gCoreContext->GetSetting("BackendServerIP6"));
    bool v6IsSet = config_v6.isNull() ? true : false;
#endif

    // loop through all available interfaces
    QList<QNetworkInterface> IFs = QNetworkInterface::allInterfaces();
    QList<QNetworkInterface>::const_iterator qni;
    for (qni = IFs.begin(); qni != IFs.end(); ++qni)
    {
        QList<QNetworkAddressEntry> IPs = qni->addressEntries();
        QList<QNetworkAddressEntry>::const_iterator qnai;
        for (qnai = IPs.begin(); qnai != IPs.end(); ++qnai)
        {
            QHostAddress ip = qnai->ip();
            if (naList_4.contains(*qnai))
                // already defined, skip
                continue;
            else if (!config_v4.isNull() && (ip == config_v4))
            {
                // IPv4 address is defined, add it
                LOG(VB_GENERAL, LOG_DEBUG,
                    QString("Adding BackendServerIP to address list."));
                naList_4.append(*qnai);
                v4IsSet = true;
            }
            else if (ip == QHostAddress::LocalHost)
            {
                // always listen on LocalHost
                LOG(VB_GENERAL, LOG_DEBUG,
                    QString("Adding IPv4 loopback to address list."));
                naList_4.append(*qnai);
                if (!v4IsSet && (config_v4 == ip))
                    v4IsSet = true;
            }
            else if (config_v4.isNull() &&
                     (ip.protocol() == QAbstractSocket::IPv4Protocol))
            {
                // IPv4 address is not defined, populate one
                // restrict autoconfiguration to RFC1918 private networks
                if (ip.isInSubnet(QHostAddress::parseSubnet("10.0.0.0/8")) ||
                        ip.isInSubnet(QHostAddress::parseSubnet("172.16.0.0/12")) ||
                        ip.isInSubnet(QHostAddress::parseSubnet("192.168.0.0/16")))
                {
                    LOG(VB_GENERAL, LOG_DEBUG,
                        QString("Adding '%1' to address list.")
                        .arg(ip.toString()));
                    naList_4.append(*qnai);
                }
                else
                    LOG(VB_GENERAL, LOG_DEBUG, QString("Skipping non-private "
                                                       "address during IPv4 autoselection: %1")
                        .arg(ip.toString()));
            }
#if !defined(QT_NO_IPV6)
            else if (naList_6.contains(*qnai))
                // already defined, skip
                continue;
            else if (!config_v6.isNull() && (ip == config_v6))
            {
                // IPv6 address is defined, add it
                LOG(VB_GENERAL, LOG_DEBUG,
                    QString("Adding BackendServerIP6 to address list."));
                naList_6.append(*qnai);
                v6IsSet = true;
            }
            else if (ip == QHostAddress::LocalHostIPv6)
            {
                // always listen on LocalHost
                LOG(VB_GENERAL, LOG_DEBUG,
                    QString("Adding IPv6 loopback to address list."));
                naList_6.append(*qnai);
                if (!v6IsSet && (config_v6 == ip))
                    v6IsSet = true;
            }
            else if (config_v6.isNull() &&
                     (ip.protocol() == QAbstractSocket::IPv6Protocol))
            {
                // IPv6 address is not defined, populate one
                // put in additional block filtering here?
                if (!ip.isInSubnet(QHostAddress::parseSubnet("fe80::/10")))
                {
                    LOG(VB_GENERAL, LOG_DEBUG,
                        QString("Adding '%1' to address list.")
                        .arg(PRETTYIP_(ip)));
                    naList_6.append(*qnai);
                }
                else
                    LOG(VB_GENERAL, LOG_DEBUG, QString("Skipping link-local "
                                                       "address during IPv6 autoselection: %1")
                        .arg(PRETTYIP_(ip)));

            }
#endif
            else
                LOG(VB_GENERAL, LOG_DEBUG, QString("Skipping address: %1")
                    .arg(PRETTYIP_(ip)));
        }
    }

    if (!v4IsSet && (config_v4 != QHostAddress::LocalHost)
            && !naList_4.isEmpty())
    {
        LOG(VB_GENERAL, LOG_CRIT, LOC + QString("Host is configured to listen "
                                                "on %1, but address is not used on any local network "
                                                "interfaces.").arg(config_v4.toString()));
    }

#if !defined(QT_NO_IPV6)
    if (!v6IsSet && (config_v6 != QHostAddress::LocalHostIPv6)
            && !naList_6.isEmpty())
    {
        LOG(VB_GENERAL, LOG_CRIT, LOC + QString("Host is configured to listen "
                                                "on %1, but address is not used on any local network "
                                                "interfaces.").arg(PRETTYIP_(config_v6)));
    }
#endif

    // NOTE: there is no warning for the case where both defined addresses
    //       are localhost, and neither are found. however this would also
    //       mean there is no configured network at all, and should be
    //       sufficiently rare a case as to not worry about it.
}
Beispiel #5
0
bool ServerSideScripting::EvaluatePage( QTextStream *pOutStream, const QString &sFileName,
                                        HTTPRequest *pRequest)
{
    try
    {

        ScriptInfo *pInfo = NULL;

        // ------------------------------------------------------------------
        // See if page has already been loaded
        // ------------------------------------------------------------------

        pInfo = GetLoadedScript( sFileName );

        // ------------------------------------------------------------------
        // Load Script File and Create Function
        // ------------------------------------------------------------------

        QFileInfo  fileInfo ( sFileName );
        QDateTime  dtLastModified = fileInfo.lastModified();

        Lock();
        if ((pInfo == NULL) || (pInfo->m_dtTimeStamp != dtLastModified ))
        {
            QString      sCode = CreateMethodFromFile( sFileName );

            QScriptValue func  = m_engine.evaluate( sCode, sFileName );

            if ( m_engine.hasUncaughtException() )
            {
                LOG(VB_GENERAL, LOG_ERR,
                    QString("Error Loading QSP File: %1 - (line %2) %3")
                        .arg(sFileName)
                        .arg(m_engine.uncaughtExceptionLineNumber())
                        .arg(m_engine.uncaughtException().toString()));

                Unlock();
                return false;
            }

            if (pInfo != NULL)
            {
                pInfo->m_oFunc       = func;
                pInfo->m_dtTimeStamp = dtLastModified;
            }
            else
            {
                pInfo = new ScriptInfo( func, dtLastModified );
                m_mapScripts[ sFileName ] = pInfo;
            }
        }

        // ------------------------------------------------------------------
        // Build array of arguments passed to script
        // ------------------------------------------------------------------

        QStringMap mapParams = pRequest->m_mapParams;

        // Valid characters for object property names must contain only
        // word characters and numbers, _ and $
        // They must not start with a number - to simplify the regexp, we
        // restrict the first character to the English alphabet
        QRegExp validChars = QRegExp("^([a-zA-Z]|_|\\$)(\\w|\\$)+$");

        QVariantMap params;
        QMap<QString, QString>::const_iterator it = mapParams.begin();
        QString prevArrayName = "";
        QVariantMap array;
        for (; it != mapParams.end(); ++it)
        {
            QString key = it.key();
            QVariant value = QVariant(it.value());

            // PHP Style parameter array
            if (key.contains("["))
            {
                QString arrayName = key.section('[',0,0);
                QString arrayKey = key.section('[',1,1);
                arrayKey.chop(1); // Remove trailing ]
                if (prevArrayName != arrayName) // New or different array
                {
                    if (!array.isEmpty())
                    {
                        params.insert(prevArrayName, QVariant(array));
                        array.clear();
                    }
                    prevArrayName = arrayName;
                }

                if (!validChars.exactMatch(arrayKey)) // Discard anything that isn't valid for now
                    continue;

                array.insert(arrayKey, value);

                if ((it + 1) != mapParams.end())
                    continue;
            }

            if (!array.isEmpty())
            {
                params.insert(prevArrayName, QVariant(array));
                array.clear();
            }
            // End Array handling

            if (!validChars.exactMatch(key)) // Discard anything that isn't valid for now
                continue;

            params.insert(key, value);

        }

        // ------------------------------------------------------------------
        // Build array of request headers
        // ------------------------------------------------------------------

        QStringMap mapHeaders = pRequest->m_mapHeaders;

        QVariantMap requestHeaders;
        for (it = mapHeaders.begin(); it != mapHeaders.end(); ++it)
        {
            QString key = it.key();
            key = key.replace('-', '_'); // May be other valid chars in a request header that we need to replace
            QVariant value = QVariant(it.value());

            if (!validChars.exactMatch(key)) // Discard anything that isn't valid for now
                continue;

            requestHeaders.insert(key, value);
        }

        // ------------------------------------------------------------------
        // Build array of information from the server e.g. client IP
        // See RFC 3875 - The Common Gateway Interface
        // ------------------------------------------------------------------

        QVariantMap serverVars;
        serverVars.insert("REMOTE_ADDR", QVariant(pRequest->GetPeerAddress()));
        serverVars.insert("SERVER_ADDR", QVariant(pRequest->GetHostAddress()));
        serverVars.insert("SERVER_PROTOCOL", QVariant(pRequest->GetRequestProtocol()));
        serverVars.insert("SERVER_SOFTWARE", QVariant(HttpServer::GetServerVersion()));

        QHostAddress clientIP = QHostAddress(pRequest->GetPeerAddress());
        QHostAddress serverIP = QHostAddress(pRequest->GetHostAddress());
        if (clientIP.protocol() == QAbstractSocket::IPv4Protocol)
        {
            serverVars.insert("IP_PROTOCOL", "IPv4");
        }
        else if (clientIP.protocol() == QAbstractSocket::IPv6Protocol)
        {
            serverVars.insert("IP_PROTOCOL", "IPv6");
        }

        if (((clientIP.protocol() == QAbstractSocket::IPv4Protocol) &&
             (clientIP.isInSubnet(QHostAddress("172.16.0.0"), 12) ||
              clientIP.isInSubnet(QHostAddress("192.168.0.0"), 16) ||
              clientIP.isInSubnet(QHostAddress("10.0.0.0"), 8))) ||
            ((clientIP.protocol() == QAbstractSocket::IPv6Protocol) &&
              clientIP.isInSubnet(serverIP, 64))) // default subnet size is assumed to be /64
        {
            serverVars.insert("CLIENT_NETWORK", "local");
        }
        else
        {
            serverVars.insert("CLIENT_NETWORK", "remote");
        }

        // ------------------------------------------------------------------
        // Add the arrays (objects) we've just created to the global scope
        // They may be accessed as 'Server.REMOTE_ADDR'
        // ------------------------------------------------------------------

        m_engine.globalObject().setProperty("Parameters",
                                            m_engine.toScriptValue(params));
        m_engine.globalObject().setProperty("RequestHeaders",
                                            m_engine.toScriptValue(requestHeaders));
        m_engine.globalObject().setProperty("Server",
                                            m_engine.toScriptValue(serverVars));

        // ------------------------------------------------------------------
        // Execute function to render output
        // ------------------------------------------------------------------

        OutputStream outStream( pOutStream );

        QScriptValueList args;
        args << m_engine.newQObject( &outStream );
        args << m_engine.toScriptValue(params);

        QScriptValue ret = pInfo->m_oFunc.call( QScriptValue(), args );

        if (ret.isError())
        {
            QScriptValue lineNo = ret.property( "lineNumber" );

            LOG(VB_GENERAL, LOG_ERR,
                QString("Error calling QSP File: %1(%2) - %3")
                    .arg(sFileName)
                    .arg( lineNo.toInt32 () )
                    .arg( ret   .toString() ));
            Unlock();
            return false;

        }

        if (m_engine.hasUncaughtException())
        {
            LOG(VB_GENERAL, LOG_ERR,
                QString("Error calling QSP File: %1(%2) - %3")
                    .arg(sFileName)
                    .arg(m_engine.uncaughtExceptionLineNumber() )
                    .arg(m_engine.uncaughtException().toString()));
            Unlock();
            return false;
        }
        Unlock();
    }
    catch(...)
    {
        LOG(VB_GENERAL, LOG_ERR,
            QString("Exception while evaluating QSP File: %1") .arg(sFileName));

        Unlock();
        return false;
    }

    return true;
}