Stem Docs

Controller Connection

Controller Connection

Functions for connecting and authenticating to the tor process.

The connect() function give an easy, one line method for getting an authenticated control connection. This is handy for CLI applications and the python interactive interpreter, but does several things that makes it undesirable for applications (uses stdin/stdout, suppresses exceptions, etc).

import sys

from stem.connection import connect

if __name__ == '__main__':
  controller = connect()

  if not controller:
    sys.exit(1)  # unable to get a connection

  print 'Tor is running version %s' % controller.get_version()
  controller.close()
% python example.py
Tor is running version 0.2.4.10-alpha-dev (git-8be6058d8f31e578)

... or if Tor isn't running...

% python example.py
[Errno 111] Connection refused

The authenticate() function, however, gives easy but fine-grained control over the authentication process. For instance...

import sys
import getpass
import stem.connection
import stem.socket

try:
  control_socket = stem.socket.ControlPort(port = 9051)
except stem.SocketError as exc:
  print 'Unable to connect to port 9051 (%s)' % exc
  sys.exit(1)

try:
  stem.connection.authenticate(control_socket)
except stem.connection.IncorrectSocketType:
  print 'Please check in your torrc that 9051 is the ControlPort.'
  print 'Maybe you configured it to be the ORPort or SocksPort instead?'
  sys.exit(1)
except stem.connection.MissingPassword:
  controller_password = getpass.getpass('Controller password: ')

  try:
    stem.connection.authenticate_password(control_socket, controller_password)
  except stem.connection.PasswordAuthFailed:
    print 'Unable to authenticate, password is incorrect'
    sys.exit(1)
except stem.connection.AuthenticationFailure as exc:
  print 'Unable to authenticate: %s' % exc
  sys.exit(1)

Module Overview:

connect - Simple method for getting authenticated control connection

authenticate - Main method for authenticating to a control socket
authenticate_none - Authenticates to an open control socket
authenticate_password - Authenticates to a socket supporting password auth
authenticate_cookie - Authenticates to a socket supporting cookie auth
authenticate_safecookie - Authenticates to a socket supporting safecookie auth

get_protocolinfo - Issues a PROTOCOLINFO query

AuthenticationFailure - Base exception raised for authentication failures
  |- UnrecognizedAuthMethods - Authentication methods are unsupported
  |- IncorrectSocketType - Socket does not speak the tor control protocol
  |
  |- OpenAuthFailed - Failure when authenticating by an open socket
  |  +- OpenAuthRejected - Tor rejected this method of authentication
  |
  |- PasswordAuthFailed - Failure when authenticating by a password
  |  |- PasswordAuthRejected - Tor rejected this method of authentication
  |  |- IncorrectPassword - Password was rejected
  |  +- MissingPassword - Socket supports password auth but wasn't attempted
  |
  |- CookieAuthFailed - Failure when authenticating by a cookie
  |  |- CookieAuthRejected - Tor rejected this method of authentication
  |  |- IncorrectCookieValue - Authentication cookie was rejected
  |  |- IncorrectCookieSize - Size of the cookie file is incorrect
  |  |- UnreadableCookieFile - Unable to read the contents of the auth cookie
  |  +- AuthChallengeFailed - Failure completing the authchallenge request
  |     |- AuthChallengeUnsupported - Tor doesn't recognize the AUTHCHALLENGE command
  |     |- AuthSecurityFailure - Server provided the wrong nonce credentials
  |     |- InvalidClientNonce - The client nonce is invalid
  |     +- UnrecognizedAuthChallengeMethod - AUTHCHALLENGE does not support the given methods.
  |
  +- MissingAuthInfo - Unexpected PROTOCOLINFO response, missing auth info
     |- NoAuthMethods - Missing any methods for authenticating
     +- NoAuthCookie - Supports cookie auth but doesn't have its path
stem.connection.AuthMethod(enum)

Enumeration of PROTOCOLINFO responses for supported authentication methods.

AuthMethod Description
NONE No authentication required.
PASSWORD Password required, see tor's HashedControlPassword option.
COOKIE Contents of the cookie file required, see tor's CookieAuthentication option.
SAFECOOKIE Need to reply to a hmac challenge using the contents of the cookie file.
UNKNOWN Tor provided one or more authentication methods that we don't recognize, probably something new.
stem.connection.connect(control_port=('127.0.0.1', 'default'), control_socket='/var/run/tor/control', password=None, password_prompt=False, chroot_path=None, controller=<class 'stem.control.Controller'>)

