<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>stem.connection — Stem 1.1.0 documentation</title> <link rel="stylesheet" href="../../_static/haiku.css" type="text/css" /> <link rel="stylesheet" href="../../_static/pygments.css" type="text/css" /> <link rel="stylesheet" href="../../_static/print.css" type="text/css" /> <script type="text/javascript"> var DOCUMENTATION_OPTIONS = { URL_ROOT: '../../', VERSION: '1.1.0', COLLAPSE_INDEX: false, FILE_SUFFIX: '.html', HAS_SOURCE: true }; </script> <script type="text/javascript" src="../../_static/jquery.js"></script> <script type="text/javascript" src="../../_static/underscore.js"></script> <script type="text/javascript" src="../../_static/doctools.js"></script> <script type="text/javascript" src="../../_static/theme_extras.js"></script> <link rel="shortcut icon" href="../../_static/favicon.png"/> <link rel="top" title="Stem 1.1.0 documentation" href="../../index.html" /> <link rel="up" title="stem" href="../stem.html" /> </head> <body> <div class="header"><img class="rightlogo" src="../../_static/logo.png" alt="Logo"/><h1 class="heading"><a href="../../index.html"> <span>Stem Docs</span></a></h1> <h2 class="heading"><span>stem.connection</span></h2> </div> <div class="topnav"> <p> <ul id="navbar"> <li><a href="../../index.html">Home</a></li> <li><a href="../../tutorials.html">Tutorials</a> <ul> <li><a href="../../tutorials/the_little_relay_that_could.html">Hello World</a></li> <li><a href="../../tutorials/to_russia_with_love.html">Client Usage</a></li> <li><a href="../../tutorials/tortoise_and_the_hare.html">Event Listening</a></li> <li><a href="../../tutorials/mirror_mirror_on_the_wall.html">Tor Descriptors</a></li> <li><a href="../../tutorials/east_of_the_sun.html">Utilities</a></li> <li><a href="../../tutorials/double_double_toil_and_trouble.html">Examples</a></li> </ul> </li> <li><a href="../../api.html">API</a> <ul> <li><a href="../../api/control.html">stem.control</a></li> <li><a href="../../api/connection.html">stem.connection</a></li> <li><a href="../../api/socket.html">stem.socket</a></li> <li><a href="../../api/process.html">stem.process</a></li> <li><a href="../../api/response.html">stem.response</a></li> <li><a href="../../api/exit_policy.html">stem.exit_policy</a></li> <li><a href="../../api/version.html">stem.version</a></li> <li><a href="../../api.html#descriptors">Descriptors</a></li> <li><a href="../../api.html#utilities">Utilities</a></li> </ul> </li> <li><a href="https://trac.torproject.org/projects/tor/wiki/doc/stem">Development</a> <ul> <li><a href="../../faq.html">FAQ</a></li> <li><a href="../../change_log.html">Change Log</a></li> <li><a href="https://trac.torproject.org/projects/tor/wiki/doc/stem/bugs">Bug Tracker</a></li> <li><a href="../../download.html">Download</a></li> </ul> </li> </ul> </p> </div> <div class="content"> <h1>Source code for stem.connection</h1><div class="highlight"><pre> <span class="c"># Copyright 2011-2013, Damian Johnson and The Tor Project</span> <span class="c"># See LICENSE for licensing information</span> <span class="sd">"""</span> <span class="sd">Functions for connecting and authenticating to the tor process.</span> <span class="sd">The :func:`~stem.connection.connect_port` and</span> <span class="sd">:func:`~stem.connection.connect_socket_file` functions give an easy, one line</span> <span class="sd">method for getting an authenticated control connection. This is handy for CLI</span> <span class="sd">applications and the python interactive interpreter, but does several things</span> <span class="sd">that makes it undesirable for applications (uses stdin/stdout, suppresses</span> <span class="sd">exceptions, etc).</span> <span class="sd">The :func:`~stem.connection.authenticate` function, however, gives easy but</span> <span class="sd">fine-grained control over the authentication process. For instance...</span> <span class="sd">::</span> <span class="sd"> import sys</span> <span class="sd"> import getpass</span> <span class="sd"> import stem.connection</span> <span class="sd"> import stem.socket</span> <span class="sd"> try:</span> <span class="sd"> control_socket = stem.socket.ControlPort(port = 9051)</span> <span class="sd"> except stem.SocketError as exc:</span> <span class="sd"> print "Unable to connect to port 9051 (%s)" % exc</span> <span class="sd"> sys.exit(1)</span> <span class="sd"> try:</span> <span class="sd"> stem.connection.authenticate(control_socket)</span> <span class="sd"> except stem.connection.IncorrectSocketType:</span> <span class="sd"> print "Please check in your torrc that 9051 is the ControlPort."</span> <span class="sd"> print "Maybe you configured it to be the ORPort or SocksPort instead?"</span> <span class="sd"> sys.exit(1)</span> <span class="sd"> except stem.connection.MissingPassword:</span> <span class="sd"> controller_password = getpass.getpass("Controller password: ")</span> <span class="sd"> try:</span> <span class="sd"> stem.connection.authenticate_password(control_socket, controller_password)</span> <span class="sd"> except stem.connection.PasswordAuthFailed:</span> <span class="sd"> print "Unable to authenticate, password is incorrect"</span> <span class="sd"> sys.exit(1)</span> <span class="sd"> except stem.connection.AuthenticationFailure as exc:</span> <span class="sd"> print "Unable to authenticate: %s" % exc</span> <span class="sd"> sys.exit(1)</span> <span class="sd">**Module Overview:**</span> <span class="sd">::</span> <span class="sd"> connect_port - Convenience method to get an authenticated control connection</span> <span class="sd"> connect_socket_file - Similar to connect_port, but for control socket files</span> <span class="sd"> authenticate - Main method for authenticating to a control socket</span> <span class="sd"> authenticate_none - Authenticates to an open control socket</span> <span class="sd"> authenticate_password - Authenticates to a socket supporting password auth</span> <span class="sd"> authenticate_cookie - Authenticates to a socket supporting cookie auth</span> <span class="sd"> authenticate_safecookie - Authenticates to a socket supporting safecookie auth</span> <span class="sd"> get_protocolinfo - Issues a PROTOCOLINFO query</span> <span class="sd"> AuthenticationFailure - Base exception raised for authentication failures</span> <span class="sd"> |- UnrecognizedAuthMethods - Authentication methods are unsupported</span> <span class="sd"> |- IncorrectSocketType - Socket does not speak the tor control protocol</span> <span class="sd"> |</span> <span class="sd"> |- OpenAuthFailed - Failure when authenticating by an open socket</span> <span class="sd"> | +- OpenAuthRejected - Tor rejected this method of authentication</span> <span class="sd"> |</span> <span class="sd"> |- PasswordAuthFailed - Failure when authenticating by a password</span> <span class="sd"> | |- PasswordAuthRejected - Tor rejected this method of authentication</span> <span class="sd"> | |- IncorrectPassword - Password was rejected</span> <span class="sd"> | +- MissingPassword - Socket supports password auth but wasn't attempted</span> <span class="sd"> |</span> <span class="sd"> |- CookieAuthFailed - Failure when authenticating by a cookie</span> <span class="sd"> | |- CookieAuthRejected - Tor rejected this method of authentication</span> <span class="sd"> | |- IncorrectCookieValue - Authentication cookie was rejected</span> <span class="sd"> | |- IncorrectCookieSize - Size of the cookie file is incorrect</span> <span class="sd"> | |- UnreadableCookieFile - Unable to read the contents of the auth cookie</span> <span class="sd"> | +- AuthChallengeFailed - Failure completing the authchallenge request</span> <span class="sd"> | |- AuthChallengeUnsupported - Tor doesn't recognize the AUTHCHALLENGE command</span> <span class="sd"> | |- AuthSecurityFailure - Server provided the wrong nonce credentials</span> <span class="sd"> | |- InvalidClientNonce - The client nonce is invalid</span> <span class="sd"> | +- UnrecognizedAuthChallengeMethod - AUTHCHALLENGE does not support the given methods.</span> <span class="sd"> |</span> <span class="sd"> +- MissingAuthInfo - Unexpected PROTOCOLINFO response, missing auth info</span> <span class="sd"> |- NoAuthMethods - Missing any methods for authenticating</span> <span class="sd"> +- NoAuthCookie - Supports cookie auth but doesn't have its path</span> <span class="sd">.. data:: AuthMethod (enum)</span> <span class="sd"> Enumeration of PROTOCOLINFO responses for supported authentication methods.</span> <span class="sd"> ============== ===========</span> <span class="sd"> AuthMethod Description</span> <span class="sd"> ============== ===========</span> <span class="sd"> **NONE** No authentication required.</span> <span class="sd"> **PASSWORD** Password required, see tor's HashedControlPassword option.</span> <span class="sd"> **COOKIE** Contents of the cookie file required, see tor's CookieAuthentication option.</span> <span class="sd"> **SAFECOOKIE** Need to reply to a hmac challenge using the contents of the cookie file.</span> <span class="sd"> **UNKNOWN** Tor provided one or more authentication methods that we don't recognize, probably something new.</span> <span class="sd"> ============== ===========</span> <span class="sd">"""</span> <span class="kn">import</span> <span class="nn">binascii</span> <span class="kn">import</span> <span class="nn">getpass</span> <span class="kn">import</span> <span class="nn">os</span> <span class="kn">import</span> <span class="nn">stem.control</span> <span class="kn">import</span> <span class="nn">stem.response</span> <span class="kn">import</span> <span class="nn">stem.socket</span> <span class="kn">import</span> <span class="nn">stem.util.connection</span> <span class="kn">import</span> <span class="nn">stem.util.enum</span> <span class="kn">import</span> <span class="nn">stem.util.str_tools</span> <span class="kn">import</span> <span class="nn">stem.util.system</span> <span class="kn">import</span> <span class="nn">stem.version</span> <span class="kn">from</span> <span class="nn">stem.util</span> <span class="kn">import</span> <span class="n">log</span> <span class="n">AuthMethod</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">enum</span><span class="o">.</span><span class="n">Enum</span><span class="p">(</span><span class="s">"NONE"</span><span class="p">,</span> <span class="s">"PASSWORD"</span><span class="p">,</span> <span class="s">"COOKIE"</span><span class="p">,</span> <span class="s">"SAFECOOKIE"</span><span class="p">,</span> <span class="s">"UNKNOWN"</span><span class="p">)</span> <span class="n">CLIENT_HASH_CONSTANT</span> <span class="o">=</span> <span class="n">b</span><span class="s">"Tor safe cookie authentication controller-to-server hash"</span> <span class="n">SERVER_HASH_CONSTANT</span> <span class="o">=</span> <span class="n">b</span><span class="s">"Tor safe cookie authentication server-to-controller hash"</span> <div class="viewcode-block" id="connect_port"><a class="viewcode-back" href="../../api/connection.html#stem.connection.connect_port">[docs]</a><span class="k">def</span> <span class="nf">connect_port</span><span class="p">(</span><span class="n">address</span> <span class="o">=</span> <span class="s">"127.0.0.1"</span><span class="p">,</span> <span class="n">port</span> <span class="o">=</span> <span class="mi">9051</span><span class="p">,</span> <span class="n">password</span> <span class="o">=</span> <span class="bp">None</span><span class="p">,</span> <span class="n">chroot_path</span> <span class="o">=</span> <span class="bp">None</span><span class="p">,</span> <span class="n">controller</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">control</span><span class="o">.</span><span class="n">Controller</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Convenience function for quickly getting a control connection. This is very</span> <span class="sd"> handy for debugging or CLI setup, handling setup and prompting for a password</span> <span class="sd"> if necessary (and none is provided). If any issues arise this prints a</span> <span class="sd"> description of the problem and returns **None**.</span> <span class="sd"> :param str address: ip address of the controller</span> <span class="sd"> :param int port: port number of the controller</span> <span class="sd"> :param str password: passphrase to authenticate to the socket</span> <span class="sd"> :param str chroot_path: path prefix if in a chroot environment</span> <span class="sd"> :param Class controller: :class:`~stem.control.BaseController` subclass to be</span> <span class="sd"> returned, this provides a :class:`~stem.socket.ControlSocket` if **None**</span> <span class="sd"> :returns: authenticated control connection, the type based on the controller argument</span> <span class="sd"> """</span> <span class="k">try</span><span class="p">:</span> <span class="n">control_port</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">socket</span><span class="o">.</span><span class="n">ControlPort</span><span class="p">(</span><span class="n">address</span><span class="p">,</span> <span class="n">port</span><span class="p">)</span> <span class="k">except</span> <span class="n">stem</span><span class="o">.</span><span class="n">SocketError</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span> <span class="k">print</span> <span class="n">exc</span> <span class="k">return</span> <span class="bp">None</span> <span class="k">return</span> <span class="n">_connect</span><span class="p">(</span><span class="n">control_port</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">chroot_path</span><span class="p">,</span> <span class="n">controller</span><span class="p">)</span> </div> <div class="viewcode-block" id="connect_socket_file"><a class="viewcode-back" href="../../api/connection.html#stem.connection.connect_socket_file">[docs]</a><span class="k">def</span> <span class="nf">connect_socket_file</span><span class="p">(</span><span class="n">path</span> <span class="o">=</span> <span class="s">"/var/run/tor/control"</span><span class="p">,</span> <span class="n">password</span> <span class="o">=</span> <span class="bp">None</span><span class="p">,</span> <span class="n">chroot_path</span> <span class="o">=</span> <span class="bp">None</span><span class="p">,</span> <span class="n">controller</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">control</span><span class="o">.</span><span class="n">Controller</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Convenience function for quickly getting a control connection. For more</span> <span class="sd"> information see the :func:`~stem.connection.connect_port` function.</span> <span class="sd"> :param str path: path where the control socket is located</span> <span class="sd"> :param str password: passphrase to authenticate to the socket</span> <span class="sd"> :param str chroot_path: path prefix if in a chroot environment</span> <span class="sd"> :param Class controller: :class:`~stem.control.BaseController` subclass to be</span> <span class="sd"> returned, this provides a :class:`~stem.socket.ControlSocket` if **None**</span> <span class="sd"> :returns: authenticated control connection, the type based on the controller argument</span> <span class="sd"> """</span> <span class="k">try</span><span class="p">:</span> <span class="n">control_socket</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">socket</span><span class="o">.</span><span class="n">ControlSocketFile</span><span class="p">(</span><span class="n">path</span><span class="p">)</span> <span class="k">except</span> <span class="n">stem</span><span class="o">.</span><span class="n">SocketError</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span> <span class="k">print</span> <span class="n">exc</span> <span class="k">return</span> <span class="bp">None</span> <span class="k">return</span> <span class="n">_connect</span><span class="p">(</span><span class="n">control_socket</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">chroot_path</span><span class="p">,</span> <span class="n">controller</span><span class="p">)</span> </div> <span class="k">def</span> <span class="nf">_connect</span><span class="p">(</span><span class="n">control_socket</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">chroot_path</span><span class="p">,</span> <span class="n">controller</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Common implementation for the connect_* functions.</span> <span class="sd"> :param stem.socket.ControlSocket control_socket: socket being authenticated to</span> <span class="sd"> :param str password: passphrase to authenticate to the socket</span> <span class="sd"> :param str chroot_path: path prefix if in a chroot environment</span> <span class="sd"> :param Class controller: :class:`~stem.control.BaseController` subclass to be</span> <span class="sd"> returned, this provides a :class:`~stem.socket.ControlSocket` if **None**</span> <span class="sd"> :returns: authenticated control connection, the type based on the controller argument</span> <span class="sd"> """</span> <span class="k">try</span><span class="p">:</span> <span class="n">authenticate</span><span class="p">(</span><span class="n">control_socket</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">chroot_path</span><span class="p">)</span> <span class="k">if</span> <span class="n">controller</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span> <span class="k">return</span> <span class="n">control_socket</span> <span class="k">else</span><span class="p">:</span> <span class="k">return</span> <span class="n">controller</span><span class="p">(</span><span class="n">control_socket</span><span class="p">)</span> <span class="k">except</span> <span class="n">MissingPassword</span><span class="p">:</span> <span class="k">if</span> <span class="n">password</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"BUG: authenticate raised MissingPassword despite getting one"</span><span class="p">)</span> <span class="k">try</span><span class="p">:</span> <span class="n">password</span> <span class="o">=</span> <span class="n">getpass</span><span class="o">.</span><span class="n">getpass</span><span class="p">(</span><span class="s">"Controller password: "</span><span class="p">)</span> <span class="k">except</span> <span class="ne">KeyboardInterrupt</span><span class="p">:</span> <span class="k">return</span> <span class="bp">None</span> <span class="k">return</span> <span class="n">_connect</span><span class="p">(</span><span class="n">control_socket</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">chroot_path</span><span class="p">,</span> <span class="n">controller</span><span class="p">)</span> <span class="k">except</span> <span class="n">AuthenticationFailure</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span> <span class="n">control_socket</span><span class="o">.</span><span class="n">close</span><span class="p">()</span> <span class="k">print</span> <span class="s">"Unable to authenticate: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">exc</span> <span class="k">return</span> <span class="bp">None</span> <div class="viewcode-block" id="authenticate"><a class="viewcode-back" href="../../api/connection.html#stem.connection.authenticate">[docs]</a><span class="k">def</span> <span class="nf">authenticate</span><span class="p">(</span><span class="n">controller</span><span class="p">,</span> <span class="n">password</span> <span class="o">=</span> <span class="bp">None</span><span class="p">,</span> <span class="n">chroot_path</span> <span class="o">=</span> <span class="bp">None</span><span class="p">,</span> <span class="n">protocolinfo_response</span> <span class="o">=</span> <span class="bp">None</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Authenticates to a control socket using the information provided by a</span> <span class="sd"> PROTOCOLINFO response. In practice this will often be all we need to</span> <span class="sd"> authenticate, raising an exception if all attempts to authenticate fail.</span> <span class="sd"> All exceptions are subclasses of AuthenticationFailure so, in practice,</span> <span class="sd"> callers should catch the types of authentication failure that they care</span> <span class="sd"> about, then have a :class:`~stem.connection.AuthenticationFailure` catch-all</span> <span class="sd"> at the end.</span> <span class="sd"> This can authenticate to either a :class:`~stem.control.BaseController` or</span> <span class="sd"> :class:`~stem.socket.ControlSocket`.</span> <span class="sd"> :param controller: tor controller or socket to be authenticated</span> <span class="sd"> :param str password: passphrase to present to the socket if it uses password</span> <span class="sd"> authentication (skips password auth if **None**)</span> <span class="sd"> :param str chroot_path: path prefix if in a chroot environment</span> <span class="sd"> :param stem.response.protocolinfo.ProtocolInfoResponse protocolinfo_response:</span> <span class="sd"> tor protocolinfo response, this is retrieved on our own if **None**</span> <span class="sd"> :raises: If all attempts to authenticate fails then this will raise a</span> <span class="sd"> :class:`~stem.connection.AuthenticationFailure` subclass. Since this may</span> <span class="sd"> try multiple authentication methods it may encounter multiple exceptions.</span> <span class="sd"> If so then the exception this raises is prioritized as follows...</span> <span class="sd"> * :class:`stem.connection.IncorrectSocketType`</span> <span class="sd"> The controller does not speak the tor control protocol. Most often this</span> <span class="sd"> happened because the user confused the SocksPort or ORPort with the</span> <span class="sd"> ControlPort.</span> <span class="sd"> * :class:`stem.connection.UnrecognizedAuthMethods`</span> <span class="sd"> All of the authentication methods tor will accept are new and</span> <span class="sd"> unrecognized. Please upgrade stem and, if that doesn't work, file a</span> <span class="sd"> ticket on 'trac.torproject.org' and I'd be happy to add support.</span> <span class="sd"> * :class:`stem.connection.MissingPassword`</span> <span class="sd"> We were unable to authenticate but didn't attempt password authentication</span> <span class="sd"> because none was provided. You should prompt the user for a password and</span> <span class="sd"> try again via 'authenticate_password'.</span> <span class="sd"> * :class:`stem.connection.IncorrectPassword`</span> <span class="sd"> We were provided with a password but it was incorrect.</span> <span class="sd"> * :class:`stem.connection.IncorrectCookieSize`</span> <span class="sd"> Tor allows for authentication by reading it a cookie file, but that file</span> <span class="sd"> is the wrong size to be an authentication cookie.</span> <span class="sd"> * :class:`stem.connection.UnreadableCookieFile`</span> <span class="sd"> Tor allows for authentication by reading it a cookie file, but we can't</span> <span class="sd"> read that file (probably due to permissions).</span> <span class="sd"> * **\***:class:`stem.connection.IncorrectCookieValue`</span> <span class="sd"> Tor allows for authentication by reading it a cookie file, but rejected</span> <span class="sd"> the contents of that file.</span> <span class="sd"> * **\***:class:`stem.connection.AuthChallengeUnsupported`</span> <span class="sd"> Tor doesn't recognize the AUTHCHALLENGE command. This is probably a Tor</span> <span class="sd"> version prior to SAFECOOKIE being implement, but this exception shouldn't</span> <span class="sd"> arise because we won't attempt SAFECOOKIE auth unless Tor claims to</span> <span class="sd"> support it.</span> <span class="sd"> * **\***:class:`stem.connection.UnrecognizedAuthChallengeMethod`</span> <span class="sd"> Tor couldn't recognize the AUTHCHALLENGE method Stem sent to it. This</span> <span class="sd"> shouldn't happen at all.</span> <span class="sd"> * **\***:class:`stem.connection.InvalidClientNonce`</span> <span class="sd"> Tor says that the client nonce provided by Stem during the AUTHCHALLENGE</span> <span class="sd"> process is invalid.</span> <span class="sd"> * **\***:class:`stem.connection.AuthSecurityFailure`</span> <span class="sd"> Nonce value provided by the server was invalid.</span> <span class="sd"> * **\***:class:`stem.connection.OpenAuthRejected`</span> <span class="sd"> Tor says that it allows for authentication without any credentials, but</span> <span class="sd"> then rejected our authentication attempt.</span> <span class="sd"> * **\***:class:`stem.connection.MissingAuthInfo`</span> <span class="sd"> Tor provided us with a PROTOCOLINFO reply that is technically valid, but</span> <span class="sd"> missing the information we need to authenticate.</span> <span class="sd"> * **\***:class:`stem.connection.AuthenticationFailure`</span> <span class="sd"> There are numerous other ways that authentication could have failed</span> <span class="sd"> including socket failures, malformed controller responses, etc. These</span> <span class="sd"> mostly constitute transient failures or bugs.</span> <span class="sd"> **\*** In practice it is highly unusual for this to occur, being more of a</span> <span class="sd"> theoretical possibility rather than something you should expect. It's fine</span> <span class="sd"> to treat these as errors. If you have a use case where this commonly</span> <span class="sd"> happens, please file a ticket on 'trac.torproject.org'.</span> <span class="sd"> In the future new :class:`~stem.connection.AuthenticationFailure`</span> <span class="sd"> subclasses may be added to allow for better error handling.</span> <span class="sd"> """</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">protocolinfo_response</span><span class="p">:</span> <span class="k">try</span><span class="p">:</span> <span class="n">protocolinfo_response</span> <span class="o">=</span> <span class="n">get_protocolinfo</span><span class="p">(</span><span class="n">controller</span><span class="p">)</span> <span class="k">except</span> <span class="n">stem</span><span class="o">.</span><span class="n">ProtocolError</span><span class="p">:</span> <span class="k">raise</span> <span class="n">IncorrectSocketType</span><span class="p">(</span><span class="s">"unable to use the control socket"</span><span class="p">)</span> <span class="k">except</span> <span class="n">stem</span><span class="o">.</span><span class="n">SocketError</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span> <span class="k">raise</span> <span class="n">AuthenticationFailure</span><span class="p">(</span><span class="s">"socket connection failed (</span><span class="si">%s</span><span class="s">)"</span> <span class="o">%</span> <span class="n">exc</span><span class="p">)</span> <span class="n">auth_methods</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">protocolinfo_response</span><span class="o">.</span><span class="n">auth_methods</span><span class="p">)</span> <span class="n">auth_exceptions</span> <span class="o">=</span> <span class="p">[]</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">auth_methods</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span> <span class="k">raise</span> <span class="n">NoAuthMethods</span><span class="p">(</span><span class="s">"our PROTOCOLINFO response did not have any methods for authenticating"</span><span class="p">)</span> <span class="c"># remove authentication methods that are either unknown or for which we don't</span> <span class="c"># have an input</span> <span class="k">if</span> <span class="n">AuthMethod</span><span class="o">.</span><span class="n">UNKNOWN</span> <span class="ow">in</span> <span class="n">auth_methods</span><span class="p">:</span> <span class="n">auth_methods</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">AuthMethod</span><span class="o">.</span><span class="n">UNKNOWN</span><span class="p">)</span> <span class="n">unknown_methods</span> <span class="o">=</span> <span class="n">protocolinfo_response</span><span class="o">.</span><span class="n">unknown_auth_methods</span> <span class="n">plural_label</span> <span class="o">=</span> <span class="s">"s"</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">unknown_methods</span><span class="p">)</span> <span class="o">></span> <span class="mi">1</span> <span class="k">else</span> <span class="s">""</span> <span class="n">methods_label</span> <span class="o">=</span> <span class="s">", "</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">unknown_methods</span><span class="p">)</span> <span class="c"># we... er, can't do anything with only unrecognized auth types</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">auth_methods</span><span class="p">:</span> <span class="n">exc_msg</span> <span class="o">=</span> <span class="s">"unrecognized authentication method</span><span class="si">%s</span><span class="s"> (</span><span class="si">%s</span><span class="s">)"</span> <span class="o">%</span> <span class="p">(</span><span class="n">plural_label</span><span class="p">,</span> <span class="n">methods_label</span><span class="p">)</span> <span class="n">auth_exceptions</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">UnrecognizedAuthMethods</span><span class="p">(</span><span class="n">exc_msg</span><span class="p">,</span> <span class="n">unknown_methods</span><span class="p">))</span> <span class="k">else</span><span class="p">:</span> <span class="n">log</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">"Authenticating to a socket with unrecognized auth method</span><span class="si">%s</span><span class="s">, ignoring them: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">plural_label</span><span class="p">,</span> <span class="n">methods_label</span><span class="p">))</span> <span class="k">if</span> <span class="n">protocolinfo_response</span><span class="o">.</span><span class="n">cookie_path</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span> <span class="k">for</span> <span class="n">cookie_auth_method</span> <span class="ow">in</span> <span class="p">(</span><span class="n">AuthMethod</span><span class="o">.</span><span class="n">COOKIE</span><span class="p">,</span> <span class="n">AuthMethod</span><span class="o">.</span><span class="n">SAFECOOKIE</span><span class="p">):</span> <span class="k">if</span> <span class="n">cookie_auth_method</span> <span class="ow">in</span> <span class="n">auth_methods</span><span class="p">:</span> <span class="n">auth_methods</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">cookie_auth_method</span><span class="p">)</span> <span class="n">exc_msg</span> <span class="o">=</span> <span class="s">"our PROTOCOLINFO response did not have the location of our authentication cookie"</span> <span class="n">auth_exceptions</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">NoAuthCookie</span><span class="p">(</span><span class="n">exc_msg</span><span class="p">,</span> <span class="n">cookie_auth_method</span> <span class="o">==</span> <span class="n">AuthMethod</span><span class="o">.</span><span class="n">SAFECOOKIE</span><span class="p">))</span> <span class="k">if</span> <span class="n">AuthMethod</span><span class="o">.</span><span class="n">PASSWORD</span> <span class="ow">in</span> <span class="n">auth_methods</span> <span class="ow">and</span> <span class="n">password</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span> <span class="n">auth_methods</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">AuthMethod</span><span class="o">.</span><span class="n">PASSWORD</span><span class="p">)</span> <span class="n">auth_exceptions</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">MissingPassword</span><span class="p">(</span><span class="s">"no passphrase provided"</span><span class="p">))</span> <span class="c"># iterating over AuthMethods so we can try them in this order</span> <span class="k">for</span> <span class="n">auth_type</span> <span class="ow">in</span> <span class="p">(</span><span class="n">AuthMethod</span><span class="o">.</span><span class="n">NONE</span><span class="p">,</span> <span class="n">AuthMethod</span><span class="o">.</span><span class="n">PASSWORD</span><span class="p">,</span> <span class="n">AuthMethod</span><span class="o">.</span><span class="n">SAFECOOKIE</span><span class="p">,</span> <span class="n">AuthMethod</span><span class="o">.</span><span class="n">COOKIE</span><span class="p">):</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">auth_type</span> <span class="ow">in</span> <span class="n">auth_methods</span><span class="p">:</span> <span class="k">continue</span> <span class="k">try</span><span class="p">:</span> <span class="k">if</span> <span class="n">auth_type</span> <span class="o">==</span> <span class="n">AuthMethod</span><span class="o">.</span><span class="n">NONE</span><span class="p">:</span> <span class="n">authenticate_none</span><span class="p">(</span><span class="n">controller</span><span class="p">,</span> <span class="bp">False</span><span class="p">)</span> <span class="k">elif</span> <span class="n">auth_type</span> <span class="o">==</span> <span class="n">AuthMethod</span><span class="o">.</span><span class="n">PASSWORD</span><span class="p">:</span> <span class="n">authenticate_password</span><span class="p">(</span><span class="n">controller</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="bp">False</span><span class="p">)</span> <span class="k">elif</span> <span class="n">auth_type</span> <span class="ow">in</span> <span class="p">(</span><span class="n">AuthMethod</span><span class="o">.</span><span class="n">COOKIE</span><span class="p">,</span> <span class="n">AuthMethod</span><span class="o">.</span><span class="n">SAFECOOKIE</span><span class="p">):</span> <span class="n">cookie_path</span> <span class="o">=</span> <span class="n">protocolinfo_response</span><span class="o">.</span><span class="n">cookie_path</span> <span class="k">if</span> <span class="n">chroot_path</span><span class="p">:</span> <span class="n">cookie_path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">chroot_path</span><span class="p">,</span> <span class="n">cookie_path</span><span class="o">.</span><span class="n">lstrip</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">sep</span><span class="p">))</span> <span class="k">if</span> <span class="n">auth_type</span> <span class="o">==</span> <span class="n">AuthMethod</span><span class="o">.</span><span class="n">SAFECOOKIE</span><span class="p">:</span> <span class="n">authenticate_safecookie</span><span class="p">(</span><span class="n">controller</span><span class="p">,</span> <span class="n">cookie_path</span><span class="p">,</span> <span class="bp">False</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="n">authenticate_cookie</span><span class="p">(</span><span class="n">controller</span><span class="p">,</span> <span class="n">cookie_path</span><span class="p">,</span> <span class="bp">False</span><span class="p">)</span> <span class="k">return</span> <span class="c"># success!</span> <span class="k">except</span> <span class="n">OpenAuthRejected</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span> <span class="n">auth_exceptions</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">exc</span><span class="p">)</span> <span class="k">except</span> <span class="n">IncorrectPassword</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span> <span class="n">auth_exceptions</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">exc</span><span class="p">)</span> <span class="k">except</span> <span class="n">PasswordAuthRejected</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span> <span class="c"># Since the PROTOCOLINFO says password auth is available we can assume</span> <span class="c"># that if PasswordAuthRejected is raised it's being raised in error.</span> <span class="n">log</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">"The authenticate_password method raised a PasswordAuthRejected when password auth should be available. Stem may need to be corrected to recognize this response: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">exc</span><span class="p">)</span> <span class="n">auth_exceptions</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">IncorrectPassword</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">exc</span><span class="p">)))</span> <span class="k">except</span> <span class="n">AuthSecurityFailure</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span> <span class="n">log</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s">"Tor failed to provide the nonce expected for safecookie authentication. (</span><span class="si">%s</span><span class="s">)"</span> <span class="o">%</span> <span class="n">exc</span><span class="p">)</span> <span class="n">auth_exceptions</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">exc</span><span class="p">)</span> <span class="k">except</span> <span class="p">(</span><span class="n">InvalidClientNonce</span><span class="p">,</span> <span class="n">UnrecognizedAuthChallengeMethod</span><span class="p">,</span> <span class="n">AuthChallengeFailed</span><span class="p">)</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span> <span class="n">auth_exceptions</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">exc</span><span class="p">)</span> <span class="k">except</span> <span class="p">(</span><span class="n">IncorrectCookieSize</span><span class="p">,</span> <span class="n">UnreadableCookieFile</span><span class="p">,</span> <span class="n">IncorrectCookieValue</span><span class="p">)</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span> <span class="n">auth_exceptions</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">exc</span><span class="p">)</span> <span class="k">except</span> <span class="n">CookieAuthRejected</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span> <span class="n">auth_func</span> <span class="o">=</span> <span class="s">"authenticate_safecookie"</span> <span class="k">if</span> <span class="n">exc</span><span class="o">.</span><span class="n">is_safecookie</span> <span class="k">else</span> <span class="s">"authenticate_cookie"</span> <span class="n">log</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">"The </span><span class="si">%s</span><span class="s"> method raised a CookieAuthRejected when cookie auth should be available. Stem may need to be corrected to recognize this response: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">auth_func</span><span class="p">,</span> <span class="n">exc</span><span class="p">))</span> <span class="n">auth_exceptions</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">IncorrectCookieValue</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">exc</span><span class="p">),</span> <span class="n">exc</span><span class="o">.</span><span class="n">cookie_path</span><span class="p">,</span> <span class="n">exc</span><span class="o">.</span><span class="n">is_safecookie</span><span class="p">))</span> <span class="k">except</span> <span class="n">stem</span><span class="o">.</span><span class="n">ControllerError</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span> <span class="n">auth_exceptions</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">AuthenticationFailure</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">exc</span><span class="p">)))</span> <span class="c"># All authentication attempts failed. Raise the exception that takes priority</span> <span class="c"># according to our pydocs.</span> <span class="k">for</span> <span class="n">exc_type</span> <span class="ow">in</span> <span class="n">AUTHENTICATE_EXCEPTIONS</span><span class="p">:</span> <span class="k">for</span> <span class="n">auth_exc</span> <span class="ow">in</span> <span class="n">auth_exceptions</span><span class="p">:</span> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">auth_exc</span><span class="p">,</span> <span class="n">exc_type</span><span class="p">):</span> <span class="k">raise</span> <span class="n">auth_exc</span> <span class="c"># We really, really shouldn't get here. It means that auth_exceptions is</span> <span class="c"># either empty or contains something that isn't an AuthenticationFailure.</span> <span class="k">raise</span> <span class="ne">AssertionError</span><span class="p">(</span><span class="s">"BUG: Authentication failed without providing a recognized exception: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="nb">str</span><span class="p">(</span><span class="n">auth_exceptions</span><span class="p">))</span> </div> <div class="viewcode-block" id="authenticate_none"><a class="viewcode-back" href="../../api/connection.html#stem.connection.authenticate_none">[docs]</a><span class="k">def</span> <span class="nf">authenticate_none</span><span class="p">(</span><span class="n">controller</span><span class="p">,</span> <span class="n">suppress_ctl_errors</span> <span class="o">=</span> <span class="bp">True</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Authenticates to an open control socket. All control connections need to</span> <span class="sd"> authenticate before they can be used, even if tor hasn't been configured to</span> <span class="sd"> use any authentication.</span> <span class="sd"> If authentication fails tor will disconnect and we'll make a best effort</span> <span class="sd"> attempt to re-establish the connection. This may not succeed, so check</span> <span class="sd"> :func:`~stem.socket.ControlSocket.is_alive` before using the socket further.</span> <span class="sd"> This can authenticate to either a :class:`~stem.control.BaseController` or</span> <span class="sd"> :class:`~stem.socket.ControlSocket`.</span> <span class="sd"> For general usage use the :func:`~stem.connection.authenticate` function</span> <span class="sd"> instead.</span> <span class="sd"> :param controller: tor controller or socket to be authenticated</span> <span class="sd"> :param bool suppress_ctl_errors: reports raised</span> <span class="sd"> :class:`~stem.ControllerError` as authentication rejection if</span> <span class="sd"> **True**, otherwise they're re-raised</span> <span class="sd"> :raises: :class:`stem.connection.OpenAuthRejected` if the empty authentication credentials aren't accepted</span> <span class="sd"> """</span> <span class="k">try</span><span class="p">:</span> <span class="n">auth_response</span> <span class="o">=</span> <span class="n">_msg</span><span class="p">(</span><span class="n">controller</span><span class="p">,</span> <span class="s">"AUTHENTICATE"</span><span class="p">)</span> <span class="c"># if we got anything but an OK response then error</span> <span class="k">if</span> <span class="nb">str</span><span class="p">(</span><span class="n">auth_response</span><span class="p">)</span> <span class="o">!=</span> <span class="s">"OK"</span><span class="p">:</span> <span class="k">try</span><span class="p">:</span> <span class="n">controller</span><span class="o">.</span><span class="n">connect</span><span class="p">()</span> <span class="k">except</span><span class="p">:</span> <span class="k">pass</span> <span class="k">raise</span> <span class="n">OpenAuthRejected</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">auth_response</span><span class="p">),</span> <span class="n">auth_response</span><span class="p">)</span> <span class="k">except</span> <span class="n">stem</span><span class="o">.</span><span class="n">ControllerError</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span> <span class="k">try</span><span class="p">:</span> <span class="n">controller</span><span class="o">.</span><span class="n">connect</span><span class="p">()</span> <span class="k">except</span><span class="p">:</span> <span class="k">pass</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">suppress_ctl_errors</span><span class="p">:</span> <span class="k">raise</span> <span class="n">exc</span> <span class="k">else</span><span class="p">:</span> <span class="k">raise</span> <span class="n">OpenAuthRejected</span><span class="p">(</span><span class="s">"Socket failed (</span><span class="si">%s</span><span class="s">)"</span> <span class="o">%</span> <span class="n">exc</span><span class="p">)</span> </div> <div class="viewcode-block" id="authenticate_password"><a class="viewcode-back" href="../../api/connection.html#stem.connection.authenticate_password">[docs]</a><span class="k">def</span> <span class="nf">authenticate_password</span><span class="p">(</span><span class="n">controller</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">suppress_ctl_errors</span> <span class="o">=</span> <span class="bp">True</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Authenticates to a control socket that uses a password (via the</span> <span class="sd"> HashedControlPassword torrc option). Quotes in the password are escaped.</span> <span class="sd"> If authentication fails tor will disconnect and we'll make a best effort</span> <span class="sd"> attempt to re-establish the connection. This may not succeed, so check</span> <span class="sd"> :func:`~stem.socket.ControlSocket.is_alive` before using the socket further.</span> <span class="sd"> If you use this function directly, rather than</span> <span class="sd"> :func:`~stem.connection.authenticate`, we may mistakenly raise a</span> <span class="sd"> PasswordAuthRejected rather than IncorrectPassword. This is because we rely</span> <span class="sd"> on tor's error messaging which is liable to change in future versions</span> <span class="sd"> (:trac:`4817`).</span> <span class="sd"> This can authenticate to either a :class:`~stem.control.BaseController` or</span> <span class="sd"> :class:`~stem.socket.ControlSocket`.</span> <span class="sd"> For general usage use the :func:`~stem.connection.authenticate` function</span> <span class="sd"> instead.</span> <span class="sd"> :param controller: tor controller or socket to be authenticated</span> <span class="sd"> :param str password: passphrase to present to the socket</span> <span class="sd"> :param bool suppress_ctl_errors: reports raised</span> <span class="sd"> :class:`~stem.ControllerError` as authentication rejection if</span> <span class="sd"> **True**, otherwise they're re-raised</span> <span class="sd"> :raises:</span> <span class="sd"> * :class:`stem.connection.PasswordAuthRejected` if the socket doesn't</span> <span class="sd"> accept password authentication</span> <span class="sd"> * :class:`stem.connection.IncorrectPassword` if the authentication</span> <span class="sd"> credentials aren't accepted</span> <span class="sd"> """</span> <span class="c"># Escapes quotes. Tor can include those in the password hash, in which case</span> <span class="c"># it expects escaped quotes from the controller. For more information see...</span> <span class="c"># https://trac.torproject.org/projects/tor/ticket/4600</span> <span class="n">password</span> <span class="o">=</span> <span class="n">password</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s">'"'</span><span class="p">,</span> <span class="s">'</span><span class="se">\\</span><span class="s">"'</span><span class="p">)</span> <span class="k">try</span><span class="p">:</span> <span class="n">auth_response</span> <span class="o">=</span> <span class="n">_msg</span><span class="p">(</span><span class="n">controller</span><span class="p">,</span> <span class="s">"AUTHENTICATE </span><span class="se">\"</span><span class="si">%s</span><span class="se">\"</span><span class="s">"</span> <span class="o">%</span> <span class="n">password</span><span class="p">)</span> <span class="c"># if we got anything but an OK response then error</span> <span class="k">if</span> <span class="nb">str</span><span class="p">(</span><span class="n">auth_response</span><span class="p">)</span> <span class="o">!=</span> <span class="s">"OK"</span><span class="p">:</span> <span class="k">try</span><span class="p">:</span> <span class="n">controller</span><span class="o">.</span><span class="n">connect</span><span class="p">()</span> <span class="k">except</span><span class="p">:</span> <span class="k">pass</span> <span class="c"># all we have to go on is the error message from tor...</span> <span class="c"># Password did not match HashedControlPassword value value from configuration...</span> <span class="c"># Password did not match HashedControlPassword *or*...</span> <span class="k">if</span> <span class="s">"Password did not match HashedControlPassword"</span> <span class="ow">in</span> <span class="nb">str</span><span class="p">(</span><span class="n">auth_response</span><span class="p">):</span> <span class="k">raise</span> <span class="n">IncorrectPassword</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">auth_response</span><span class="p">),</span> <span class="n">auth_response</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="k">raise</span> <span class="n">PasswordAuthRejected</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">auth_response</span><span class="p">),</span> <span class="n">auth_response</span><span class="p">)</span> <span class="k">except</span> <span class="n">stem</span><span class="o">.</span><span class="n">ControllerError</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span> <span class="k">try</span><span class="p">:</span> <span class="n">controller</span><span class="o">.</span><span class="n">connect</span><span class="p">()</span> <span class="k">except</span><span class="p">:</span> <span class="k">pass</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">suppress_ctl_errors</span><span class="p">:</span> <span class="k">raise</span> <span class="n">exc</span> <span class="k">else</span><span class="p">:</span> <span class="k">raise</span> <span class="n">PasswordAuthRejected</span><span class="p">(</span><span class="s">"Socket failed (</span><span class="si">%s</span><span class="s">)"</span> <span class="o">%</span> <span class="n">exc</span><span class="p">)</span> </div> <div class="viewcode-block" id="authenticate_cookie"><a class="viewcode-back" href="../../api/connection.html#stem.connection.authenticate_cookie">[docs]</a><span class="k">def</span> <span class="nf">authenticate_cookie</span><span class="p">(</span><span class="n">controller</span><span class="p">,</span> <span class="n">cookie_path</span><span class="p">,</span> <span class="n">suppress_ctl_errors</span> <span class="o">=</span> <span class="bp">True</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Authenticates to a control socket that uses the contents of an authentication</span> <span class="sd"> cookie (generated via the CookieAuthentication torrc option). This does basic</span> <span class="sd"> validation that this is a cookie before presenting the contents to the</span> <span class="sd"> socket.</span> <span class="sd"> The :class:`~stem.connection.IncorrectCookieSize` and</span> <span class="sd"> :class:`~stem.connection.UnreadableCookieFile` exceptions take precedence</span> <span class="sd"> over the other types.</span> <span class="sd"> If authentication fails tor will disconnect and we'll make a best effort</span> <span class="sd"> attempt to re-establish the connection. This may not succeed, so check</span> <span class="sd"> :func:`~stem.socket.ControlSocket.is_alive` before using the socket further.</span> <span class="sd"> If you use this function directly, rather than</span> <span class="sd"> :func:`~stem.connection.authenticate`, we may mistakenly raise a</span> <span class="sd"> :class:`~stem.connection.CookieAuthRejected` rather than</span> <span class="sd"> :class:`~stem.connection.IncorrectCookieValue`. This is because we rely on</span> <span class="sd"> tor's error messaging which is liable to change in future versions</span> <span class="sd"> (:trac:`4817`).</span> <span class="sd"> This can authenticate to either a :class:`~stem.control.BaseController` or</span> <span class="sd"> :class:`~stem.socket.ControlSocket`.</span> <span class="sd"> For general usage use the :func:`~stem.connection.authenticate` function</span> <span class="sd"> instead.</span> <span class="sd"> :param controller: tor controller or socket to be authenticated</span> <span class="sd"> :param str cookie_path: path of the authentication cookie to send to tor</span> <span class="sd"> :param bool suppress_ctl_errors: reports raised</span> <span class="sd"> :class:`~stem.ControllerError` as authentication rejection if</span> <span class="sd"> **True**, otherwise they're re-raised</span> <span class="sd"> :raises:</span> <span class="sd"> * :class:`stem.connection.IncorrectCookieSize` if the cookie file's size</span> <span class="sd"> is wrong</span> <span class="sd"> * :class:`stem.connection.UnreadableCookieFile` if the cookie file doesn't</span> <span class="sd"> exist or we're unable to read it</span> <span class="sd"> * :class:`stem.connection.CookieAuthRejected` if cookie authentication is</span> <span class="sd"> attempted but the socket doesn't accept it</span> <span class="sd"> * :class:`stem.connection.IncorrectCookieValue` if the cookie file's value</span> <span class="sd"> is rejected</span> <span class="sd"> """</span> <span class="n">cookie_data</span> <span class="o">=</span> <span class="n">_read_cookie</span><span class="p">(</span><span class="n">cookie_path</span><span class="p">,</span> <span class="bp">False</span><span class="p">)</span> <span class="k">try</span><span class="p">:</span> <span class="c"># binascii.b2a_hex() takes a byte string and returns one too. With python 3</span> <span class="c"># this is a problem because string formatting for byte strings includes the</span> <span class="c"># b'' wrapper...</span> <span class="c">#</span> <span class="c"># >>> "AUTHENTICATE %s" % b'content'</span> <span class="c"># "AUTHENTICATE b'content'"</span> <span class="c">#</span> <span class="c"># This seems dumb but oh well. Converting the result to unicode so it won't</span> <span class="c"># misbehave.</span> <span class="n">auth_token_hex</span> <span class="o">=</span> <span class="n">binascii</span><span class="o">.</span><span class="n">b2a_hex</span><span class="p">(</span><span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">str_tools</span><span class="o">.</span><span class="n">_to_bytes</span><span class="p">(</span><span class="n">cookie_data</span><span class="p">))</span> <span class="n">msg</span> <span class="o">=</span> <span class="s">"AUTHENTICATE </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">str_tools</span><span class="o">.</span><span class="n">_to_unicode</span><span class="p">(</span><span class="n">auth_token_hex</span><span class="p">)</span> <span class="n">auth_response</span> <span class="o">=</span> <span class="n">_msg</span><span class="p">(</span><span class="n">controller</span><span class="p">,</span> <span class="n">msg</span><span class="p">)</span> <span class="c"># if we got anything but an OK response then error</span> <span class="k">if</span> <span class="nb">str</span><span class="p">(</span><span class="n">auth_response</span><span class="p">)</span> <span class="o">!=</span> <span class="s">"OK"</span><span class="p">:</span> <span class="k">try</span><span class="p">:</span> <span class="n">controller</span><span class="o">.</span><span class="n">connect</span><span class="p">()</span> <span class="k">except</span><span class="p">:</span> <span class="k">pass</span> <span class="c"># all we have to go on is the error message from tor...</span> <span class="c"># ... Authentication cookie did not match expected value.</span> <span class="c"># ... *or* authentication cookie.</span> <span class="k">if</span> <span class="s">"*or* authentication cookie."</span> <span class="ow">in</span> <span class="nb">str</span><span class="p">(</span><span class="n">auth_response</span><span class="p">)</span> <span class="ow">or</span> \ <span class="s">"Authentication cookie did not match expected value."</span> <span class="ow">in</span> <span class="nb">str</span><span class="p">(</span><span class="n">auth_response</span><span class="p">):</span> <span class="k">raise</span> <span class="n">IncorrectCookieValue</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">auth_response</span><span class="p">),</span> <span class="n">cookie_path</span><span class="p">,</span> <span class="bp">False</span><span class="p">,</span> <span class="n">auth_response</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="k">raise</span> <span class="n">CookieAuthRejected</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">auth_response</span><span class="p">),</span> <span class="n">cookie_path</span><span class="p">,</span> <span class="bp">False</span><span class="p">,</span> <span class="n">auth_response</span><span class="p">)</span> <span class="k">except</span> <span class="n">stem</span><span class="o">.</span><span class="n">ControllerError</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span> <span class="k">try</span><span class="p">:</span> <span class="n">controller</span><span class="o">.</span><span class="n">connect</span><span class="p">()</span> <span class="k">except</span><span class="p">:</span> <span class="k">pass</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">suppress_ctl_errors</span><span class="p">:</span> <span class="k">raise</span> <span class="n">exc</span> <span class="k">else</span><span class="p">:</span> <span class="k">raise</span> <span class="n">CookieAuthRejected</span><span class="p">(</span><span class="s">"Socket failed (</span><span class="si">%s</span><span class="s">)"</span> <span class="o">%</span> <span class="n">exc</span><span class="p">,</span> <span class="n">cookie_path</span><span class="p">,</span> <span class="bp">False</span><span class="p">)</span> </div> <div class="viewcode-block" id="authenticate_safecookie"><a class="viewcode-back" href="../../api/connection.html#stem.connection.authenticate_safecookie">[docs]</a><span class="k">def</span> <span class="nf">authenticate_safecookie</span><span class="p">(</span><span class="n">controller</span><span class="p">,</span> <span class="n">cookie_path</span><span class="p">,</span> <span class="n">suppress_ctl_errors</span> <span class="o">=</span> <span class="bp">True</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Authenticates to a control socket using the safe cookie method, which is</span> <span class="sd"> enabled by setting the CookieAuthentication torrc option on Tor client's which</span> <span class="sd"> support it.</span> <span class="sd"> Authentication with this is a two-step process...</span> <span class="sd"> 1. send a nonce to the server and receives a challenge from the server for</span> <span class="sd"> the cookie's contents</span> <span class="sd"> 2. generate a hash digest using the challenge received in the first step, and</span> <span class="sd"> use it to authenticate the controller</span> <span class="sd"> The :class:`~stem.connection.IncorrectCookieSize` and</span> <span class="sd"> :class:`~stem.connection.UnreadableCookieFile` exceptions take precedence</span> <span class="sd"> over the other exception types.</span> <span class="sd"> The :class:`~stem.connection.AuthChallengeUnsupported`,</span> <span class="sd"> :class:`~stem.connection.UnrecognizedAuthChallengeMethod`,</span> <span class="sd"> :class:`~stem.connection.InvalidClientNonce` and</span> <span class="sd"> :class:`~stem.connection.CookieAuthRejected` exceptions are next in the order</span> <span class="sd"> of precedence. Depending on the reason, one of these is raised if the first</span> <span class="sd"> (AUTHCHALLENGE) step fails.</span> <span class="sd"> In the second (AUTHENTICATE) step,</span> <span class="sd"> :class:`~stem.connection.IncorrectCookieValue` or</span> <span class="sd"> :class:`~stem.connection.CookieAuthRejected` maybe raised.</span> <span class="sd"> If authentication fails tor will disconnect and we'll make a best effort</span> <span class="sd"> attempt to re-establish the connection. This may not succeed, so check</span> <span class="sd"> :func:`~stem.socket.ControlSocket.is_alive` before using the socket further.</span> <span class="sd"> For general usage use the :func:`~stem.connection.authenticate` function</span> <span class="sd"> instead.</span> <span class="sd"> :param controller: tor controller or socket to be authenticated</span> <span class="sd"> :param str cookie_path: path of the authentication cookie to send to tor</span> <span class="sd"> :param bool suppress_ctl_errors: reports raised</span> <span class="sd"> :class:`~stem.ControllerError` as authentication rejection if</span> <span class="sd"> **True**, otherwise they're re-raised</span> <span class="sd"> :raises:</span> <span class="sd"> * :class:`stem.connection.IncorrectCookieSize` if the cookie file's size</span> <span class="sd"> is wrong</span> <span class="sd"> * :class:`stem.connection.UnreadableCookieFile` if the cookie file doesn't</span> <span class="sd"> exist or we're unable to read it</span> <span class="sd"> * :class:`stem.connection.CookieAuthRejected` if cookie authentication is</span> <span class="sd"> attempted but the socket doesn't accept it</span> <span class="sd"> * :class:`stem.connection.IncorrectCookieValue` if the cookie file's value</span> <span class="sd"> is rejected</span> <span class="sd"> * :class:`stem.connection.UnrecognizedAuthChallengeMethod` if the Tor</span> <span class="sd"> client fails to recognize the AuthChallenge method</span> <span class="sd"> * :class:`stem.connection.AuthChallengeUnsupported` if AUTHCHALLENGE is</span> <span class="sd"> unimplemented, or if unable to parse AUTHCHALLENGE response</span> <span class="sd"> * :class:`stem.connection.AuthSecurityFailure` if AUTHCHALLENGE's response</span> <span class="sd"> looks like a security attack</span> <span class="sd"> * :class:`stem.connection.InvalidClientNonce` if stem's AUTHCHALLENGE</span> <span class="sd"> client nonce is rejected for being invalid</span> <span class="sd"> """</span> <span class="n">cookie_data</span> <span class="o">=</span> <span class="n">_read_cookie</span><span class="p">(</span><span class="n">cookie_path</span><span class="p">,</span> <span class="bp">True</span><span class="p">)</span> <span class="n">client_nonce</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">urandom</span><span class="p">(</span><span class="mi">32</span><span class="p">)</span> <span class="k">try</span><span class="p">:</span> <span class="n">client_nonce_hex</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">str_tools</span><span class="o">.</span><span class="n">_to_unicode</span><span class="p">(</span><span class="n">binascii</span><span class="o">.</span><span class="n">b2a_hex</span><span class="p">(</span><span class="n">client_nonce</span><span class="p">))</span> <span class="n">authchallenge_response</span> <span class="o">=</span> <span class="n">_msg</span><span class="p">(</span><span class="n">controller</span><span class="p">,</span> <span class="s">"AUTHCHALLENGE SAFECOOKIE </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">client_nonce_hex</span><span class="p">)</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">authchallenge_response</span><span class="o">.</span><span class="n">is_ok</span><span class="p">():</span> <span class="k">try</span><span class="p">:</span> <span class="n">controller</span><span class="o">.</span><span class="n">connect</span><span class="p">()</span> <span class="k">except</span><span class="p">:</span> <span class="k">pass</span> <span class="n">authchallenge_response_str</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">authchallenge_response</span><span class="p">)</span> <span class="k">if</span> <span class="s">"Authentication required."</span> <span class="ow">in</span> <span class="n">authchallenge_response_str</span><span class="p">:</span> <span class="k">raise</span> <span class="n">AuthChallengeUnsupported</span><span class="p">(</span><span class="s">"SAFECOOKIE authentication isn't supported"</span><span class="p">,</span> <span class="n">cookie_path</span><span class="p">)</span> <span class="k">elif</span> <span class="s">"AUTHCHALLENGE only supports"</span> <span class="ow">in</span> <span class="n">authchallenge_response_str</span><span class="p">:</span> <span class="k">raise</span> <span class="n">UnrecognizedAuthChallengeMethod</span><span class="p">(</span><span class="n">authchallenge_response_str</span><span class="p">,</span> <span class="n">cookie_path</span><span class="p">)</span> <span class="k">elif</span> <span class="s">"Invalid base16 client nonce"</span> <span class="ow">in</span> <span class="n">authchallenge_response_str</span><span class="p">:</span> <span class="k">raise</span> <span class="n">InvalidClientNonce</span><span class="p">(</span><span class="n">authchallenge_response_str</span><span class="p">,</span> <span class="n">cookie_path</span><span class="p">)</span> <span class="k">elif</span> <span class="s">"Cookie authentication is disabled"</span> <span class="ow">in</span> <span class="n">authchallenge_response_str</span><span class="p">:</span> <span class="k">raise</span> <span class="n">CookieAuthRejected</span><span class="p">(</span><span class="n">authchallenge_response_str</span><span class="p">,</span> <span class="n">cookie_path</span><span class="p">,</span> <span class="bp">True</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="k">raise</span> <span class="n">AuthChallengeFailed</span><span class="p">(</span><span class="n">authchallenge_response</span><span class="p">,</span> <span class="n">cookie_path</span><span class="p">)</span> <span class="k">except</span> <span class="n">stem</span><span class="o">.</span><span class="n">ControllerError</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span> <span class="k">try</span><span class="p">:</span> <span class="n">controller</span><span class="o">.</span><span class="n">connect</span><span class="p">()</span> <span class="k">except</span><span class="p">:</span> <span class="k">pass</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">suppress_ctl_errors</span><span class="p">:</span> <span class="k">raise</span> <span class="n">exc</span> <span class="k">else</span><span class="p">:</span> <span class="k">raise</span> <span class="n">AuthChallengeFailed</span><span class="p">(</span><span class="s">"Socket failed (</span><span class="si">%s</span><span class="s">)"</span> <span class="o">%</span> <span class="n">exc</span><span class="p">,</span> <span class="n">cookie_path</span><span class="p">,</span> <span class="bp">True</span><span class="p">)</span> <span class="k">try</span><span class="p">:</span> <span class="n">stem</span><span class="o">.</span><span class="n">response</span><span class="o">.</span><span class="n">convert</span><span class="p">(</span><span class="s">"AUTHCHALLENGE"</span><span class="p">,</span> <span class="n">authchallenge_response</span><span class="p">)</span> <span class="k">except</span> <span class="n">stem</span><span class="o">.</span><span class="n">ProtocolError</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">suppress_ctl_errors</span><span class="p">:</span> <span class="k">raise</span> <span class="n">exc</span> <span class="k">else</span><span class="p">:</span> <span class="k">raise</span> <span class="n">AuthChallengeFailed</span><span class="p">(</span><span class="s">"Unable to parse AUTHCHALLENGE response: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">exc</span><span class="p">,</span> <span class="n">cookie_path</span><span class="p">)</span> <span class="n">expected_server_hash</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">_hmac_sha256</span><span class="p">(</span> <span class="n">SERVER_HASH_CONSTANT</span><span class="p">,</span> <span class="n">cookie_data</span> <span class="o">+</span> <span class="n">client_nonce</span> <span class="o">+</span> <span class="n">authchallenge_response</span><span class="o">.</span><span class="n">server_nonce</span><span class="p">)</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">_cryptovariables_equal</span><span class="p">(</span><span class="n">authchallenge_response</span><span class="o">.</span><span class="n">server_hash</span><span class="p">,</span> <span class="n">expected_server_hash</span><span class="p">):</span> <span class="k">raise</span> <span class="n">AuthSecurityFailure</span><span class="p">(</span><span class="s">"Tor provided the wrong server nonce"</span><span class="p">,</span> <span class="n">cookie_path</span><span class="p">)</span> <span class="k">try</span><span class="p">:</span> <span class="n">client_hash</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">_hmac_sha256</span><span class="p">(</span> <span class="n">CLIENT_HASH_CONSTANT</span><span class="p">,</span> <span class="n">cookie_data</span> <span class="o">+</span> <span class="n">client_nonce</span> <span class="o">+</span> <span class="n">authchallenge_response</span><span class="o">.</span><span class="n">server_nonce</span><span class="p">)</span> <span class="n">auth_response</span> <span class="o">=</span> <span class="n">_msg</span><span class="p">(</span><span class="n">controller</span><span class="p">,</span> <span class="s">"AUTHENTICATE </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">str_tools</span><span class="o">.</span><span class="n">_to_unicode</span><span class="p">(</span><span class="n">binascii</span><span class="o">.</span><span class="n">b2a_hex</span><span class="p">(</span><span class="n">client_hash</span><span class="p">)))</span> <span class="k">except</span> <span class="n">stem</span><span class="o">.</span><span class="n">ControllerError</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span> <span class="k">try</span><span class="p">:</span> <span class="n">controller</span><span class="o">.</span><span class="n">connect</span><span class="p">()</span> <span class="k">except</span><span class="p">:</span> <span class="k">pass</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">suppress_ctl_errors</span><span class="p">:</span> <span class="k">raise</span> <span class="n">exc</span> <span class="k">else</span><span class="p">:</span> <span class="k">raise</span> <span class="n">CookieAuthRejected</span><span class="p">(</span><span class="s">"Socket failed (</span><span class="si">%s</span><span class="s">)"</span> <span class="o">%</span> <span class="n">exc</span><span class="p">,</span> <span class="n">cookie_path</span><span class="p">,</span> <span class="bp">True</span><span class="p">,</span> <span class="n">auth_response</span><span class="p">)</span> <span class="c"># if we got anything but an OK response then err</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">auth_response</span><span class="o">.</span><span class="n">is_ok</span><span class="p">():</span> <span class="k">try</span><span class="p">:</span> <span class="n">controller</span><span class="o">.</span><span class="n">connect</span><span class="p">()</span> <span class="k">except</span><span class="p">:</span> <span class="k">pass</span> <span class="c"># all we have to go on is the error message from tor...</span> <span class="c"># ... Safe cookie response did not match expected value</span> <span class="c"># ... *or* authentication cookie.</span> <span class="k">if</span> <span class="s">"*or* authentication cookie."</span> <span class="ow">in</span> <span class="nb">str</span><span class="p">(</span><span class="n">auth_response</span><span class="p">)</span> <span class="ow">or</span> \ <span class="s">"Safe cookie response did not match expected value"</span> <span class="ow">in</span> <span class="nb">str</span><span class="p">(</span><span class="n">auth_response</span><span class="p">):</span> <span class="k">raise</span> <span class="n">IncorrectCookieValue</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">auth_response</span><span class="p">),</span> <span class="n">cookie_path</span><span class="p">,</span> <span class="bp">True</span><span class="p">,</span> <span class="n">auth_response</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="k">raise</span> <span class="n">CookieAuthRejected</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">auth_response</span><span class="p">),</span> <span class="n">cookie_path</span><span class="p">,</span> <span class="bp">True</span><span class="p">,</span> <span class="n">auth_response</span><span class="p">)</span> </div> <div class="viewcode-block" id="get_protocolinfo"><a class="viewcode-back" href="../../api/connection.html#stem.connection.get_protocolinfo">[docs]</a><span class="k">def</span> <span class="nf">get_protocolinfo</span><span class="p">(</span><span class="n">controller</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Issues a PROTOCOLINFO query to a control socket, getting information about</span> <span class="sd"> the tor process running on it. If the socket is already closed then it is</span> <span class="sd"> first reconnected.</span> <span class="sd"> According to the control spec the cookie_file is an absolute path. However,</span> <span class="sd"> this often is not the case (especially for the Tor Browser Bundle). If the</span> <span class="sd"> path is relative then we'll make an attempt (which may not work) to correct</span> <span class="sd"> this (:trac:`1101`).</span> <span class="sd"> This can authenticate to either a :class:`~stem.control.BaseController` or</span> <span class="sd"> :class:`~stem.socket.ControlSocket`.</span> <span class="sd"> :param controller: tor controller or socket to be queried</span> <span class="sd"> :returns: :class:`~stem.response.protocolinfo.ProtocolInfoResponse` provided by tor</span> <span class="sd"> :raises:</span> <span class="sd"> * :class:`stem.ProtocolError` if the PROTOCOLINFO response is</span> <span class="sd"> malformed</span> <span class="sd"> * :class:`stem.SocketError` if problems arise in establishing or</span> <span class="sd"> using the socket</span> <span class="sd"> """</span> <span class="k">try</span><span class="p">:</span> <span class="n">protocolinfo_response</span> <span class="o">=</span> <span class="n">_msg</span><span class="p">(</span><span class="n">controller</span><span class="p">,</span> <span class="s">"PROTOCOLINFO 1"</span><span class="p">)</span> <span class="k">except</span><span class="p">:</span> <span class="n">protocolinfo_response</span> <span class="o">=</span> <span class="bp">None</span> <span class="c"># Tor hangs up on sockets after receiving a PROTOCOLINFO query if it isn't</span> <span class="c"># next followed by authentication. Transparently reconnect if that happens.</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">protocolinfo_response</span> <span class="ow">or</span> <span class="nb">str</span><span class="p">(</span><span class="n">protocolinfo_response</span><span class="p">)</span> <span class="o">==</span> <span class="s">"Authentication required."</span><span class="p">:</span> <span class="n">controller</span><span class="o">.</span><span class="n">connect</span><span class="p">()</span> <span class="k">try</span><span class="p">:</span> <span class="n">protocolinfo_response</span> <span class="o">=</span> <span class="n">_msg</span><span class="p">(</span><span class="n">controller</span><span class="p">,</span> <span class="s">"PROTOCOLINFO 1"</span><span class="p">)</span> <span class="k">except</span> <span class="n">stem</span><span class="o">.</span><span class="n">SocketClosed</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span> <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">SocketError</span><span class="p">(</span><span class="n">exc</span><span class="p">)</span> <span class="n">stem</span><span class="o">.</span><span class="n">response</span><span class="o">.</span><span class="n">convert</span><span class="p">(</span><span class="s">"PROTOCOLINFO"</span><span class="p">,</span> <span class="n">protocolinfo_response</span><span class="p">)</span> <span class="c"># attempt to expand relative cookie paths</span> <span class="k">if</span> <span class="n">protocolinfo_response</span><span class="o">.</span><span class="n">cookie_path</span><span class="p">:</span> <span class="n">_expand_cookie_path</span><span class="p">(</span><span class="n">protocolinfo_response</span><span class="p">,</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">system</span><span class="o">.</span><span class="n">get_pid_by_name</span><span class="p">,</span> <span class="s">"tor"</span><span class="p">)</span> <span class="c"># attempt to expand relative cookie paths via the control port or socket file</span> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">controller</span><span class="p">,</span> <span class="n">stem</span><span class="o">.</span><span class="n">socket</span><span class="o">.</span><span class="n">ControlSocket</span><span class="p">):</span> <span class="n">control_socket</span> <span class="o">=</span> <span class="n">controller</span> <span class="k">else</span><span class="p">:</span> <span class="n">control_socket</span> <span class="o">=</span> <span class="n">controller</span><span class="o">.</span><span class="n">get_socket</span><span class="p">()</span> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">control_socket</span><span class="p">,</span> <span class="n">stem</span><span class="o">.</span><span class="n">socket</span><span class="o">.</span><span class="n">ControlPort</span><span class="p">):</span> <span class="k">if</span> <span class="n">control_socket</span><span class="o">.</span><span class="n">get_address</span><span class="p">()</span> <span class="o">==</span> <span class="s">"127.0.0.1"</span><span class="p">:</span> <span class="n">pid_method</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">system</span><span class="o">.</span><span class="n">get_pid_by_port</span> <span class="n">_expand_cookie_path</span><span class="p">(</span><span class="n">protocolinfo_response</span><span class="p">,</span> <span class="n">pid_method</span><span class="p">,</span> <span class="n">control_socket</span><span class="o">.</span><span class="n">get_port</span><span class="p">())</span> <span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">control_socket</span><span class="p">,</span> <span class="n">stem</span><span class="o">.</span><span class="n">socket</span><span class="o">.</span><span class="n">ControlSocketFile</span><span class="p">):</span> <span class="n">pid_method</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">system</span><span class="o">.</span><span class="n">get_pid_by_open_file</span> <span class="n">_expand_cookie_path</span><span class="p">(</span><span class="n">protocolinfo_response</span><span class="p">,</span> <span class="n">pid_method</span><span class="p">,</span> <span class="n">control_socket</span><span class="o">.</span><span class="n">get_socket_path</span><span class="p">())</span> <span class="k">return</span> <span class="n">protocolinfo_response</span> </div> <span class="k">def</span> <span class="nf">_msg</span><span class="p">(</span><span class="n">controller</span><span class="p">,</span> <span class="n">message</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Sends and receives a message with either a</span> <span class="sd"> :class:`~stem.socket.ControlSocket` or :class:`~stem.control.BaseController`.</span> <span class="sd"> """</span> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">controller</span><span class="p">,</span> <span class="n">stem</span><span class="o">.</span><span class="n">socket</span><span class="o">.</span><span class="n">ControlSocket</span><span class="p">):</span> <span class="n">controller</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">message</span><span class="p">)</span> <span class="k">return</span> <span class="n">controller</span><span class="o">.</span><span class="n">recv</span><span class="p">()</span> <span class="k">else</span><span class="p">:</span> <span class="k">return</span> <span class="n">controller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="n">message</span><span class="p">)</span> <span class="k">def</span> <span class="nf">_read_cookie</span><span class="p">(</span><span class="n">cookie_path</span><span class="p">,</span> <span class="n">is_safecookie</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Provides the contents of a given cookie file.</span> <span class="sd"> :param str cookie_path: absolute path of the cookie file</span> <span class="sd"> :param bool is_safecookie: **True** if this was for SAFECOOKIE</span> <span class="sd"> authentication, **False** if for COOKIE</span> <span class="sd"> :raises:</span> <span class="sd"> * :class:`stem.connection.UnreadableCookieFile` if the cookie file is</span> <span class="sd"> unreadable</span> <span class="sd"> * :class:`stem.connection.IncorrectCookieSize` if the cookie size is</span> <span class="sd"> incorrect (not 32 bytes)</span> <span class="sd"> """</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">cookie_path</span><span class="p">):</span> <span class="n">exc_msg</span> <span class="o">=</span> <span class="s">"Authentication failed: '</span><span class="si">%s</span><span class="s">' doesn't exist"</span> <span class="o">%</span> <span class="n">cookie_path</span> <span class="k">raise</span> <span class="n">UnreadableCookieFile</span><span class="p">(</span><span class="n">exc_msg</span><span class="p">,</span> <span class="n">cookie_path</span><span class="p">,</span> <span class="n">is_safecookie</span><span class="p">)</span> <span class="c"># Abort if the file isn't 32 bytes long. This is to avoid exposing arbitrary</span> <span class="c"># file content to the port.</span> <span class="c">#</span> <span class="c"># Without this a malicious socket could, for instance, claim that</span> <span class="c"># '~/.bash_history' or '~/.ssh/id_rsa' was its authentication cookie to trick</span> <span class="c"># us into reading it for them with our current permissions.</span> <span class="c">#</span> <span class="c"># https://trac.torproject.org/projects/tor/ticket/4303</span> <span class="n">auth_cookie_size</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">getsize</span><span class="p">(</span><span class="n">cookie_path</span><span class="p">)</span> <span class="k">if</span> <span class="n">auth_cookie_size</span> <span class="o">!=</span> <span class="mi">32</span><span class="p">:</span> <span class="n">exc_msg</span> <span class="o">=</span> <span class="s">"Authentication failed: authentication cookie '</span><span class="si">%s</span><span class="s">' is the wrong size (</span><span class="si">%i</span><span class="s"> bytes instead of 32)"</span> <span class="o">%</span> <span class="p">(</span><span class="n">cookie_path</span><span class="p">,</span> <span class="n">auth_cookie_size</span><span class="p">)</span> <span class="k">raise</span> <span class="n">IncorrectCookieSize</span><span class="p">(</span><span class="n">exc_msg</span><span class="p">,</span> <span class="n">cookie_path</span><span class="p">,</span> <span class="n">is_safecookie</span><span class="p">)</span> <span class="k">try</span><span class="p">:</span> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">cookie_path</span><span class="p">,</span> <span class="s">'rb'</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span> <span class="k">return</span> <span class="n">f</span><span class="o">.</span><span class="n">read</span><span class="p">()</span> <span class="k">except</span> <span class="ne">IOError</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span> <span class="n">exc_msg</span> <span class="o">=</span> <span class="s">"Authentication failed: unable to read '</span><span class="si">%s</span><span class="s">' (</span><span class="si">%s</span><span class="s">)"</span> <span class="o">%</span> <span class="p">(</span><span class="n">cookie_path</span><span class="p">,</span> <span class="n">exc</span><span class="p">)</span> <span class="k">raise</span> <span class="n">UnreadableCookieFile</span><span class="p">(</span><span class="n">exc_msg</span><span class="p">,</span> <span class="n">cookie_path</span><span class="p">,</span> <span class="n">is_safecookie</span><span class="p">)</span> <span class="k">def</span> <span class="nf">_expand_cookie_path</span><span class="p">(</span><span class="n">protocolinfo_response</span><span class="p">,</span> <span class="n">pid_resolver</span><span class="p">,</span> <span class="n">pid_resolution_arg</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Attempts to expand a relative cookie path with the given pid resolver. This</span> <span class="sd"> leaves the cookie_path alone if it's already absolute, **None**, or the</span> <span class="sd"> system calls fail.</span> <span class="sd"> """</span> <span class="n">cookie_path</span> <span class="o">=</span> <span class="n">protocolinfo_response</span><span class="o">.</span><span class="n">cookie_path</span> <span class="k">if</span> <span class="n">cookie_path</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isabs</span><span class="p">(</span><span class="n">cookie_path</span><span class="p">):</span> <span class="k">try</span><span class="p">:</span> <span class="n">tor_pid</span> <span class="o">=</span> <span class="n">pid_resolver</span><span class="p">(</span><span class="n">pid_resolution_arg</span><span class="p">)</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">tor_pid</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">IOError</span><span class="p">(</span><span class="s">"pid lookup failed"</span><span class="p">)</span> <span class="n">tor_cwd</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">system</span><span class="o">.</span><span class="n">get_cwd</span><span class="p">(</span><span class="n">tor_pid</span><span class="p">)</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">tor_cwd</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">IOError</span><span class="p">(</span><span class="s">"cwd lookup failed"</span><span class="p">)</span> <span class="n">cookie_path</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">system</span><span class="o">.</span><span class="n">expand_path</span><span class="p">(</span><span class="n">cookie_path</span><span class="p">,</span> <span class="n">tor_cwd</span><span class="p">)</span> <span class="k">except</span> <span class="ne">IOError</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span> <span class="n">resolver_labels</span> <span class="o">=</span> <span class="p">{</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">system</span><span class="o">.</span><span class="n">get_pid_by_name</span><span class="p">:</span> <span class="s">" by name"</span><span class="p">,</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">system</span><span class="o">.</span><span class="n">get_pid_by_port</span><span class="p">:</span> <span class="s">" by port"</span><span class="p">,</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">system</span><span class="o">.</span><span class="n">get_pid_by_open_file</span><span class="p">:</span> <span class="s">" by socket file"</span><span class="p">,</span> <span class="p">}</span> <span class="n">pid_resolver_label</span> <span class="o">=</span> <span class="n">resolver_labels</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">pid_resolver</span><span class="p">,</span> <span class="s">""</span><span class="p">)</span> <span class="n">log</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">"unable to expand relative tor cookie path</span><span class="si">%s</span><span class="s">: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">pid_resolver_label</span><span class="p">,</span> <span class="n">exc</span><span class="p">))</span> <span class="n">protocolinfo_response</span><span class="o">.</span><span class="n">cookie_path</span> <span class="o">=</span> <span class="n">cookie_path</span> <div class="viewcode-block" id="AuthenticationFailure"><a class="viewcode-back" href="../../api/connection.html#stem.connection.AuthenticationFailure">[docs]</a><span class="k">class</span> <span class="nc">AuthenticationFailure</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Base error for authentication failures.</span> <span class="sd"> :var stem.socket.ControlMessage auth_response: AUTHENTICATE response from the</span> <span class="sd"> control socket, **None** if one wasn't received</span> <span class="sd"> """</span> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">message</span><span class="p">,</span> <span class="n">auth_response</span> <span class="o">=</span> <span class="bp">None</span><span class="p">):</span> <span class="nb">super</span><span class="p">(</span><span class="n">AuthenticationFailure</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="n">message</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">auth_response</span> <span class="o">=</span> <span class="n">auth_response</span> </div> <div class="viewcode-block" id="UnrecognizedAuthMethods"><a class="viewcode-back" href="../../api/connection.html#stem.connection.UnrecognizedAuthMethods">[docs]</a><span class="k">class</span> <span class="nc">UnrecognizedAuthMethods</span><span class="p">(</span><span class="n">AuthenticationFailure</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> All methods for authenticating aren't recognized.</span> <span class="sd"> :var list unknown_auth_methods: authentication methods that weren't recognized</span> <span class="sd"> """</span> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">message</span><span class="p">,</span> <span class="n">unknown_auth_methods</span><span class="p">):</span> <span class="nb">super</span><span class="p">(</span><span class="n">UnrecognizedAuthMethods</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="n">message</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">unknown_auth_methods</span> <span class="o">=</span> <span class="n">unknown_auth_methods</span> </div> <div class="viewcode-block" id="IncorrectSocketType"><a class="viewcode-back" href="../../api/connection.html#stem.connection.IncorrectSocketType">[docs]</a><span class="k">class</span> <span class="nc">IncorrectSocketType</span><span class="p">(</span><span class="n">AuthenticationFailure</span><span class="p">):</span> <span class="s">"Socket does not speak the control protocol."</span> </div> <div class="viewcode-block" id="OpenAuthFailed"><a class="viewcode-back" href="../../api/connection.html#stem.connection.OpenAuthFailed">[docs]</a><span class="k">class</span> <span class="nc">OpenAuthFailed</span><span class="p">(</span><span class="n">AuthenticationFailure</span><span class="p">):</span> <span class="s">"Failure to authenticate to an open socket."</span> </div> <div class="viewcode-block" id="OpenAuthRejected"><a class="viewcode-back" href="../../api/connection.html#stem.connection.OpenAuthRejected">[docs]</a><span class="k">class</span> <span class="nc">OpenAuthRejected</span><span class="p">(</span><span class="n">OpenAuthFailed</span><span class="p">):</span> <span class="s">"Attempt to connect to an open control socket was rejected."</span> </div> <div class="viewcode-block" id="PasswordAuthFailed"><a class="viewcode-back" href="../../api/connection.html#stem.connection.PasswordAuthFailed">[docs]</a><span class="k">class</span> <span class="nc">PasswordAuthFailed</span><span class="p">(</span><span class="n">AuthenticationFailure</span><span class="p">):</span> <span class="s">"Failure to authenticate with a password."</span> </div> <div class="viewcode-block" id="PasswordAuthRejected"><a class="viewcode-back" href="../../api/connection.html#stem.connection.PasswordAuthRejected">[docs]</a><span class="k">class</span> <span class="nc">PasswordAuthRejected</span><span class="p">(</span><span class="n">PasswordAuthFailed</span><span class="p">):</span> <span class="s">"Socket does not support password authentication."</span> </div> <div class="viewcode-block" id="IncorrectPassword"><a class="viewcode-back" href="../../api/connection.html#stem.connection.IncorrectPassword">[docs]</a><span class="k">class</span> <span class="nc">IncorrectPassword</span><span class="p">(</span><span class="n">PasswordAuthFailed</span><span class="p">):</span> <span class="s">"Authentication password incorrect."</span> </div> <div class="viewcode-block" id="MissingPassword"><a class="viewcode-back" href="../../api/connection.html#stem.connection.MissingPassword">[docs]</a><span class="k">class</span> <span class="nc">MissingPassword</span><span class="p">(</span><span class="n">PasswordAuthFailed</span><span class="p">):</span> <span class="s">"Password authentication is supported but we weren't provided with one."</span> </div> <div class="viewcode-block" id="CookieAuthFailed"><a class="viewcode-back" href="../../api/connection.html#stem.connection.CookieAuthFailed">[docs]</a><span class="k">class</span> <span class="nc">CookieAuthFailed</span><span class="p">(</span><span class="n">AuthenticationFailure</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Failure to authenticate with an authentication cookie.</span> <span class="sd"> :param str cookie_path: location of the authentication cookie we attempted</span> <span class="sd"> :param bool is_safecookie: **True** if this was for SAFECOOKIE</span> <span class="sd"> authentication, **False** if for COOKIE</span> <span class="sd"> :param stem.response.ControlMessage auth_response: reply to our</span> <span class="sd"> authentication attempt</span> <span class="sd"> """</span> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">message</span><span class="p">,</span> <span class="n">cookie_path</span><span class="p">,</span> <span class="n">is_safecookie</span><span class="p">,</span> <span class="n">auth_response</span> <span class="o">=</span> <span class="bp">None</span><span class="p">):</span> <span class="nb">super</span><span class="p">(</span><span class="n">CookieAuthFailed</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="n">message</span><span class="p">,</span> <span class="n">auth_response</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">is_safecookie</span> <span class="o">=</span> <span class="n">is_safecookie</span> <span class="bp">self</span><span class="o">.</span><span class="n">cookie_path</span> <span class="o">=</span> <span class="n">cookie_path</span> </div> <div class="viewcode-block" id="CookieAuthRejected"><a class="viewcode-back" href="../../api/connection.html#stem.connection.CookieAuthRejected">[docs]</a><span class="k">class</span> <span class="nc">CookieAuthRejected</span><span class="p">(</span><span class="n">CookieAuthFailed</span><span class="p">):</span> <span class="s">"Socket does not support password authentication."</span> </div> <div class="viewcode-block" id="IncorrectCookieValue"><a class="viewcode-back" href="../../api/connection.html#stem.connection.IncorrectCookieValue">[docs]</a><span class="k">class</span> <span class="nc">IncorrectCookieValue</span><span class="p">(</span><span class="n">CookieAuthFailed</span><span class="p">):</span> <span class="s">"Authentication cookie value was rejected."</span> </div> <div class="viewcode-block" id="IncorrectCookieSize"><a class="viewcode-back" href="../../api/connection.html#stem.connection.IncorrectCookieSize">[docs]</a><span class="k">class</span> <span class="nc">IncorrectCookieSize</span><span class="p">(</span><span class="n">CookieAuthFailed</span><span class="p">):</span> <span class="s">"Aborted because the cookie file is the wrong size."</span> </div> <div class="viewcode-block" id="UnreadableCookieFile"><a class="viewcode-back" href="../../api/connection.html#stem.connection.UnreadableCookieFile">[docs]</a><span class="k">class</span> <span class="nc">UnreadableCookieFile</span><span class="p">(</span><span class="n">CookieAuthFailed</span><span class="p">):</span> <span class="s">"Error arose in reading the authentication cookie."</span> </div> <div class="viewcode-block" id="AuthChallengeFailed"><a class="viewcode-back" href="../../api/connection.html#stem.connection.AuthChallengeFailed">[docs]</a><span class="k">class</span> <span class="nc">AuthChallengeFailed</span><span class="p">(</span><span class="n">CookieAuthFailed</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> AUTHCHALLENGE command has failed.</span> <span class="sd"> """</span> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">message</span><span class="p">,</span> <span class="n">cookie_path</span><span class="p">):</span> <span class="nb">super</span><span class="p">(</span><span class="n">AuthChallengeFailed</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="n">message</span><span class="p">,</span> <span class="n">cookie_path</span><span class="p">,</span> <span class="bp">True</span><span class="p">)</span> </div> <div class="viewcode-block" id="AuthChallengeUnsupported"><a class="viewcode-back" href="../../api/connection.html#stem.connection.AuthChallengeUnsupported">[docs]</a><span class="k">class</span> <span class="nc">AuthChallengeUnsupported</span><span class="p">(</span><span class="n">AuthChallengeFailed</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> AUTHCHALLENGE isn't implemented.</span> <span class="sd"> """</span> </div> <div class="viewcode-block" id="UnrecognizedAuthChallengeMethod"><a class="viewcode-back" href="../../api/connection.html#stem.connection.UnrecognizedAuthChallengeMethod">[docs]</a><span class="k">class</span> <span class="nc">UnrecognizedAuthChallengeMethod</span><span class="p">(</span><span class="n">AuthChallengeFailed</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Tor couldn't recognize our AUTHCHALLENGE method.</span> <span class="sd"> :var str authchallenge_method: AUTHCHALLENGE method that Tor couldn't recognize</span> <span class="sd"> """</span> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">message</span><span class="p">,</span> <span class="n">cookie_path</span><span class="p">,</span> <span class="n">authchallenge_method</span><span class="p">):</span> <span class="nb">super</span><span class="p">(</span><span class="n">UnrecognizedAuthChallengeMethod</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="n">message</span><span class="p">,</span> <span class="n">cookie_path</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">authchallenge_method</span> <span class="o">=</span> <span class="n">authchallenge_method</span> </div> <div class="viewcode-block" id="AuthSecurityFailure"><a class="viewcode-back" href="../../api/connection.html#stem.connection.AuthSecurityFailure">[docs]</a><span class="k">class</span> <span class="nc">AuthSecurityFailure</span><span class="p">(</span><span class="n">AuthChallengeFailed</span><span class="p">):</span> <span class="s">"AUTHCHALLENGE response is invalid."</span> </div> <div class="viewcode-block" id="InvalidClientNonce"><a class="viewcode-back" href="../../api/connection.html#stem.connection.InvalidClientNonce">[docs]</a><span class="k">class</span> <span class="nc">InvalidClientNonce</span><span class="p">(</span><span class="n">AuthChallengeFailed</span><span class="p">):</span> <span class="s">"AUTHCHALLENGE request contains an invalid client nonce."</span> </div> <div class="viewcode-block" id="MissingAuthInfo"><a class="viewcode-back" href="../../api/connection.html#stem.connection.MissingAuthInfo">[docs]</a><span class="k">class</span> <span class="nc">MissingAuthInfo</span><span class="p">(</span><span class="n">AuthenticationFailure</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> The PROTOCOLINFO response didn't have enough information to authenticate.</span> <span class="sd"> These are valid control responses but really shouldn't happen in practice.</span> <span class="sd"> """</span> </div> <div class="viewcode-block" id="NoAuthMethods"><a class="viewcode-back" href="../../api/connection.html#stem.connection.NoAuthMethods">[docs]</a><span class="k">class</span> <span class="nc">NoAuthMethods</span><span class="p">(</span><span class="n">MissingAuthInfo</span><span class="p">):</span> <span class="s">"PROTOCOLINFO response didn't have any methods for authenticating."</span> </div> <div class="viewcode-block" id="NoAuthCookie"><a class="viewcode-back" href="../../api/connection.html#stem.connection.NoAuthCookie">[docs]</a><span class="k">class</span> <span class="nc">NoAuthCookie</span><span class="p">(</span><span class="n">MissingAuthInfo</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> PROTOCOLINFO response supports cookie auth but doesn't have its path.</span> <span class="sd"> :param bool is_safecookie: **True** if this was for SAFECOOKIE</span> <span class="sd"> authentication, **False** if for COOKIE</span> <span class="sd"> """</span> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">message</span><span class="p">,</span> <span class="n">is_safecookie</span><span class="p">):</span> <span class="nb">super</span><span class="p">(</span><span class="n">NoAuthCookie</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="n">message</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">is_safecookie</span> <span class="o">=</span> <span class="n">is_safecookie</span> <span class="c"># authentication exceptions ordered as per the authenticate function's pydocs</span></div> <span class="n">AUTHENTICATE_EXCEPTIONS</span> <span class="o">=</span> <span class="p">(</span> <span class="n">IncorrectSocketType</span><span class="p">,</span> <span class="n">UnrecognizedAuthMethods</span><span class="p">,</span> <span class="n">MissingPassword</span><span class="p">,</span> <span class="n">IncorrectPassword</span><span class="p">,</span> <span class="n">IncorrectCookieSize</span><span class="p">,</span> <span class="n">UnreadableCookieFile</span><span class="p">,</span> <span class="n">IncorrectCookieValue</span><span class="p">,</span> <span class="n">AuthChallengeUnsupported</span><span class="p">,</span> <span class="n">UnrecognizedAuthChallengeMethod</span><span class="p">,</span> <span class="n">InvalidClientNonce</span><span class="p">,</span> <span class="n">AuthSecurityFailure</span><span class="p">,</span> <span class="n">OpenAuthRejected</span><span class="p">,</span> <span class="n">MissingAuthInfo</span><span class="p">,</span> <span class="n">AuthenticationFailure</span> <span class="p">)</span> </pre></div> </div> <div class="bottomnav"> </div> <div class="footer"> </div> </body> </html>