Opened 4 years ago

Closed 4 years ago

Last modified 4 years ago

#17086 closed defect (worksforme)

CircuitEvent socks_username and socks_password is always None

Reported by: trodun Owned by:
Priority: Medium Milestone:
Component: Core Tor/Stem Version:
Severity: Keywords: socks_username, socks_password
Cc: atagar Actual Points:
Parent ID: Points:
Reviewer: Sponsor:

Description

Passing a socks user and pass with the request will not lead to these attributes being set, but the stream isolation is triggered.

import io

import pycurl
from stem.process import launch_tor_with_config
from stem.control import Controller, EventType


SOCKS_PORT = 9050
CONTROL_PORT = 9051


def query(url, user=None, passw=None):

    output = io.BytesIO()

    query = pycurl.Curl()
    query.setopt(query.URL, url)
    query.setopt(query.PROXY, '127.0.0.1')
    query.setopt(query.PROXYPORT, SOCKS_PORT)
    query.setopt(query.PROXYTYPE, 7)
    query.setopt(query.PROXYUSERNAME, user)
    query.setopt(query.PROXYPASSWORD, passw)
    query.setopt(query.WRITEFUNCTION, output.write)

    query.perform()
    return output.getvalue()


def circ_event(circ):
    print(circ.socks_username, circ.socks_password)

tor_process = launch_tor_with_config(
    config={'SocksPort': str(SOCKS_PORT),
            'ControlPort': str(CONTROL_PORT),
            'SOCKSListenAddress': '127.0.0.1'})

controller = Controller.from_port(port=CONTROL_PORT)
controller.authenticate()
controller.add_event_listener(circ_event, EventType.CIRC)

query('http://example.com/', user='data', passw='lost')

controller.close()
tor_process.kill()

Output:

None None
None None
None None
None None
None None
None None
None None
None None
None None
None None

Child Tickets

Change History (13)

comment:1 Changed 4 years ago by atagar

Resolution: not a bug
Status: newclosed

Hi trodun, please see SOCKSPort and proposal 171 which added stream isolation. You're not providing any stream isolation flags with your SocksPort configuration.

I'm not terribly familiar with stream isolation but it doesn't really involve Stem (we just pass along the event attributes).

comment:2 Changed 4 years ago by trodun

The relavant flag, IsolateSOCKSAuth in enabled by default.

The isolation works nicely on Tor's part when passing different auth info, the problem is that the passed credentials are not saved by stem in CircuitEvent socks_username and socks_password.

Storing the passed username and password would be the function of those two attributes, but they are always None.
https://stem.torproject.org/api/response.html#stem.response.events.CircuitEvent

Please consider reopening the issue.

comment:3 Changed 4 years ago by trodun

It could be possible that Tor is at fault for not exposing the data to stem.

comment:4 Changed 4 years ago by atagar

It could be possible that Tor is at fault for not exposing the data to stem.

Most likely. Try using telnet to see if that attribute is being provided on the event or not...

https://stem.torproject.org/faq.html#can-i-interact-with-tors-controller-interface-directly

If so then feel free to reopen. If not then you're welcome to reopen under the 'Tor' component instead. :)

comment:5 Changed 4 years ago by trodun

I was not able to see the new circuit being created after 'setevents circ', but it was shown in telnet when it got closed, and the password was listed.

I have printed every event_message in stem/util/control.py, and the same seems to be happening regarding passwords, the raw event only contains the auth data when a circuit closed event is fired, this is also picked up correctly by stem.

It seems to be a Tor bug indeed.

Last edited 4 years ago by trodun (previous) (diff)

comment:6 Changed 4 years ago by trodun

Component: StemTor
Resolution: not a bug
Status: closedreopened

comment:7 Changed 4 years ago by yawning

