Vidalia  0.2.17
NetworkSettings.cpp
Go to the documentation of this file.
00001 /*
00002 **  This file is part of Vidalia, and is subject to the license terms in the
00003 **  LICENSE file, found in the top level directory of this distribution. If you
00004 **  did not receive the LICENSE file with this file, you may obtain it from the
00005 **  Vidalia source package distributed by the Vidalia Project at
00006 **  http://www.torproject.org/projects/vidalia.html. No part of Vidalia, 
00007 **  including this file, may be copied, modified, propagated, or distributed 
00008 **  except according to the terms described in the LICENSE file.
00009 */
00010 
00011 /*
00012 ** \file NetworkSettings.cpp
00013 ** \brief Settings for configuring an HTTP/HTTPS proxy or bridges
00014 */
00015 
00016 #include "NetworkSettings.h"
00017 #include "TorControl.h"
00018 
00019 #define SETTING_FASCIST_FIREWALL    "FascistFirewall"
00020 #define SETTING_REACHABLE_ADDRESSES "ReachableAddresses"
00021 
00022 /* Vidalia-specific proxy options */
00023 #define SETTING_PROXY_TYPE          "ProxyType"
00024 #define SETTING_PROXY_ADDRESS       "ProxyAddress"
00025 #define SETTING_PROXY_USERNAME      "ProxyUsername"
00026 #define SETTING_PROXY_PASSWORD      "ProxyPassword"
00027 
00028 /* Tor's proxy options */
00029 #define SETTING_HTTPS_PROXY         "HttpsProxy"
00030 #define SETTING_HTTPS_PROXY_AUTH    "HttpsProxyAuthenticator"
00031 #define SETTING_SOCKS4_PROXY        "Socks4Proxy"
00032 #define SETTING_SOCKS5_PROXY        "Socks5Proxy"
00033 #define SETTING_SOCKS5_USERNAME     "Socks5ProxyUsername"
00034 #define SETTING_SOCKS5_PASSWORD     "Socks5ProxyPassword"
00035 
00036 #define SETTING_USE_BRIDGES         "UseBridges"
00037 #define SETTING_BRIDGE_LIST         "Bridge"
00038 #define SETTING_UPDATE_BRIDGES      "UpdateBridgesFromAuthority"
00039 #define SETTING_TUNNEL_DIR_CONNS    "TunnelDirConns"
00040 #define SETTING_PREFER_TUNNELED_DIR_CONNS "PreferTunneledDirConns"
00041 
00042 
00043 /** Default constructor */
00044 NetworkSettings::NetworkSettings(TorControl *torControl)
00045 : AbstractTorSettings("Network", torControl)
00046 {
00047   setDefault(SETTING_PROXY_TYPE,        NoProxy);
00048   setDefault(SETTING_PROXY_ADDRESS,     "");
00049   setDefault(SETTING_PROXY_USERNAME,    "");
00050   setDefault(SETTING_PROXY_PASSWORD,    "");
00051   setDefault(SETTING_USE_BRIDGES,       false);
00052   setDefault(SETTING_BRIDGE_LIST,       QStringList());
00053   setDefault(SETTING_FASCIST_FIREWALL,  false);
00054   setDefault(SETTING_TUNNEL_DIR_CONNS,  true);
00055   setDefault(SETTING_REACHABLE_ADDRESSES,
00056     QStringList() << "*:80" << "*:443");
00057 }
00058 
00059 /** Applies the current network configuration settings to Tor. If
00060  * <b>errmsg</b> is specified and an error occurs while applying the settings,
00061  * it will be set to a string describing the error. */
00062 bool
00063 NetworkSettings::apply(QString *errmsg)
00064 {
00065   QMultiHash<QString, QString> conf;
00066   quint32 torVersion = torControl()->getTorVersion();
00067 
00068   conf.insert(SETTING_REACHABLE_ADDRESSES,
00069     (getFascistFirewall() ? 
00070       localValue(SETTING_REACHABLE_ADDRESSES).toStringList().join(",") : ""));
00071  
00072   QString socks4, socks5, http, https;
00073   QString addr, user, pass, auth;
00074 
00075   addr = localValue(SETTING_PROXY_ADDRESS).toString();
00076   user = localValue(SETTING_PROXY_USERNAME).toString();
00077   pass = localValue(SETTING_PROXY_PASSWORD).toString();
00078 
00079   if (!user.isEmpty() || !pass.isEmpty())
00080     auth = QString("%1:%2").arg(user).arg(pass);
00081  
00082   switch (getProxyType()) {
00083     case NoProxy:
00084       break;
00085     case Socks4Proxy:
00086       socks4 = addr;
00087       break;
00088     case Socks5Proxy:
00089       socks5 = addr;
00090       break;
00091     case HttpHttpsProxy:
00092       http = addr;
00093       https = http;
00094       break;
00095   }
00096 
00097   if (torVersion >= 0x020201) {
00098     /* SOCKS support was implemented in 0.2.2.1 */
00099     conf.insert(SETTING_SOCKS4_PROXY, socks4);
00100     conf.insert(SETTING_SOCKS5_PROXY, socks5);
00101     conf.insert(SETTING_SOCKS5_USERNAME, user);
00102     conf.insert(SETTING_SOCKS5_PASSWORD, pass);
00103   }
00104 
00105   conf.insert(SETTING_HTTPS_PROXY, https);
00106   conf.insert(SETTING_HTTPS_PROXY_AUTH, auth);
00107 
00108   if (getUseBridges()) {
00109     /* We want to always enable TunnelDirConns and friends when using
00110      * bridge relays. */
00111     conf.insert(SETTING_TUNNEL_DIR_CONNS, "1");
00112     conf.insert(SETTING_PREFER_TUNNELED_DIR_CONNS, "1");
00113   } else if (torVersion <= 0x020021) {
00114     /* TunnelDirConns is enabled by default on Tor >= 0.2.0.22-rc, so don't
00115      * disable it if our Tor is recent enough. */
00116     conf.insert(SETTING_TUNNEL_DIR_CONNS, "0");
00117     conf.insert(SETTING_PREFER_TUNNELED_DIR_CONNS, "0");
00118   }
00119 
00120   if (torVersion >= 0x020003) {
00121     /* Do the bridge stuff only on Tor >= 0.2.0.3-alpha */
00122     QStringList bridges = localValue(SETTING_BRIDGE_LIST).toStringList();
00123     if (getUseBridges() && !bridges.isEmpty()) {
00124       conf.insert(SETTING_USE_BRIDGES, "1");
00125       conf.insert(SETTING_UPDATE_BRIDGES, "1");
00126       foreach (QString bridge, bridges) {
00127         conf.insert(SETTING_BRIDGE_LIST, bridge);
00128       }
00129     } else {
00130       conf.insert(SETTING_USE_BRIDGES, "0");
00131       conf.insert(SETTING_BRIDGE_LIST, "");
00132       conf.insert(SETTING_UPDATE_BRIDGES, "0");
00133     }
00134   }
00135   return torControl()->setConf(conf, errmsg);
00136 }
00137 
00138 /** Returns true if we need to set ReachableAddresses because we're behind a
00139  * restrictive firewall that limits the ports Tor can connect to. */
00140 bool
00141 NetworkSettings::getFascistFirewall()
00142 {
00143   return localValue(SETTING_FASCIST_FIREWALL).toBool();
00144 }
00145 
00146 /** Sets to <b>fascistFirewall</b> whether Tor should only create outgoing
00147  * connections to the list of ports specified in setReachablePorts().
00148  * \sa setReachablePorts() */
00149 void
00150 NetworkSettings::setFascistFirewall(bool fascistFirewall)
00151 {
00152   setValue(SETTING_FASCIST_FIREWALL, fascistFirewall);
00153 }
00154 
00155 /** Returns a list of ports to be specified in ReachableAddresses. */
00156 QList<quint16>
00157 NetworkSettings::getReachablePorts()
00158 {
00159   QList<quint16> reachablePorts;
00160   QStringList lineList;
00161   bool ok;
00162 
00163   lineList = value(SETTING_REACHABLE_ADDRESSES).toStringList();
00164   foreach (QString line, lineList) {
00165     foreach (QString address, line.split(",", QString::SkipEmptyParts)) {
00166       QStringList parts = address.split(":");
00167       if (parts.size() >= 2) {
00168         quint16 port = parts.at(1).toUInt(&ok);
00169         if (ok)
00170           reachablePorts << port;
00171       }
00172     }
00173   }
00174   return reachablePorts;
00175 }
00176 
00177 /** Sets the list of ports that will be specified in ReachableAddresses to
00178  * <b>reachablePorts</b>. */
00179 void
00180 NetworkSettings::setReachablePorts(const QList<quint16> &reachablePorts)
00181 {
00182   if (!reachablePorts.isEmpty()) {
00183     QStringList portList;
00184     foreach (quint16 port, reachablePorts) {
00185       portList << "*:" + QString::number(port);
00186     }
00187     setValue(SETTING_REACHABLE_ADDRESSES, portList);
00188   }
00189 }
00190 
00191 /** Returns the proxy type Tor is using, or NoProxy if it makes direct
00192  * connections. */ 
00193 NetworkSettings::ProxyType
00194 NetworkSettings::getProxyType()
00195 {
00196   QString type = value(SETTING_PROXY_TYPE).toString();
00197   return proxyTypeFromString(type);
00198 }
00199 
00200 /** Set the type of proxy Tor should use to <b>type</b>. */
00201 void
00202 NetworkSettings::setProxyType(ProxyType type)
00203 {
00204   setValue(SETTING_PROXY_TYPE, proxyTypeToString(type));
00205 }
00206 
00207 /** Returns the address of the proxy server Tor makes connections through. */
00208 QString
00209 NetworkSettings::getProxyAddress()
00210 {
00211   return value(SETTING_PROXY_ADDRESS).toString();
00212 }
00213 
00214 /** Sets the proxy address and port to <b>addr</b>. */
00215 void
00216 NetworkSettings::setProxyAddress(const QString &addr)
00217 {
00218   setValue(SETTING_PROXY_ADDRESS, addr);
00219 }
00220 
00221 /** Returns the username used to login to the proxy server. */
00222 QString
00223 NetworkSettings::getProxyUsername()
00224 {
00225   return value(SETTING_PROXY_USERNAME).toString();
00226 }
00227 
00228 /** Sets the proxy server username to <b>user</b>. */ 
00229 void
00230 NetworkSettings::setProxyUsername(const QString &user)
00231 {
00232   setValue(SETTING_PROXY_USERNAME, user);
00233 }
00234 
00235 /** Returns the password used to login to the proxy server. */
00236 QString
00237 NetworkSettings::getProxyPassword()
00238 {
00239   return value(SETTING_PROXY_PASSWORD).toString();
00240 }
00241 
00242 /** Sets the proxy server password to <b>pass</b>. */ 
00243 void
00244 NetworkSettings::setProxyPassword(const QString &pass)
00245 {
00246   setValue(SETTING_PROXY_PASSWORD, pass);
00247 }
00248 
00249 /** Returns true if Tor should try to use bridge nodes to access the Tor
00250  * network. */
00251 bool
00252 NetworkSettings::getUseBridges()
00253 {
00254   return value(SETTING_USE_BRIDGES).toBool();
00255 }
00256 
00257 /** Sets to <b>useBridges</b> whether Tor should try to use bridge nodes
00258  * to access the Tor network. */
00259 void
00260 NetworkSettings::setUseBridges(bool useBridges)
00261 {
00262   setValue(SETTING_USE_BRIDGES, useBridges);
00263 }
00264 
00265 /** Returns a list of bridge nodes Tor should use. */
00266 QStringList
00267 NetworkSettings::getBridgeList()
00268 {
00269   return value(SETTING_BRIDGE_LIST).toStringList();
00270 }
00271 
00272 /** Sets to <b>bridgeList</b> the list of bridge nodes Tor should use. */
00273 void
00274 NetworkSettings::setBridgeList(const QStringList &bridgeList)
00275 {
00276   setValue(SETTING_BRIDGE_LIST, bridgeList);
00277 }
00278 
00279 /** Returns true if Tor is configured to try to tunnel its directory
00280  * connections through a one-hop circuit. */
00281 bool
00282 NetworkSettings::getTunnelDirConns()
00283 {
00284   return value(SETTING_TUNNEL_DIR_CONNS).toBool();
00285 }
00286 
00287 /** Converts the ProxyType <b>type</b> to a string to store in the
00288  * configuration file. */
00289 QString
00290 NetworkSettings::proxyTypeToString(ProxyType type)
00291 {
00292   QString ret;
00293 
00294   switch (type) {
00295     case Socks4Proxy:
00296       ret = "socks4";
00297       break;
00298     case Socks5Proxy:
00299       ret = "socks5";
00300       break;
00301     case HttpHttpsProxy:
00302       ret = "httphttps";
00303       break;
00304     case NoProxy:
00305     default:
00306       ret = "none";
00307       break;
00308   }
00309 
00310   return ret;
00311 }
00312 
00313 /** Converts the proxy type string <b>type</b> to its ProxyType counterpart. */
00314 NetworkSettings::ProxyType
00315 NetworkSettings::proxyTypeFromString(const QString &type)
00316 {
00317   QString str = type.toLower();
00318   
00319   if (str == "socks4")
00320     return Socks4Proxy;
00321   if (str == "socks5")
00322     return Socks5Proxy;
00323   if (str == "httphttps")
00324     return HttpHttpsProxy;
00325 
00326   return NoProxy;
00327 }
00328