Browse Source

added handling of sentry/machine auth

pull/18/merge
Rossen Georgiev 9 years ago
parent
commit
68e427ed7f
  1. 92
      steam/client/__init__.py

92
steam/client/__init__.py

@ -1,5 +1,7 @@
import os
import logging import logging
import gevent import gevent
from Crypto.Hash import SHA
from eventemitter import EventEmitter from eventemitter import EventEmitter
from steam.enums.emsg import EMsg from steam.enums.emsg import EMsg
from steam.enums import EResult, EOSType from steam.enums import EResult, EOSType
@ -13,6 +15,8 @@ logger = logging.getLogger("SteamClient")
class SteamClient(EventEmitter, FeatureBase): class SteamClient(EventEmitter, FeatureBase):
current_jobid = 0 current_jobid = 0
credential_location = None
username = None
def __init__(self): def __init__(self):
self.cm = CMClient() self.cm = CMClient()
@ -20,6 +24,7 @@ class SteamClient(EventEmitter, FeatureBase):
# register listners # register listners
self.cm.on(None, self._handle_cm_events) self.cm.on(None, self._handle_cm_events)
self.on(EMsg.ClientLogOnResponse, self._handle_logon) self.on(EMsg.ClientLogOnResponse, self._handle_logon)
self.on(EMsg.ClientUpdateMachineAuth, self._handle_update_machine_auth)
self.on("disconnected", self._handle_disconnect) self.on("disconnected", self._handle_disconnect)
self.logged_on = False self.logged_on = False
@ -36,11 +41,14 @@ class SteamClient(EventEmitter, FeatureBase):
logger.debug("Emit event: %s" % repr(event)) logger.debug("Emit event: %s" % repr(event))
super(SteamClient, self).emit(event, *args) super(SteamClient, self).emit(event, *args)
def set_credential_location(self, path):
self.credential_location = path
@property @property
def steam_id(self): def steam_id(self):
return self.cm.steam_id return self.cm.steam_id
@property
@property
def connected(self): def connected(self):
return self.cm.connected return self.cm.connected
@ -65,6 +73,7 @@ class SteamClient(EventEmitter, FeatureBase):
self.emit("job_%d" % jobid, *args) self.emit("job_%d" % jobid, *args)
def _handle_disconnect(self): def _handle_disconnect(self):
self.username = None
self.logged_on = False self.logged_on = False
self.current_jobid = 0 self.current_jobid = 0
@ -80,13 +89,30 @@ class SteamClient(EventEmitter, FeatureBase):
self.disconnect() self.disconnect()
if result in (EResult.AccountLogonDenied, if result in (EResult.AccountLogonDenied,
EResult.AccountLoginDeniedNeedTwoFactor, EResult.AccountLoginDeniedNeedTwoFactor,
EResult.TwoFactorCodeMismatch, EResult.TwoFactorCodeMismatch,
): ):
self.emit("auth_code_required", result) self.emit("auth_code_required", result)
else: else:
self.emit("error", result) self.emit("error", result)
def _handle_update_machine_auth(self, message):
ok = self.store_sentry(self.username, message.body.bytes)
if ok:
resp = MsgProto(EMsg.ClientUpdateMachineAuthResponse)
resp.header.jobid_target = message.header.jobid_source
resp.body.filename = message.body.filename
resp.body.eresult = EResult.OK
resp.body.sha_file = SHA.new(message.body.bytes).digest()
resp.body.getlasterror = 0
resp.body.offset = message.body.offset
resp.body.cubwrote = message.body.cubtowrite
self.send(resp)
def send(self, message): def send(self, message):
if not self.connected: if not self.connected:
raise RuntimeError("Cannot send message while not connected") raise RuntimeError("Cannot send message while not connected")
@ -116,21 +142,44 @@ class SteamClient(EventEmitter, FeatureBase):
if not self.cm.channel_secured: if not self.cm.channel_secured:
self.wait_event("channel_secured") self.wait_event("channel_secured")
def anonymous_login(self): def _get_sentry_path(self, username):
logger.debug("Attempting Anonymous login") if self.credential_location is not None:
return os.path.join(self.credential_location,
self._pre_login() "%s_sentry.bin" % username
)
message = MsgProto(EMsg.ClientLogon) return None
message.header.steamid = SteamID(type='AnonUser', universe='Public')
message.body.protocol_version = 65575 def get_sentry(self, username):
self.send(message) filepath = self._get_sentry_path(username)
if filepath and os.path.isfile(filepath):
try:
with open(filepath, 'r') as f:
return f.read()
except IOError as e:
logger.error("get_sentry: %s" % str(e))
return None
def store_sentry(self, username, sentry_bytes):
filepath = self._get_sentry_path(username)
if filepath:
try:
with open(filepath, 'w') as f:
f.write(sentry_bytes)
return True
except IOError as e:
logger.error("store_sentry: %s" % str(e))
return False
def login(self, username, password, auth_code=None, two_factor_code=None, remember=False): def login(self, username, password, auth_code=None, two_factor_code=None, remember=False):
logger.debug("Attempting login") logger.debug("Attempting login")
self._pre_login() self._pre_login()
self.username = username
message = MsgProto(EMsg.ClientLogon) message = MsgProto(EMsg.ClientLogon)
message.header.steamid = SteamID(type='Individual', universe='Public') message.header.steamid = SteamID(type='Individual', universe='Public')
message.body.protocol_version = 65575 message.body.protocol_version = 65575
@ -141,6 +190,13 @@ class SteamClient(EventEmitter, FeatureBase):
message.body.account_name = username message.body.account_name = username
message.body.password = password message.body.password = password
sentry = self.get_sentry(username)
if sentry is None:
message.body.eresult_sentryfile = EResult.FileNotFound
else:
message.body.eresult_sentryfile = EResult.OK
message.body.sha_sentryfile = SHA.new(sentry).digest()
if auth_code: if auth_code:
message.body.auth_code = auth_code message.body.auth_code = auth_code
if two_factor_code: if two_factor_code:
@ -148,6 +204,16 @@ class SteamClient(EventEmitter, FeatureBase):
self.send(message) self.send(message)
def anonymous_login(self):
logger.debug("Attempting Anonymous login")
self._pre_login()
message = MsgProto(EMsg.ClientLogon)
message.header.steamid = SteamID(type='AnonUser', universe='Public')
message.body.protocol_version = 65575
self.send(message)
def logout(self): def logout(self):
if self.logged_on: if self.logged_on:
self.logged_on = False self.logged_on = False

Loading…
Cancel
Save