NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

GPS.py (39878B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\script\net\GPS.py
      2 import marshal
      3 import socket
      4 import sys
      5 import types
      6 import blue
      7 import carbon.common.lib.const as const
      8 import carbon.common.script.net.machobase as macho
      9 import evecrypto.crypto as Crypto
     10 import localization
     11 import log
     12 import uthread
     13 from carbon.common.script.net.GPSExceptions import GPSTransportClosed, GPSRemoteTransportClosed
     14 from carbon.common.script.net.machoNetExceptions import UserRejectedByVIP
     15 from carbon.common.script.util.format import CaseFold
     16 from eveexceptions import UserError
     17 from eveprefs import prefs, boot
     18 from eve.common.script.util.writebuffer import WriteBuffer
     19 Enter = blue.pyos.taskletTimer.EnterTasklet
     20 Leave = blue.pyos.taskletTimer.ReturnFromTasklet
     21 ClientConnectFailed = socket.error
     22 
     23 def ClientConnectFailedString(e):
     24     return e.args[1]
     25 
     26 
     27 def GetHostByName_Ex(host):
     28     return socket.gethostbyname_ex(host)[2]
     29 
     30 
     31 def GetAddrInfo(host):
     32     return [ e[4][0] for e in socket.getaddrinfo(host, None) if e[0] == socket.AF_INET and not e[4][0].startswith('0.') ]
     33 
     34 
     35 error = socket.error
     36 gethostname = socket.gethostname
     37 
     38 class GPSTransportFactory(object):
     39     __guid__ = 'gps.GPSTransportFactory'
     40 
     41     def __init__(self, useacl = 0, name = '(unknown)'):
     42         self.useACL = useacl
     43         self.name = name
     44 
     45     def Listen(self, address):
     46         pass
     47 
     48     def Connect(self, address):
     49         pass
     50 
     51 
     52 class GPSAddressable(object):
     53 
     54     def GetAddress(self):
     55         return self.address
     56 
     57     def GetESPAddress(self):
     58         return self.__GetPrefixedAddress('externalNetPrefix', natOffset=True)
     59 
     60     def GetExternalAddress(self):
     61         return self.__GetPrefixedAddress('externalNetPrefix')
     62 
     63     def GetInternalAddress(self):
     64         return self.__GetPrefixedAddress('internalNetPrefix')
     65 
     66     def __GetPrefixedAddress(self, prefixWhat, natOffset = False):
     67         host, port = self.address.split(':')
     68         addresses = GetAddrInfo(host)
     69         ipaddress = None
     70         find = [prefixWhat + '_' + macho.mode, prefixWhat, 'externalNetPrefix']
     71         for prefValue in find:
     72             prefix = str(prefs.GetValue(prefValue, ''))
     73             if prefix:
     74                 break
     75 
     76         if prefix:
     77             if not prefs.GetValue('enableNewStyleNetworkPrefix', False):
     78                 lastDot = addresses[0].rindex('.')
     79                 ipaddress = prefix + addresses[0][lastDot + 1:]
     80                 if len(ipaddress.split('.')) != 4:
     81                     raise RuntimeError('Configuration Error:  %s MUST contain precisely three dots' % prefixWhat)
     82             elif prefValue == 'externalNetPrefix_proxy':
     83                 lastDot = addresses[0].rindex('.')
     84                 lastBit = int(addresses[0][lastDot + 1:])
     85                 if natOffset:
     86                     lastBit += int(prefs.GetValue('externalNetNatOffset', 0))
     87                 ipaddress = prefix + str(lastBit)
     88                 if len(ipaddress.split('.')) != 4:
     89                     raise RuntimeError('Configuration Error:  %s MUST contain precisely three dots' % prefixWhat)
     90             else:
     91                 found = False
     92                 for ipaddress in GetHostByName_Ex(''):
     93                     if ipaddress.startswith(prefix):
     94                         found = True
     95                         break
     96 
     97                 if not found:
     98                     raise RuntimeError('Configuration Error:  unable to find IP for %s using prefix %s ' % (prefixWhat, prefix))
     99         elif len(addresses) == 1:
    100             ipaddress = addresses[0]
    101         elif prefs.clusterMode not in ('LIVE', 'TEST'):
    102             for address in addresses:
    103                 if address.startswith('10.0.'):
    104                     continue
    105                 if address.startswith('172.'):
    106                     continue
    107                 ipaddress = address
    108                 break
    109 
    110             if ipaddress is None:
    111                 raise RuntimeError('No sane interfaces found from %s', addresses)
    112         else:
    113             raise RuntimeError("Configuration Error:  Multiple potential %s addresses, couldn't determine which one to use." % prefixWhat)
    114         return '%s:%s' % (ipaddress, port)
    115 
    116 
    117 class GPSTransportAcceptor(GPSAddressable):
    118     __guid__ = 'gps.GPSTransportAcceptor'
    119 
    120     def __init__(self, useACL):
    121         self.useACL = useACL
    122 
    123     def CheckACL(self, address):
    124         if self.useACL:
    125             return sm.services['machoNet'].CheckACL(address)
    126 
    127     def Accept(self):
    128         return None
    129 
    130     def Close(self, reason = None, reasonCode = None, reasonArgs = {}):
    131         pass
    132 
    133 
    134 class GPSTransport(GPSAddressable):
    135     __guid__ = 'gps.GPSTransport'
    136     __mandatory_fields__ = []
    137     __HANDSHAKE_SECRET_KEY = 170472
    138 
    139     def __init__(self, *args, **keywords):
    140         self.cryptoContext = Crypto.CryptoCreateContext()
    141         self.handShakePaddingLength = boot.GetValue('handShakePaddingLength', 64)
    142         self.handShake = None
    143 
    144     def ProxyAuthenticationHandshakeLoad(self, packet):
    145         global blue
    146         ret = blue.marshal.Load(packet, skipCrcCheck=True)
    147         if macho.mode != 'proxy':
    148             log.LogError('ProxyAuthenticationHandshakeLoad can only be called on a proxy, currently on: ' + macho.mode)
    149             raise GPSTransportClosed('ProxyAuthenticationHandshakeLoad called on an incorrect macho.mode')
    150         if isinstance(ret, GPSTransportClosed):
    151             raise ret
    152         if not isinstance(ret, tuple):
    153             log.LogError('ProxyAuthenticationHandshakeLoad Deserialized an unexpected type ' + type(ret).__name__ + ' but only (tuple,) is allowed.')
    154             raise GPSTransportClosed('ProxyAuthenticationHandshakeLoad - Deserialized an unexpected type')
    155         return ret
    156 
    157     def Read(self):
    158         pass
    159 
    160     def Write(self, packet):
    161         pass
    162 
    163     def Close(self, reason = None, reasonCode = None, reasonArgs = {}):
    164         pass
    165 
    166     def IsClosed(self):
    167         return True
    168 
    169     def ApplyWithTimeout(self, func, args, timeout = 120, message = None):
    170         rts = [0]
    171         t = uthread.worker('machoNet::TimeoutWorker', self.TimeoutWorker, self, timeout, rts, message)
    172         try:
    173             ret = func(*args)
    174         finally:
    175             rts[0] = 1
    176             t.kill()
    177 
    178         return ret
    179 
    180     @staticmethod
    181     def TimeoutWorker(transport, secs, rts, message = None):
    182         try:
    183             blue.pyos.synchro.SleepWallclock(1000 * secs)
    184             if not rts[0]:
    185                 transport.Close(*message)
    186         except TaskletExit:
    187             pass
    188 
    189     def HandleClientAuthenticationStep1(self, transportID, counter):
    190         handshakeTimeout = prefs.GetValue('GpsCompatibilityHandshakeTimeout', 120) * (10 if counter else 1)
    191         log.general.Log('GPS[%d]: HandleClientAuthentication waiting for handshake (timeout=%ds, counter=%d)' % (transportID, handshakeTimeout, counter), log.LGINFO)
    192         message = (localization.GetByLabel('/Carbon/GPS/ConnectionTimeoutClientNotCompatible'), 'HANDSHAKE_TIMEOUT_CLIENTCOMPATIBILITYHANDSHAKE')
    193         packet = self.ApplyWithTimeout(self.UnEncryptedRead, (), message=message, timeout=handshakeTimeout)
    194         if len(packet) == 0:
    195             log.general.Log('Handshake Failed - Empty packet from %s' % self.GetAddress(), log.LGERR)
    196             self.Close(localization.GetByLabel('/Carbon/GPS/IncompatibleProtocol'), 'HANDSHAKE_INCOMPATIBLEPROTOCOL')
    197             return 'ERR'
    198         response = self.ProxyAuthenticationHandshakeLoad(packet)
    199         if not isinstance(response, tuple):
    200             log.general.Log('Deserialized an unexpected type %s during ClientAuthenticationStep1 where only (tuple) is allowed' % type(response).__name__, log.LGERR)
    201             self.Close(localization.GetByLabel('/Carbon/GPS/IncompatibleProtocol'), 'HANDSHAKE_FAILEDVERIFICATION')
    202             return 'ERR'
    203         if len(response) != 6:
    204             log.general.Log('Returned tuple type in ClientAuthenticationStep1 has length=%d but should be length=6' % len(response), log.LGERR)
    205             self.Close(localization.GetByLabel('/Carbon/GPS/IncompatibleProtocol'), 'HANDSHAKE_FAILEDVERIFICATION')
    206             return 'ERR'
    207         if not isinstance(response[0], int):
    208             log.general.Log('HandshakeSecretKey is of unexpected type %s, should be int' % type(response[0]).__name__, log.LGERR)
    209             self.Close(localization.GetByLabel('/Carbon/GPS/IncompatibleProtocol'), 'HANDSHAKE_FAILEDVERIFICATION')
    210             return 'ERR'
    211         if response[0] != GPSTransport.__HANDSHAKE_SECRET_KEY:
    212             log.general.Log('HandshakeSecretKey value=%s failed validation, should be %s' % (response[0], GPSTransport.__HANDSHAKE_SECRET_KEY), log.LGERR)
    213             self.Close(localization.GetByLabel('/Carbon/GPS/IncompatibleProtocol'), 'HANDSHAKE_FAILEDVERIFICATION')
    214             return 'ERR'
    215         if not isinstance(response[1], int):
    216             log.general.Log('macho.version is of unexpected type %s, should be int' % type(response[1]).__name__, log.LGERR)
    217             self.Close(localization.GetByLabel('/Carbon/GPS/IncompatibleProtocol'), 'HANDSHAKE_INCOMPATIBLEPROTOCOL')
    218             return 'ERR'
    219         if macho.version != response[1]:
    220             log.general.Log('Handshake Failed - Insecure Macho Version Mismatch - Client: %s - Server: %s' % (response[1], macho.version), log.LGERR)
    221             self.Close(localization.GetByLabel('/Carbon/GPS/IncompatibleProtocol'), 'HANDSHAKE_INCOMPATIBLEPROTOCOL')
    222             return 'ERR'
    223         if not isinstance(response[2], int):
    224             log.general.Log('loggedOnUserCount is of unexpected type %s, should be int' % type(response[2]).__name__, log.LGERR)
    225             self.Close(localization.GetByLabel('/Carbon/GPS/IncompatibleProtocol'), 'HANDSHAKE_FAILEDVERIFICATION')
    226             return 'ERR'
    227         if not isinstance(response[3], float):
    228             log.general.Log('boot.version is of unexpected type %s, should be float' % type(response[3]).__name__, log.LGERR)
    229             self.Close(localization.GetByLabel('/Carbon/GPS/IncompatibleVersion'), 'HANDSHAKE_INCOMPATIBLEVERSION')
    230             return 'ERR'
    231         if boot.version != response[3]:
    232             log.general.Log('Handshake Failed - Insecure Boot Version Mismatch (common.ini:version) - Client: %s - Server: %s' % (response[3], boot.version), log.LGERR)
    233             self.Close(localization.GetByLabel('/Carbon/GPS/IncompatibleVersion'), 'HANDSHAKE_INCOMPATIBLEVERSION')
    234             return 'ERR'
    235         if not isinstance(response[4], (int, unicode, str)):
    236             log.general.Log('boot.build is of unexpected type %s, should be one of (int, unicode, str)' % type(response[4]).__name__, log.LGERR)
    237             self.Close(localization.GetByLabel('/Carbon/GPS/IncompatibleBuild'), 'HANDSHAKE_INCOMPATIBLEBUILD')
    238             return 'ERR'
    239         if boot.build > response[4]:
    240             log.general.Log('Handshake Failed - Insecure Boot Build Mismatch (common.ini:build) - Client: %s - Server: %s' % (response[4], boot.build), log.LGERR)
    241             self.Close(localization.GetByLabel('/Carbon/GPS/IncompatibleBuild'), 'HANDSHAKE_INCOMPATIBLEBUILD')
    242             return 'ERR'
    243         if not isinstance(response[5], (str, unicode)):
    244             log.general.Log('Combined boot.codename+@+boot.region is of unexpected type %s, should be one of (str, unicode)' % type(response[5]).__name__, log.LGERR)
    245             self.Close(localization.GetByLabel('/Carbon/GPS/IncompatibleProtocol'), 'HANDSHAKE_FAILEDVERIFICATION')
    246             return 'ERR'
    247         if '@' in response[5]:
    248             codename, region = response[5].split('@')
    249         else:
    250             codename, region = response[5], ''
    251         if str(boot.region) != region:
    252             if boot.role == 'client':
    253                 log.general.Log('Handshake Failed - Insecure Region Code Mismatch (common.ini:region) - Client: %s - Server: %s' % (region, str(boot.region)), log.LGERR)
    254             self.Close(localization.GetByLabel('/Carbon/GPS/IncompatibleRegion'), 'HANDSHAKE_INCOMPATIBLEREGION')
    255             return 'ERR'
    256         if str(boot.codename) != codename:
    257             log.general.Log('Handshake Failed - Insecure Boot Code Name Mismatch (common.ini:codename) - Client: %s - Server: %s' % (codename, str(boot.codename)), log.LGERR)
    258             self.Close(localization.GetByLabel('/Carbon/GPS/IncompatibleRelease'), 'HANDSHAKE_INCOMPATIBLERELEASE')
    259             return 'ERR'
    260         return 'OK'
    261 
    262     def HandleClientAuthenticationStep2(self, transportID, counter, eveInVIP):
    263         log.general.Log('LLV Reading Client Crypto Context OR VIP Key OR Queue Check', log.LGINFO)
    264         vipKey = None
    265         message = (localization.GetByLabel('/Carbon/GPS/ConnectionTimeoutNoCompatibilityHandshake'), 'HANDSHAKE_TIMEOUT_CLIENTSECUREHANDSHAKE')
    266         clientCryptoContextPacket = self.ProxyAuthenticationHandshakeLoad(self.ApplyWithTimeout(self.UnEncryptedRead, (), message=message))
    267         if not isinstance(clientCryptoContextPacket, tuple):
    268             log.general.Log('Deserialized an unexpected type %s during ClientAuthenticationStep2 where only (tuple) is allowed' % type(clientCryptoContextPacket).__name__, log.LGERR)
    269             self.Close(localization.GetByLabel('/Carbon/GPS/IncompatibleProtocol'), 'HANDSHAKE_FAILEDVERIFICATION')
    270             return ('ERR', None, None, None)
    271         if len(clientCryptoContextPacket) not in (2, 3):
    272             log.general.Log('Returned tuple type in ClientAuthenticationStep2 has length=%d but should be length=2or3' % len(clientCryptoContextPacket), log.LGERR)
    273             self.Close(localization.GetByLabel('/Carbon/GPS/IncompatibleProtocol'), 'HANDSHAKE_FAILEDVERIFICATION')
    274             return ('ERR', None, None, None)
    275         if not isinstance(clientCryptoContextPacket[1], str):
    276             log.general.Log('ClientCryptContextPacket element[1] is of unexpected type %s, should be str' % type(clientCryptoContextPacket[1]).__name__, log.LGERR)
    277             self.Close(localization.GetByLabel('/Carbon/GPS/IncompatibleProtocol'), 'HANDSHAKE_FAILEDVERIFICATION')
    278             return ('ERR', None, None, None)
    279         if len(clientCryptoContextPacket) == 3 and not isinstance(clientCryptoContextPacket[2], str):
    280             log.general.Log('ClientCryptContextPacket element[2] is of unexpected type %s, should be str' % type(clientCryptoContextPacket[2]).__name__, log.LGERR)
    281             self.Close(localization.GetByLabel('/Carbon/GPS/IncompatibleProtocol'), 'HANDSHAKE_FAILEDVERIFICATION')
    282             return ('ERR', None, None, None)
    283         if clientCryptoContextPacket[0] is None and clientCryptoContextPacket[1] == 'VK':
    284             vipKey = clientCryptoContextPacket[2]
    285         if clientCryptoContextPacket[0] is None and clientCryptoContextPacket[1] == 'VK':
    286             log.general.Log('LLV Reading Client Crypto Context OR Queue Check', log.LGINFO)
    287             message = (localization.GetByLabel('/Carbon/GPS/ConnectionTimeoutNoCompatibilityHandshake'), 'HANDSHAKE_TIMEOUT_CLIENTSECUREHANDSHAKE')
    288             clientCryptoContextPacket = self.ProxyAuthenticationHandshakeLoad(self.ApplyWithTimeout(self.UnEncryptedRead, (), message=message))
    289         if counter == 0:
    290             sm.GetService('machoNet').PutTransportInLogonQueue(transportID)
    291         logonQueuePosition = sm.GetService('machoNet').GetLogonQueuePosition(transportID, vipKey)
    292         if clientCryptoContextPacket[0] is None and clientCryptoContextPacket[1] == 'QC':
    293             if eveInVIP:
    294                 self.Close(localization.GetByLabel('/Carbon/GPS/NotAcceptingConnections'), 'ACL_NOTACCEPTING')
    295                 return ('OK', None, None, None)
    296             log.general.Log('Logon Queue Position Query - Complete', log.LGINFO)
    297             self.UnEncryptedWrite(macho.Dumps(logonQueuePosition))
    298             return ('OK', None, None, None)
    299         log.general.Log('LLV Reading Client Crypto Context', log.LGINFO)
    300         keyVersion, request = clientCryptoContextPacket
    301         if keyVersion != getattr(macho, 'publicKeyVersion', 'placebo'):
    302             log.general.Log('Handshake Failed - Public Key Mismatch - Public Key Version is %s but should be %s' % (keyVersion, getattr(macho, 'publicKeyVersion', 'placebo')), log.LGERR)
    303             self.Close(localization.GetByLabel('/Carbon/GPS/IncompatiblePublicKey'), 'HANDSHAKE_INCOMPATIBLEPUBLICKEY')
    304             return ('ERR', None, None, None)
    305         log.general.Log('LLV Initializing Crypto Context', log.LGINFO)
    306         cryptoCtxRequest = self.cryptoContext.Initialize(request)
    307         if type(cryptoCtxRequest) != types.DictType:
    308             self.Close('Handshake Failed - ' + cryptoCtxRequest)
    309             return ('ERR', None, None, None)
    310         return (None,
    311          vipKey,
    312          logonQueuePosition,
    313          cryptoCtxRequest)
    314 
    315     def HandleClientAuthenticationStep3(self, request):
    316         passwordVersion = 0
    317         userName = None
    318         passwordVersionOK = False
    319         passwordVersionAttempteRemaining = 2
    320         while not passwordVersionOK:
    321             if passwordVersionAttempteRemaining < 1:
    322                 self.Close('Password version handshake failure')
    323                 return ('ERR', None, None)
    324             passwordVersionAttempteRemaining -= 1
    325             log.general.Log('LLV Reading Secure Client Handshake', log.LGINFO)
    326             message = (localization.GetByLabel('/Carbon/GPS/ConnectionTimeoutNoCompatibilityHandshake'), 'HANDSHAKE_TIMEOUT_CLIENTSECUREHANDSHAKE')
    327             clientChallenge, request2 = self.ProxyAuthenticationHandshakeLoad(self.ApplyWithTimeout(self.EncryptedRead, (), message=message))
    328             if not isinstance(clientChallenge, str):
    329                 log.general.Log('Deserialized an unexpected type %s of clientChallenge during ClientAuthenticationStep3 where only str is allowed' % type(clientChallenge).__name__, log.LGERR)
    330                 self.Close(localization.GetByLabel('/Carbon/GPS/IncompatibleProtocol'), 'HANDSHAKE_FAILEDVERIFICATION')
    331                 return ('ERR', None, None)
    332             if not isinstance(request2, types.DictType):
    333                 log.general.Log('Deserialized an unexpected type %s of request2 during ClientAuthenticationStep3 where only types.DictType is allowed' % type(request2).__name__, log.LGERR)
    334                 self.Close(localization.GetByLabel('/Carbon/GPS/IncompatibleProtocol'), 'HANDSHAKE_FAILEDVERIFICATION')
    335                 return ('ERR', None, None)
    336             request.update(request2)
    337             log.general.Log('LLV Verifying Secure Client Handshake', log.LGINFO)
    338             for k in self.__mandatory_fields__:
    339                 if k not in request:
    340                     self.Close('Handshake corrupt, missing %s' % k)
    341                     return ('ERR', None, None)
    342 
    343             if passwordVersion == 0 or userName != request['user_name']:
    344                 passwordVersion = 2
    345                 userName = request['user_name']
    346             if passwordVersionAttempteRemaining == 1:
    347                 log.general.Log('LLV Writing password version', log.LGINFO)
    348                 self.EncryptedWrite(macho.Dumps(passwordVersion))
    349             if passwordVersion == 1:
    350                 if request['user_password'] is not None:
    351                     passwordVersionOK = True
    352             else:
    353                 passwordVersionOK = True
    354 
    355         log.general.Log('LLV Performing Version Check', log.LGINFO)
    356         if str(boot.region) != request['boot_region']:
    357             log.general.Log('Handshake Failed - Boot Region Mismatch - Boot Region is %s but should be %s' % (request['boot.region'], str(boot.region)), log.LGERR)
    358             self.Close(localization.GetByLabel('/Carbon/GPS/IncompatibleRegion'), 'HANDSHAKE_INCOMPATIBLEREGION')
    359             return ('ERR', None, None)
    360         if str(boot.codename) != request['boot_codename']:
    361             log.general.Log('Handshake Failed - Boot Code Name Mismatch - Boot Code Name is %s but should be %s' % (request['boot.codeName'], str(boot.codename)), log.LGERR)
    362             self.Close(localization.GetByLabel('/Carbon/GPS/IncompatibleRelease'), 'HANDSHAKE_INCOMPATIBLERELEASE')
    363             return ('ERR', None, None)
    364         if boot.version != request['boot_version']:
    365             log.general.Log('Handshake Failed - Boot Version Mismatch - Boot Version is %s but should be %s' % (request['boot.version'], boot.version), log.LGERR)
    366             self.Close(localization.GetByLabel('/Carbon/GPS/IncompatibleVersion'), 'HANDSHAKE_INCOMPATIBLEVERSION')
    367             return ('ERR', None, None)
    368         if macho.version != request['macho_version']:
    369             log.general.Log('Handshake Failed - Macho Version Mismatch - Macho Version is %s but should be %s' % (request['macho.version'], macho.version), log.LGERR)
    370             self.Close(localization.GetByLabel('/Carbon/GPS/IncompatibleProtocol'), 'HANDSHAKE_INCOMPATIBLEPROTOCOL')
    371             return ('ERR', None, None)
    372         if boot.build > request['boot_build']:
    373             log.general.Log('Handshake Failed - Boot Build Mismatch - Boot Build is %s but should be at least %s' % (request['boot.build'], boot.build), log.LGERR)
    374             self.Close(localization.GetByLabel('/Carbon/GPS/IncompatibleBuild'), 'HANDSHAKE_INCOMPATIBLEBUILD')
    375             return ('ERR', None, None)
    376         if len(clientChallenge) != self.handShakePaddingLength:
    377             self.Close(localization.GetByLabel('/Carbon/GPS/IncorrentHandshakePadding', current=len(clientChallenge), expected=self.handShakePaddingLength))
    378             return ('ERR', None, None)
    379         handShakeHash = Crypto.CryptoHash(clientChallenge)
    380         return (None, request, handShakeHash)
    381 
    382     def HandleClientAuthentication(self, loggedOnUserCount, transportID, counter, sessionID, eveInVIP):
    383         timer = Enter('machoNet::GPS::HandleClientAuthentication')
    384         try:
    385             try:
    386                 updateInfo = sm.GetService('machoNet').GetValidClientCodeHash()
    387             except:
    388                 log.general.Log('Clienthash info not available', log.LGINFO)
    389                 updateInfo = const.responseUnknown
    390 
    391             initialHandshakeRequest = (GPSTransport.__HANDSHAKE_SECRET_KEY,
    392              macho.version,
    393              loggedOnUserCount,
    394              boot.version,
    395              boot.build,
    396              str(boot.codename) + '@' + str(boot.region),
    397              updateInfo)
    398             self.UnEncryptedWrite(macho.Dumps(initialHandshakeRequest))
    399             step1Response = self.HandleClientAuthenticationStep1(transportID, counter)
    400             if step1Response != 'OK':
    401                 return step1Response
    402             step2ReturnCode, vipKey, logonQueuePosition, request = self.HandleClientAuthenticationStep2(transportID, counter, eveInVIP)
    403             if step2ReturnCode is not None:
    404                 return step2ReturnCode
    405             self.UnEncryptedWrite(macho.Dumps('OK CC'))
    406             step3ReturnCode, request, handShakeHash = self.HandleClientAuthenticationStep3(request)
    407             if step3ReturnCode is not None:
    408                 return step3ReturnCode
    409             try:
    410                 globalConfig = sm.GetService('machoNet').GetGlobalConfig()
    411             except:
    412                 log.LogException()
    413                 globalConfig = {}
    414 
    415             log.general.Log('LLV Generating Server Challenge', log.LGINFO)
    416             dict = {'challenge_responsehash': handShakeHash,
    417              'macho_version': macho.version,
    418              'boot_version': boot.version,
    419              'boot_build': boot.build,
    420              'boot_codename': str(boot.codename),
    421              'boot_region': str(boot.region),
    422              'cluster_usercount': loggedOnUserCount,
    423              'proxy_nodeid': sm.GetService('machoNet').GetNodeID(),
    424              'user_logonqueueposition': logonQueuePosition,
    425              'config_vals': globalConfig}
    426             serverChallenge = Crypto.GetRandomBytes(self.handShakePaddingLength)
    427             log.general.Log('LLV Crypting Server Challenge', log.LGINFO)
    428             from carbon.server.script.net import handShake
    429             code = marshal.dumps(handShake.GetHandshakeFunc())
    430             ch = (serverChallenge,
    431              Crypto.Sign(code),
    432              {},
    433              dict)
    434             log.general.Log('LLV Writing Server Challenge', log.LGINFO)
    435             self.EncryptedWrite(macho.Dumps(ch))
    436             if not request['user_name'] or not (request['user_password'] or request['user_password_hash']) or logonQueuePosition > 1:
    437                 return 'OK'
    438             if vipKey and vipKey != Crypto.CryptoHash(CaseFold(request['user_name'] or '')):
    439                 self.Close(localization.GetByLabel('/Carbon/GPS/HandshakeFailedVIPKey'))
    440                 return 'ERR'
    441             log.general.Log('LLV Reading Client Challenge-Response', log.LGINFO)
    442             message = (localization.GetByLabel('/Carbon/GPS/ConnectionTimeoutClientTimeout'), 'HANDSHAKE_TIMEOUT_CLIENTRESPONSETOSERVERCHALLENGE')
    443             challengeResponse, funcOutput, funcResult = self.ProxyAuthenticationHandshakeLoad(self.ApplyWithTimeout(self.EncryptedRead, (), message=message))
    444             if not isinstance(challengeResponse, str):
    445                 log.general.Log('Deserialized an unexpected type %s of challengeResponse where only str is allowed' % type(challengeResponse).__name__, log.LGERR)
    446                 self.Close(localization.GetByLabel('/Carbon/GPS/IncompatibleProtocol'), 'HANDSHAKE_FAILEDVERIFICATION')
    447                 return 'ERR'
    448             if not isinstance(funcOutput, str):
    449                 log.general.Log('Deserialized an unexpected type %s of funcOutput where only str is allowed' % type(funcOutput).__name__, log.LGERR)
    450                 self.Close(localization.GetByLabel('/Carbon/GPS/IncompatibleProtocol'), 'HANDSHAKE_FAILEDVERIFICATION')
    451                 return 'ERR'
    452             if not isinstance(funcResult, types.DictType):
    453                 log.general.Log('Deserialized an unexpected type %s of funcResult where only types.DictType is allowed' % type(funcResult).__name__, log.LGERR)
    454                 self.Close(localization.GetByLabel('/Carbon/GPS/IncompatibleProtocol'), 'HANDSHAKE_FAILEDVERIFICATION')
    455                 return 'ERR'
    456             if funcResult.get('errors', ''):
    457                 log.general.Log('Errors in verifying handshake function %s' % funcResult['errors'], log.LGERR)
    458             if challengeResponse != Crypto.CryptoHash(serverChallenge):
    459                 self.Close(localization.GetByLabel('/Carbon/GPS/HandshakeFailedHashMismatch'))
    460                 return 'ERR'
    461             verification = handShake.Verify(funcOutput, funcResult, request)
    462             if verification is not None:
    463                 self.Close(localization.GetByLabel('/Carbon/GPS/HandshakeFailedVerificationFailure', verification=verification), 'HANDSHAKE_FAILEDVERIFICATION')
    464                 return 'ERR'
    465             request['handshakefunc_output'] = funcOutput
    466             request['handshakefunc_result'] = funcResult
    467             try:
    468                 authenticationResult = sm.GetService('machoNet').Authenticate(self, request, sessionID)
    469                 request.update(authenticationResult)
    470             except UserRejectedByVIP:
    471                 if not sm.GetService('machoNet').IsClusterShuttingDown():
    472                     log.general.Log("Handshake Failed - VIP Check - The cluster is running in VIP mode, and you're not kewl", log.LGINFO)
    473                 self.Close(localization.GetByLabel('/Carbon/GPS/NotAcceptingConnections'), 'ACL_NOTACCEPTING')
    474                 return 'OK'
    475             except UserError as e:
    476                 self.Close(e.msg, e.msg, e.dict)
    477                 return 'ERR'
    478             except RuntimeError as e:
    479                 self.Close(e.msg, e.msg, e.dict)
    480                 return 'ERR'
    481             except Exception:
    482                 log.LogException('Handshake Failed - Server Failure')
    483                 self.Close(localization.GetByLabel('/Carbon/GPS/HandshakeFailedServerFailure'))
    484                 return 'ERR'
    485 
    486             authenticationResult['live_updates'] = sm.GetService('liveUpdateMgr').GetLiveUpdates(request)
    487             authenticationResult['client_hash'] = sm.GetService('machoNet').GetValidClientCodeHash()
    488             log.general.Log('LLV Writing Server Challenge-Response-Ack', log.LGINFO)
    489             self.EncryptedWrite(macho.Dumps(authenticationResult))
    490             log.general.Log('LLV Succeeded', log.LGINFO)
    491             self.handShake = request
    492             return request
    493         finally:
    494             Leave(timer)
    495 
    496     def Authenticate(self, username, password, token):
    497         timer = Enter('machoNet::GPS::Authenticate')
    498         try:
    499             message = (localization.GetByLabel('/Carbon/GPS/ConnectionTimeoutNoCompatibilityHandshake'), 'HANDSHAKE_TIMEOUT_FAILEDSERVERINITIATECOMPATIBILITYHANDSHAKE')
    500             response = macho.Loads(self.ApplyWithTimeout(self.UnEncryptedRead, (), message=message))
    501             insecresp = {'macho_version': response[1],
    502              'cluster_usercount': response[2],
    503              'boot_version': response[3],
    504              'boot_build': response[4],
    505              'update_info': response[6]}
    506             if '@' in response[5]:
    507                 insecresp['boot_codename'], insecresp['boot_region'] = response[5].split('@')
    508             else:
    509                 insecresp['boot_codename'], insecresp['boot_region'] = response[5], ''
    510             if str(boot.region) != insecresp['boot_region']:
    511                 log.general.Log('Handshake Failed - Insecure Boot Region Mismatch (common.ini:region) - Server: %s  - Client: %s' % (insecresp['boot_region'], str(boot.region)), log.LGERR)
    512                 self.Close(localization.GetByLabel('/Carbon/GPS/IncompatibleRegion'), 'HANDSHAKE_INCOMPATIBLEREGION')
    513                 raise GPSTransportClosed(localization.GetByLabel('/Carbon/GPS/IncompatibleRegion'), 'HANDSHAKE_INCOMPATIBLEREGION', machoVersion=response[1], version=response[3], build=response[4], codename=insecresp['boot_codename'], region=insecresp['boot_region'], loggedOnUserCount=response[2])
    514             if str(boot.codename) != insecresp['boot_codename']:
    515                 log.general.Log('Handshake Failed - Insecure Boot Code Name Mismatch  (common.ini:codename) - Server: %s - Client: %s' % (insecresp['boot_codename'], str(boot.codename)), log.LGERR)
    516                 self.Close(localization.GetByLabel('/Carbon/GPS/IncompatibleRelease'), 'HANDSHAKE_INCOMPATIBLERELEASE')
    517                 raise GPSTransportClosed(localization.GetByLabel('/Carbon/GPS/IncompatibleRelease'), 'HANDSHAKE_INCOMPATIBLERELEASE', machoVersion=response[1], version=response[3], build=response[4], codename=insecresp['boot_codename'], region=insecresp['boot_region'], loggedOnUserCount=response[2])
    518             if boot.version != response[3]:
    519                 log.general.Log('Handshake Failed - Insecure Boot Version Mismatch (common.ini:version) - Server: %s - Client: %s' % (response[3], boot.version), log.LGERR)
    520                 self.Close(localization.GetByLabel('/Carbon/GPS/IncompatibleVersion'), 'HANDSHAKE_INCOMPATIBLEVERSION')
    521                 raise GPSTransportClosed(localization.GetByLabel('/Carbon/GPS/IncompatibleVersion'), 'HANDSHAKE_INCOMPATIBLEVERSION', machoVersion=response[1], version=response[3], build=response[4], codename=insecresp['boot_codename'], region=insecresp['boot_region'], loggedOnUserCount=response[2])
    522             if macho.version != response[1]:
    523                 log.general.Log('Handshake Failed - Insecure Macho Version Mismatch - Server: %s - Client: %s' % (response[1], macho.version), log.LGERR)
    524                 self.Close(localization.GetByLabel('/Carbon/GPS/IncompatibleProtocol'), 'HANDSHAKE_INCOMPATIBLEPROTOCOL')
    525                 raise GPSTransportClosed(localization.GetByLabel('/Carbon/GPS/IncompatibleProtocol'), 'HANDSHAKE_INCOMPATIBLEPROTOCOL', machoVersion=response[1], version=response[3], build=response[4], codename=insecresp['boot_codename'], region=insecresp['boot_region'], loggedOnUserCount=response[2])
    526             if boot.build < response[4]:
    527                 log.general.Log('Handshake Failed - Insecure Boot Build Mismatch (common.ini:build) - Server: %s - Client: %s' % (response[4], boot.build), log.LGERR)
    528                 self.Close(localization.GetByLabel('/Carbon/GPS/IncompatibleBuild'), 'HANDSHAKE_INCOMPATIBLEBUILD')
    529                 raise GPSTransportClosed(localization.GetByLabel('/Carbon/GPS/IncompatibleBuild'), 'HANDSHAKE_INCOMPATIBLEBUILD', machoVersion=response[1], version=response[3], build=response[4], codename=insecresp['boot_codename'], region=insecresp['boot_region'], loggedOnUserCount=response[2])
    530             request = (GPSTransport.__HANDSHAKE_SECRET_KEY,
    531              macho.version,
    532              0,
    533              boot.version,
    534              boot.build,
    535              str(boot.codename) + '@' + str(boot.region))
    536             self.UnEncryptedWrite(macho.Dumps(request))
    537             if username:
    538                 self.UnEncryptedWrite(macho.Dumps((None, 'VK', Crypto.CryptoHash(CaseFold(username)))))
    539             if username is None:
    540                 self.UnEncryptedWrite(macho.Dumps((None, 'QC')))
    541                 message = (localization.GetByLabel('/Carbon/GPS/ConnectionTimeoutNoCompatibilityHandshake'), 'HANDSHAKE_TIMEOUT_FAILEDSERVERINITIATECOMPATIBILITYHANDSHAKE')
    542                 logonQueuePosition = macho.Loads(self.ApplyWithTimeout(self.UnEncryptedRead, (), message=message))
    543                 sm.GetService('machoNet').SetLogonQueuePosition(logonQueuePosition)
    544                 return insecresp
    545             log.general.Log('LLV Initializing Crypto Context', log.LGINFO)
    546             request = self.cryptoContext.Initialize()
    547             if type(request) != types.DictType:
    548                 log.general.Log('LLV Crypto Init Context failure: ' + request, log.LGERR)
    549                 self.Close('Crypto Initialization Failure')
    550                 raise GPSTransportClosed(localization.GetByLabel('/Carbon/GPS/IncompatibleBuild'), 'HANDSHAKE_INCOMPATIBLEBUILD', loggedOnUserCount=response[2])
    551             log.general.Log('LLV Sending Encrypted Session Key', log.LGINFO)
    552             self.UnEncryptedWrite(macho.Dumps((getattr(macho, 'publicKeyVersion', 'placebo'), request)))
    553             message = (localization.GetByLabel('/Carbon/GPS/ConnectionTimeoutClientNotCompatible'), 'HANDSHAKE_TIMEOUT_CLIENTCOMPATIBILITYHANDSHAKE')
    554             macho.Loads(self.ApplyWithTimeout(self.UnEncryptedRead, (), message=message))
    555             log.general.Log('LLV Generating Secure Client Handshake', log.LGINFO)
    556             affiliateID = 0
    557             dict = {'macho_version': macho.version,
    558              'boot_version': boot.version,
    559              'boot_build': boot.build,
    560              'boot_codename': str(boot.codename),
    561              'boot_region': str(boot.region),
    562              'user_name': username,
    563              'user_password': None,
    564              'user_password_hash': macho.PasswordHash(username, password),
    565              'user_languageid': prefs.GetValue('languageID', 'EN'),
    566              'user_affiliateid': affiliateID,
    567              'user_sso_token': token}
    568             clientChallenge = Crypto.GetRandomBytes(self.handShakePaddingLength)
    569             log.general.Log('LLV Writing Secure Client Handshake', log.LGINFO)
    570             self.EncryptedWrite(macho.Dumps((clientChallenge, dict)))
    571             log.general.Log('LLV Reading password version', log.LGINFO)
    572             message = (localization.GetByLabel('/Carbon/GPS/ConnectionTimeoutServerTimeout'), 'HANDSHAKE_TIMEOUT_SERVERSECUREHANDSHAKE')
    573             passwordVersion = macho.Loads(self.ApplyWithTimeout(self.EncryptedRead, (), message=message))
    574             if passwordVersion == 1:
    575                 dict['user_password'] = password
    576                 dict['user_password_hash'] = None
    577                 log.general.Log('LLV Writing Secure Client Handshake (Attempt 2)', log.LGINFO)
    578                 self.EncryptedWrite(macho.Dumps((clientChallenge, dict)))
    579             log.general.Log('LLV Reading Crypted Server Handshake', log.LGINFO)
    580             message = (localization.GetByLabel('/Carbon/GPS/ConnectionTimeoutServerTimeout'), 'HANDSHAKE_TIMEOUT_SERVERSECUREHANDSHAKE')
    581             serverChallenge, signedFunc, context, response = macho.Loads(self.ApplyWithTimeout(self.EncryptedRead, (), message=message))
    582             log.general.Log('LLV Verifying Response Hash', log.LGINFO)
    583             if response['challenge_responsehash'] != Crypto.CryptoHash(clientChallenge):
    584                 self.Close("Server response signature incorrect, the server's crypto hash wasn't correct")
    585                 raise GPSTransportClosed("Server response signature incorrect, the server's crypto hash wasn't correct", loggedOnUserCount=response[2])
    586             if response.get('user_logonqueueposition', 0) >= 2:
    587                 sm.GetService('machoNet').SetLogonQueuePosition(response['user_logonqueueposition'])
    588                 raise UserError('AutLogonFailureTotalUsers', {'position': response['user_logonqueueposition']})
    589             outputBuffer, funcResult = self.__Execute(signedFunc, context)
    590             log.general.Log('LLV Writing Secure Challenge-Response', log.LGINFO)
    591             self.EncryptedWrite(macho.Dumps((Crypto.CryptoHash(serverChallenge), outputBuffer, funcResult)))
    592             log.general.Log('LLV Reading Ack to Challenge-Response', log.LGINFO)
    593             message = (localization.GetByLabel('/Carbon/GPS/ConnectionTimeoutChallengeFailure'), 'HANDSHAKE_TIMEOUT_SERVERRESPONSETOCLIENTCHALLENGE')
    594             crAck = macho.Loads(self.ApplyWithTimeout(self.EncryptedRead, (), message=message))
    595             if not crAck:
    596                 self.Close("Server didn't ACK our Challenge-Response")
    597                 raise GPSTransportClosed(localization.GetByLabel('/Carbon/GPS/ChallengeResponseNotAcknowledged'), loggedOnUserCount=response[2])
    598             response.update(crAck)
    599             if 'live_updates' in response:
    600                 live_updates = response['live_updates']
    601                 del response['live_updates']
    602                 for theUpdate in live_updates:
    603                     sm.ScatterEvent('OnLiveClientUpdate', theUpdate.code)
    604 
    605             log.general.Log('LLV Succeeded', log.LGINFO)
    606             self.handShake = response
    607             return response
    608         finally:
    609             Leave(timer)
    610 
    611     def __Execute(self, signedFunc, context):
    612         marshaled, verified = Crypto.Verify(signedFunc)
    613         if not verified:
    614             raise RuntimeError('Failed to verify initial function blobs')
    615         func = marshal.loads(marshaled)
    616         output = WriteBuffer()
    617         temp = sys.stdout
    618         temp2 = sys.stderr
    619         sys.stdout = output
    620         sys.stderr = output
    621         try:
    622             if macho.mode != 'client':
    623                 raise RuntimeError('H4x0r won by calling GPS::__Execute on the server :(')
    624             funcResult = eval(func, globals(), context)
    625         except:
    626             funcResult = {}
    627             import traceback
    628             exctype, exc, tb = sys.exc_info()
    629             try:
    630                 traceback.print_exception(exctype, exc, tb)
    631             finally:
    632                 exctype = None
    633                 exc = None
    634                 tb = None
    635 
    636             sys.exc_clear()
    637         finally:
    638             sys.stdout = temp
    639             sys.stderr = temp2
    640 
    641         return (output.buffer, funcResult)
    642 
    643     def EncryptedRead(self):
    644         cryptedPacket = self.UnEncryptedRead()
    645         return self.cryptoContext.SymmetricDecryption(cryptedPacket)
    646 
    647     def EncryptedWrite(self, packet, header = None):
    648         encryptedPacket = self.cryptoContext.SymmetricEncryption(packet)
    649         return self.UnEncryptedWrite(encryptedPacket, header)
    650 
    651     def CreateClosedPacket(self, reason, reasonCode = None, reasonArgs = {}, exception = None):
    652         msg = 'Creating Closed Packet: ' + reason
    653         if exception:
    654             msg += ' exception:' + repr(exception)
    655         log.general.Log(msg, log.LGINFO)
    656         etype = GPSRemoteTransportClosed
    657         etype = GPSTransportClosed
    658         exception = None
    659         packet = macho.Dumps(etype(reason, reasonCode, reasonArgs, exception=exception))
    660         return self.cryptoContext.OptionalSymmetricEncryption(packet)