>>> SETEVENTS CIRC
250 OK

 [Open https://www.google.com in Tor Browser]

>>> /events
CIRC 228 LAUNCHED BUILD_FLAGS=NEED_CAPACITY PURPOSE=GENERAL TIME_CREATED=2015-09-19T05:46:10.638685
CIRC 228 EXTENDED [Guard Redacted] BUILD_FLAGS=NEED_CAPACITY PURPOSE=GENERAL TIME_CREATED=2015-09-19T05:46:10.638685 SOCKS_USERNAME="google.com" SOCKS_PASSWORD="0"

...

CIRC 228 BUILT [Path Redacted] BUILD_FLAGS=NEED_CAPACITY PURPOSE=GENERAL TIME_CREATED=2015-09-19T05:46:10.638685 SOCKS_USERNAME="google.com" SOCKS_PASSWORD="0"

Tor sends the SOCKS username and password correctly, so I'm tempted to Invalid this.

comment:8 Changed 4 years ago by cypherpunks

There is something weird going on with Tor being launched via stem.

If Tor is launched with the same configuration via the command line, things work properly. torrc:
SocksPort 9050
SOCKSListenAddress 127.0.0.1
ControlPort 9051

If it's launched via stem, socks username/password are missing.

comment:9 in reply to:  7 Changed 4 years ago by trodun

Replying to yawning:

Tor sends the SOCKS username and password correctly, so I'm tempted to Invalid this.

I'm not sure if the component is Stem or Tor, but the bug report should not be invalid unless the shared example runs as expected. Is the user/pass printed out for you?

comment:10 Changed 4 years ago by atagar

If Tor is launched with the same configuration via the command line, things work properly

For what it's worth Stem launches tor by shelling out to it. You can find the implementation here.

comment:11 Changed 4 years ago by yawning

Component: TorStem

This is not a tor bug though the behavior is counter-intuitive (Changed the component, though I think Stem is doing the right thing as well).

This is what is happening in the launch_tor_with_config call:

  1. Stem fork/execs a tor instance and waits for it to bootstrap to 100%.
  2. Tor starts up, and builds a test circuit to a random exit. (Tor has successfully opened a circuit. Looks like client functionality is working.)
  3. Tor finishes bootstrapping.
  4. Stem returns from the call.

Since a usable circuit is already built (the one use for testing client functionality), tor is just attaching the incoming request to the existing (BUILT) circuit, and no circuit status events are fired.

ypres :: /tmp % python2 fuck.py

  # Dump the circuit status before issuing a query.

circuit-status=
1 BUILT $9F7D6E6420183C2B76D3CE99624EBC98A21A967E~Nivrim,$B143D439B72D239A419F8DCE07B8A8EB1B486FA7~wardsback,$5FEA88EFEDC5897F7094A1759CE25BA0D3DA87E7~YellowNet BUILD_FLAGS=NEED_CAPACITY PURPOSE=GENERAL TIME_CREATED=2015-09-20T14:56:06.293922
2 EXTENDED $9F7D6E6420183C2B76D3CE99624EBC98A21A967E~Nivrim,$5DEF69E67BAF2CF26D36B5AC2A925BB2EA376593~WhiteDragon BUILD_FLAGS=NEED_CAPACITY PURPOSE=GENERAL TIME_CREATED=2015-09-20T14:56:07.278613
3 EXTENDED BUILD_FLAGS=IS_INTERNAL,NEED_CAPACITY,NEED_UPTIME PURPOSE=GENERAL TIME_CREATED=2015-09-20T14:56:08.278115
OK

  # Query issued here.
  # The STREAM event shows that the chosen CircuitID is '1'

STREAM 5 NEW 0 example.com:80 SOURCE_ADDR=127.0.0.1:38569 PURPOSE=USER
STREAM 5 SENTCONNECT 1 example.com:80
CIRC 3 EXTENDED $9F7D6E6420183C2B76D3CE99624EBC98A21A967E~Nivrim BUILD_FLAGS=IS_INTERNAL,NEED_CAPACITY,NEED_UPTIME PURPOSE=GENERAL TIME_CREATED=2015-09-20T14:56:08.278115
CIRC 4 LAUNCHED BUILD_FLAGS=IS_INTERNAL,NEED_CAPACITY,NEED_UPTIME PURPOSE=GENERAL TIME_CREATED=2015-09-20T14:56:09.278708
CIRC 3 EXTENDED $9F7D6E6420183C2B76D3CE99624EBC98A21A967E~Nivrim,$C382878DCDB4920EF768C99D3C31981DBE7E5F93~ddorfgermany BUILD_FLAGS=IS_INTERNAL,NEED_CAPACITY,NEED_UPTIME PURPOSE=GENERAL TIME_CREATED=2015-09-20T14:56:08.278115
CIRC 4 EXTENDED $9F7D6E6420183C2B76D3CE99624EBC98A21A967E~Nivrim BUILD_FLAGS=IS_INTERNAL,NEED_CAPACITY,NEED_UPTIME PURPOSE=GENERAL TIME_CREATED=2015-09-20T14:56:09.278708
CIRC 2 EXTENDED $9F7D6E6420183C2B76D3CE99624EBC98A21A967E~Nivrim,$5DEF69E67BAF2CF26D36B5AC2A925BB2EA376593~WhiteDragon,$615EBC4B48F03858FA50A3E23E5AF569D0D2308A~AccessNow004 BUILD_FLAGS=NEED_CAPACITY PURPOSE=GENERAL TIME_CREATED=2015-09-20T14:56:07.278613
CIRC 2 BUILT $9F7D6E6420183C2B76D3CE99624EBC98A21A967E~Nivrim,$5DEF69E67BAF2CF26D36B5AC2A925BB2EA376593~WhiteDragon,$615EBC4B48F03858FA50A3E23E5AF569D0D2308A~AccessNow004 BUILD_FLAGS=NEED_CAPACITY PURPOSE=GENERAL TIME_CREATED=2015-09-20T14:56:07.278613
CIRC 3 EXTENDED $9F7D6E6420183C2B76D3CE99624EBC98A21A967E~Nivrim,$C382878DCDB4920EF768C99D3C31981DBE7E5F93~ddorfgermany,$5BB51E650366D14C95027DB2F1D7A69BC5B00676~Richie BUILD_FLAGS=IS_INTERNAL,NEED_CAPACITY,NEED_UPTIME PURPOSE=GENERAL TIME_CREATED=2015-09-20T14:56:08.278115
CIRC 3 BUILT $9F7D6E6420183C2B76D3CE99624EBC98A21A967E~Nivrim,$C382878DCDB4920EF768C99D3C31981DBE7E5F93~ddorfgermany,$5BB51E650366D14C95027DB2F1D7A69BC5B00676~Richie BUILD_FLAGS=IS_INTERNAL,NEED_CAPACITY,NEED_UPTIME PURPOSE=GENERAL TIME_CREATED=2015-09-20T14:56:08.278115
STREAM 5 REMAP 1 93.184.216.34:80 SOURCE=EXIT
STREAM 5 SUCCEEDED 1 93.184.216.34:80
CIRC 4 EXTENDED $9F7D6E6420183C2B76D3CE99624EBC98A21A967E~Nivrim,$9D5A5D54EC2B63CBDA5345EAEA9768539E926C5E~CatRelay12 BUILD_FLAGS=IS_INTERNAL,NEED_CAPACITY,NEED_UPTIME PURPOSE=GENERAL TIME_CREATED=2015-09-20T14:56:09.278708
CIRC 4 EXTENDED $9F7D6E6420183C2B76D3CE99624EBC98A21A967E~Nivrim,$9D5A5D54EC2B63CBDA5345EAEA9768539E926C5E~CatRelay12,$E0BACC71EE7065CA3A6EAC50715886827BC9F7BA~Vienna BUILD_FLAGS=IS_INTERNAL,NEED_CAPACITY,NEED_UPTIME PURPOSE=GENERAL TIME_CREATED=2015-09-20T14:56:09.278708
CIRC 4 BUILT $9F7D6E6420183C2B76D3CE99624EBC98A21A967E~Nivrim,$9D5A5D54EC2B63CBDA5345EAEA9768539E926C5E~CatRelay12,$E0BACC71EE7065CA3A6EAC50715886827BC9F7BA~Vienna BUILD_FLAGS=IS_INTERNAL,NEED_CAPACITY,NEED_UPTIME PURPOSE=GENERAL TIME_CREATED=2015-09-20T14:56:09.278708

  # Query is done here.

STREAM 5 CLOSED 1 93.184.216.34:80 REASON=DONE

  # Dump the circuit status again.

circuit-status=
1 BUILT $9F7D6E6420183C2B76D3CE99624EBC98A21A967E~Nivrim,$B143D439B72D239A419F8DCE07B8A8EB1B486FA7~wardsback,$5FEA88EFEDC5897F7094A1759CE25BA0D3DA87E7~YellowNet BUILD_FLAGS=NEED_CAPACITY PURPOSE=GENERAL TIME_CREATED=2015-09-20T14:56:06.293922 SOCKS_USERNAME="data" SOCKS_PASSWORD="lost"
2 BUILT $9F7D6E6420183C2B76D3CE99624EBC98A21A967E~Nivrim,$5DEF69E67BAF2CF26D36B5AC2A925BB2EA376593~WhiteDragon,$615EBC4B48F03858FA50A3E23E5AF569D0D2308A~AccessNow004 BUILD_FLAGS=NEED_CAPACITY PURPOSE=GENERAL TIME_CREATED=2015-09-20T14:56:07.278613
3 BUILT $9F7D6E6420183C2B76D3CE99624EBC98A21A967E~Nivrim,$C382878DCDB4920EF768C99D3C31981DBE7E5F93~ddorfgermany,$5BB51E650366D14C95027DB2F1D7A69BC5B00676~Richie BUILD_FLAGS=IS_INTERNAL,NEED_CAPACITY,NEED_UPTIME PURPOSE=GENERAL TIME_CREATED=2015-09-20T14:56:08.278115
4 BUILT $9F7D6E6420183C2B76D3CE99624EBC98A21A967E~Nivrim,$9D5A5D54EC2B63CBDA5345EAEA9768539E926C5E~CatRelay12,$E0BACC71EE7065CA3A6EAC50715886827BC9F7BA~Vienna BUILD_FLAGS=IS_INTERNAL,NEED_CAPACITY,NEED_UPTIME PURPOSE=GENERAL TIME_CREATED=2015-09-20T14:56:09.278708
OK

comment:12 Changed 4 years ago by atagar

Resolution: worksforme
Status: reopenedclosed

Hi trodun, glad ya finally got to the root of this! You can manually construct circuits, or send a NEWNYM signal and send client traffic to cause new circuits to be generated.

If you *really* want launch_tor() to return before tor is done being launched then you can provide a completion_percent argument to tell it to return early. This will let you access tor before its test circuit is done being constructed.

comment:13 Changed 4 years ago by atagar

Oops! Didn't catch that it was you, Yawning, that figured this out. Sorry. :P

Note: See TracTickets for help on using tickets.