Convenience function for quickly getting a control connection. This is very handy for debugging or CLI setup, handling setup and prompting for a password if necessary (and none is provided). If any issues arise this prints a description of the problem and returns None.

If both a control_port and control_socket are provided then the control_socket is tried first, and this provides a generic error message if they're both unavailable.

In much the same vein as git porcelain commands, users should not rely on details of how this works. Messages and details of this function's behavior could change in the future.

If the port is 'default' then this checks on both 9051 (default for relays) and 9151 (default for the Tor Browser). This default may change in the future.

New in version 1.2.0.

Changed in version 1.5.0: Use both port 9051 and 9151 by default.

Parameters:
  • contol_port (tuple) -- address and port tuple, for instance ('127.0.0.1', 9051)
  • path (str) -- path where the control socket is located
  • password (str) -- passphrase to authenticate to the socket
  • password_prompt (bool) -- prompt for the controller password if it wasn't supplied
  • chroot_path (str) -- path prefix if in a chroot environment
  • controller (Class) -- BaseController subclass to be returned, this provides a ControlSocket if None
Returns:

authenticated control connection, the type based on the controller argument

Raises :

ValueError if given an invalid control_port, or both control_port and control_socket are None

stem.connection.connect_port(address='127.0.0.1', port=9051, password=None, chroot_path=None, controller=<class 'stem.control.Controller'>)[source]

Convenience function for quickly getting a control connection. This is very handy for debugging or CLI setup, handling setup and prompting for a password if necessary (and none is provided). If any issues arise this prints a description of the problem and returns None.

Deprecated since version 1.2.0: Use connect() instead.

Parameters:
  • address (str) -- ip address of the controller
  • port (int) -- port number of the controller
  • password (str) -- passphrase to authenticate to the socket
  • chroot_path (str) -- path prefix if in a chroot environment
  • controller (Class) -- BaseController subclass to be returned, this provides a ControlSocket if None
Returns:

authenticated control connection, the type based on the controller argument

stem.connection.connect_socket_file(path='/var/run/tor/control', password=None, chroot_path=None, controller=<class 'stem.control.Controller'>)[source]

Convenience function for quickly getting a control connection. For more information see the connect_port() function.

In much the same vein as git porcelain commands, users should not rely on details of how this works. Messages or details of this function's behavior might change in the future.

Deprecated since version 1.2.0: Use connect() instead.

Parameters:
  • path (str) -- path where the control socket is located
  • password (str) -- passphrase to authenticate to the socket
  • chroot_path (str) -- path prefix if in a chroot environment
  • controller (Class) -- BaseController subclass to be returned, this provides a ControlSocket if None
Returns:

authenticated control connection, the type based on the controller argument

stem.connection.authenticate(controller, password=None, chroot_path=None, protocolinfo_response=None)[source]

Authenticates to a control socket using the information provided by a PROTOCOLINFO response. In practice this will often be all we need to authenticate, raising an exception if all attempts to authenticate fail.

All exceptions are subclasses of AuthenticationFailure so, in practice, callers should catch the types of authentication failure that they care about, then have a AuthenticationFailure catch-all at the end.

This can authenticate to either a BaseController or ControlSocket.

Parameters:
  • controller -- tor controller or socket to be authenticated
  • password (str) -- passphrase to present to the socket if it uses password authentication (skips password auth if None)
  • chroot_path (str) -- path prefix if in a chroot environment
  • protocolinfo_response (stem.response.protocolinfo.ProtocolInfoResponse) -- tor protocolinfo response, this is retrieved on our own if None
Raises :

If all attempts to authenticate fails then this will raise a AuthenticationFailure subclass. Since this may try multiple authentication methods it may encounter multiple exceptions. If so then the exception this raises is prioritized as follows...

* In practice it is highly unusual for this to occur, being more of a theoretical possibility rather than something you should expect. It's fine to treat these as errors. If you have a use case where this commonly happens, please file a ticket on 'trac.torproject.org'.

In the future new AuthenticationFailure subclasses may be added to allow for better error handling.

stem.connection.authenticate_none(controller, suppress_ctl_errors=True)[source]

Authenticates to an open control socket. All control connections need to authenticate before they can be used, even if tor hasn't been configured to use any authentication.

If authentication fails tor will disconnect and we'll make a best effort attempt to re-establish the connection. This may not succeed, so check is_alive() before using the socket further.

