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