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; }
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; } }
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. }
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. }
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; }