This can authenticate to either a BaseController or ControlSocket.

For general usage use the authenticate() function instead.

Parameters:
  • controller -- tor controller or socket to be authenticated
  • suppress_ctl_errors (bool) -- reports raised ControllerError as authentication rejection if True, otherwise they're re-raised
Raises :

stem.connection.OpenAuthRejected if the empty authentication credentials aren't accepted

stem.connection.authenticate_password(controller, password, suppress_ctl_errors=True)[source]

Authenticates to a control socket that uses a password (via the HashedControlPassword torrc option). Quotes in the password are escaped.

If authentication fails tor will disconnect and we'll make a best effort attempt to re-establish the connection. This may not succeed, so check is_alive() before using the socket further.

If you use this function directly, rather than authenticate(), we may mistakenly raise a PasswordAuthRejected rather than IncorrectPassword. This is because we rely on tor's error messaging which is liable to change in future versions (ticket 4817).

This can authenticate to either a BaseController or ControlSocket.

For general usage use the authenticate() function instead.

Parameters:
  • controller -- tor controller or socket to be authenticated
  • password (str) -- passphrase to present to the socket
  • suppress_ctl_errors (bool) -- reports raised ControllerError as authentication rejection if True, otherwise they're re-raised
Raises :

Authenticates to a control socket that uses the contents of an authentication cookie (generated via the CookieAuthentication torrc option). This does basic validation that this is a cookie before presenting the contents to the socket.

The IncorrectCookieSize and UnreadableCookieFile exceptions take precedence over the other types.

If authentication fails tor will disconnect and we'll make a best effort attempt to re-establish the connection. This may not succeed, so check is_alive() before using the socket further.

If you use this function directly, rather than authenticate(), we may mistakenly raise a CookieAuthRejected rather than IncorrectCookieValue. This is because we rely on tor's error messaging which is liable to change in future versions (ticket 4817).

This can authenticate to either a BaseController or ControlSocket.

For general usage use the authenticate() function instead.

Parameters:
  • controller -- tor controller or socket to be authenticated
  • cookie_path (str) -- path of the authentication cookie to send to tor
  • suppress_ctl_errors (bool) -- reports raised ControllerError as authentication rejection if True, otherwise they're re-raised
Raises :
stem.connection.authenticate_safecookie(controller, cookie_path, suppress_ctl_errors=True)[source]

Authenticates to a control socket using the safe cookie method, which is enabled by setting the CookieAuthentication torrc option on Tor client's which support it.

Authentication with this is a two-step process...

  1. send a nonce to the server and receives a challenge from the server for the cookie's contents
  2. generate a hash digest using the challenge received in the first step, and use it to authenticate the controller

The IncorrectCookieSize and UnreadableCookieFile exceptions take precedence over the other exception types.

The AuthChallengeUnsupported, UnrecognizedAuthChallengeMethod, InvalidClientNonce and CookieAuthRejected exceptions are next in the order of precedence. Depending on the reason, one of these is raised if the first (AUTHCHALLENGE) step fails.

In the second (AUTHENTICATE) step, IncorrectCookieValue or CookieAuthRejected maybe raised.

If authentication fails tor will disconnect and we'll make a best effort attempt to re-establish the connection. This may not succeed, so check is_alive() before using the socket further.

For general usage use the authenticate() function instead.

Parameters:
  • controller -- tor controller or socket to be authenticated
  • cookie_path (str) -- path of the authentication cookie to send to tor
  • suppress_ctl_errors (bool) -- reports raised ControllerError as authentication rejection if True, otherwise they're re-raised
Raises :
stem.connection.get_protocolinfo(controller)[source]

Issues a PROTOCOLINFO query to a control socket, getting information about the tor process running on it. If the socket is already closed then it is first reconnected.

According to the control spec the cookie_file is an absolute path. However, this often is not the case (especially for the Tor Browser Bundle). If the path is relative then we'll make an attempt (which may not work) to correct this (ticket 1101).

This can authenticate to either a BaseController or ControlSocket.

Parameters:

controller -- tor controller or socket to be queried

Returns:

ProtocolInfoResponse provided by tor

Raises :
exception stem.connection.AuthenticationFailure(message, auth_response=None)[source]

Bases: exceptions.Exception

Base error for authentication failures.

Variables:auth_response (stem.socket.ControlMessage) -- AUTHENTICATE response from the control socket, None if one wasn't received
exception stem.connection.UnrecognizedAuthMethods(message, unknown_auth_methods)[source]

Bases: stem.connection.AuthenticationFailure

All methods for authenticating aren't recognized.

Variables:unknown_auth_methods (list) -- authentication methods that weren't recognized
exception stem.connection.IncorrectSocketType(message, auth_response=None)[source]

Bases: stem.connection.AuthenticationFailure

Socket does not speak the control protocol.

exception stem.connection.OpenAuthFailed(message, auth_response=None)[source]

Bases: stem.connection.AuthenticationFailure

Failure to authenticate to an open socket.

exception stem.connection.OpenAuthRejected(message, auth_response=None)[source]

Bases: stem.connection.OpenAuthFailed

Attempt to connect to an open control socket was rejected.

exception stem.connection.PasswordAuthFailed(message, auth_response=None)[source]

Bases: stem.connection.AuthenticationFailure

Failure to authenticate with a password.

exception stem.connection.PasswordAuthRejected(message, auth_response=None)[source]

Bases: stem.connection.PasswordAuthFailed

Socket does not support password authentication.

exception stem.connection.IncorrectPassword(message, auth_response=None)[source]

Bases: stem.connection.PasswordAuthFailed

Authentication password incorrect.

exception stem.connection.MissingPassword(message, auth_response=None)[source]

Bases: stem.connection.PasswordAuthFailed

Password authentication is supported but we weren't provided with one.

exception stem.connection.CookieAuthFailed(message, cookie_path, is_safecookie, auth_response=None)[source]

Bases: stem.connection.AuthenticationFailure

Failure to authenticate with an authentication cookie.

Parameters:
  • cookie_path (str) -- location of the authentication cookie we attempted
  • is_safecookie (bool) -- True if this was for SAFECOOKIE authentication, False if for COOKIE
  • auth_response (stem.response.ControlMessage) -- reply to our authentication attempt
exception stem.connection.CookieAuthRejected(message, cookie_path, is_safecookie, auth_response=None)[source]

Bases: stem.connection.CookieAuthFailed

Socket does not support password authentication.

exception stem.connection.IncorrectCookieValue(message, cookie_path, is_safecookie, auth_response=None)[source]

Bases: stem.connection.CookieAuthFailed

Authentication cookie value was rejected.

exception stem.connection.IncorrectCookieSize(message, cookie_path, is_safecookie, auth_response=None)[source]

Bases: stem.connection.CookieAuthFailed

Aborted because the cookie file is the wrong size.

exception stem.connection.UnreadableCookieFile(message, cookie_path, is_safecookie, auth_response=None)[source]

Bases: stem.connection.CookieAuthFailed

Error arose in reading the authentication cookie.

exception stem.connection.AuthChallengeFailed(message, cookie_path)[source]

Bases: stem.connection.CookieAuthFailed

AUTHCHALLENGE command has failed.

exception stem.connection.AuthChallengeUnsupported(message, cookie_path)[source]

Bases: stem.connection.AuthChallengeFailed

AUTHCHALLENGE isn't implemented.

exception stem.connection.UnrecognizedAuthChallengeMethod(message, cookie_path, authchallenge_method)[source]

Bases: stem.connection.AuthChallengeFailed

Tor couldn't recognize our AUTHCHALLENGE method.

Variables:authchallenge_method (str) -- AUTHCHALLENGE method that Tor couldn't recognize
exception stem.connection.AuthSecurityFailure(message, cookie_path)[source]

Bases: stem.connection.AuthChallengeFailed

AUTHCHALLENGE response is invalid.

exception stem.connection.InvalidClientNonce(message, cookie_path)[source]

Bases: stem.connection.AuthChallengeFailed

AUTHCHALLENGE request contains an invalid client nonce.

exception stem.connection.MissingAuthInfo(message, auth_response=None)[source]

Bases: stem.connection.AuthenticationFailure

The PROTOCOLINFO response didn't have enough information to authenticate. These are valid control responses but really shouldn't happen in practice.

exception stem.connection.NoAuthMethods(message, auth_response=None)[source]

Bases: stem.connection.MissingAuthInfo

PROTOCOLINFO response didn't have any methods for authenticating.

exception stem.connection.NoAuthCookie(message, is_safecookie)[source]

Bases: stem.connection.MissingAuthInfo

PROTOCOLINFO response supports cookie auth but doesn't have its path.

Parameters:is_safecookie (bool) -- True if this was for SAFECOOKIE authentication, False if for COOKIE