def createKmsRequestBase(): requestDict = kmsBase.kmsRequestStruct() requestDict['versionMinor'] = clt_config['KMSProtocolMinorVersion'] requestDict['versionMajor'] = clt_config['KMSProtocolMajorVersion'] requestDict['isClientVm'] = 0 requestDict['licenseStatus'] = clt_config['KMSClientLicenseStatus'] requestDict['graceTime'] = 43200 requestDict['applicationId'] = UUID( uuid.UUID(clt_config['KMSClientAppID']).bytes_le) requestDict['skuId'] = UUID( uuid.UUID(clt_config['KMSClientSkuID']).bytes_le) requestDict['kmsCountedId'] = UUID( uuid.UUID(clt_config['KMSClientKMSCountedID']).bytes_le) requestDict['clientMachineId'] = UUID( uuid.UUID(clt_config['cmid']).bytes_le if ( clt_config['cmid'] is not None) else uuid.uuid4().bytes_le) requestDict[ 'previousClientMachineId'] = '\0' * 16 # I'm pretty sure this is supposed to be a null UUID. requestDict['requiredClientCount'] = clt_config['RequiredClientCount'] requestDict['requestTime'] = dt_to_filetime(datetime.datetime.utcnow()) requestDict['machineName'] = (clt_config['machine'] if ( clt_config['machine'] is not None) else ''.join( random.choice(string.ascii_letters + string.digits) for i in range(random.randint(2, 63)))).encode('utf-16le') requestDict['mnPad'] = '\0'.encode('utf-16le') * ( 63 - len(requestDict['machineName'].decode('utf-16le'))) # Debug Stuff pretty_printer(num_text=9, where="clt") requestDict = byterize(requestDict) loggerclt.debug("Request Base Dictionary: \n%s\n" % justify(requestDict.dump(print_to_stdout=False))) return requestDict
def sql_update_epid(dbName, kmsRequest, response): cmid = str(kmsRequest['clientMachineId'].get()) con = None try: con = sqlite3.connect(dbName) cur = con.cursor() cur.execute("SELECT * FROM clients WHERE clientMachineId=?;", [cmid]) try: data = cur.fetchone() if data[6]: response["kmsEpid"] = data[6].encode('utf-16le') else: cur.execute( "UPDATE clients SET kmsEpid=? WHERE clientMachineId=?;", (str(response["kmsEpid"].decode('utf-16le')), cmid)) except sqlite3.Error as e: pretty_printer(log_obj=loggersrv.error, to_exit=True, put_text="{reverse}{red}{bold}%s. Exiting...{end}" % str(e)) except sqlite3.Error as e: pretty_printer(log_obj=loggersrv.error, to_exit=True, put_text="{reverse}{red}{bold}%s. Exiting...{end}" % str(e)) finally: if con: con.commit() con.close() return response
def client_connect(): loggerclt.info("Connecting to %s on port %d" % (clt_config['ip'], clt_config['port'])) try: clt_sock = socket.create_connection( (clt_config['ip'], clt_config['port']), timeout=clt_config['timeoutidle']) loggerclt.info("Connection successful !") clt_sock.settimeout(clt_config['timeoutsndrcv']) except socket.timeout: pretty_printer( log_obj=loggerclt.error, to_exit=True, where="clt", put_text= "{reverse}{red}{bold}Client connection timed out. Exiting...{end}") except (socket.gaierror, socket.error) as e: pretty_printer( log_obj=loggerclt.error, to_exit=True, where="clt", put_text= "{reverse}{red}{bold}Connection failed '%s:%d': %s. Exiting...{end}" % (clt_config['ip'], clt_config['port'], str(e))) return clt_sock
def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True): socketserver.BaseServer.__init__(self, server_address, RequestHandlerClass) self.__shutdown_request = False self.r_service, self.w_service = socket.socketpair() if hasattr(selectors, 'PollSelector'): self._ServerSelector = selectors.PollSelector else: self._ServerSelector = selectors.SelectSelector try: ip_ver = ipaddress.ip_address(server_address[0]) except ValueError as e: pretty_printer(log_obj=loggersrv.error, to_exit=True, put_text="{reverse}{red}{bold}%s. Exiting...{end}" % str(e)) if ip_ver.version == 4: self.address_family = socket.AF_INET elif ip_ver.version == 6: self.address_family = socket.AF_INET6 self.socket = socket.socket(self.address_family, self.socket_type) if bind_and_activate: try: self.server_bind() self.server_activate() except: self.server_close() raise
def generateRequest(self, requestBase): esalt = self.getRandomSalt() moo = aes.AESModeOfOperation() moo.aes.v6 = self.v6 dsalt = moo.decrypt(esalt, 16, moo.ModeOfOperation["CBC"], self.key, moo.aes.KeySize["SIZE_128"], esalt) dsalt = bytearray(dsalt) decrypted = self.DecryptedRequest() decrypted['salt'] = bytes(dsalt) decrypted['request'] = requestBase padded = aes.append_PKCS7_padding(enco(str(decrypted), 'latin-1')) mode, orig_len, crypted = moo.encrypt(padded, moo.ModeOfOperation["CBC"], self.key, moo.aes.KeySize["SIZE_128"], esalt) message = self.RequestV5.Message(bytes(bytearray(crypted))) request = self.RequestV5() bodyLength = 2 + 2 + len(message) request['bodyLength1'] = bodyLength request['bodyLength2'] = bodyLength request['versionMinor'] = requestBase['versionMinor'] request['versionMajor'] = requestBase['versionMajor'] request['message'] = message pretty_printer(num_text = 10, where = "clt") request = byterize(request) loggersrv.info("Request V%d Data: \n%s\n" % (self.ver, justify(request.dump(print_to_stdout = False)))) loggersrv.info("Request V%d: \n%s\n" % (self.ver, justify(deco(binascii.b2a_hex(enco(str(request), 'latin-1')), 'utf-8')))) return request
def server_daemon(): if 'etrigan' in srv_config.values(): path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'pykms_config.pickle') if srv_config['operation'] in ['stop', 'restart', 'status'] and len(sys.argv[1:]) > 2: pretty_printer(put_text = "{reverse}{red}{bold}too much arguments. Exiting...{end}", to_exit = True) if srv_config['gui']: pass else: if srv_config['operation'] == 'start': with open(path, 'wb') as file: pickle.dump(srv_config, file, protocol = pickle.HIGHEST_PROTOCOL) elif srv_config['operation'] in ['stop', 'status', 'restart']: with open(path, 'rb') as file: old_srv_config = pickle.load(file) old_srv_config = {x: old_srv_config[x] for x in old_srv_config if x not in ['operation']} srv_config.update(old_srv_config) serverdaemon = Etrigan(srv_config['etriganpid'], logfile = srv_config['etriganlog'], loglevel = srv_config['etriganlev'], mute = srv_config['etriganmute'], pause_loop = None) if srv_config['operation'] == 'start': serverdaemon.want_quit = True if srv_config['gui']: serverdaemon.funcs_to_daemonize = [server_with_gui] else: server_without_gui = ServerWithoutGui() serverdaemon.funcs_to_daemonize = [server_without_gui.start, server_without_gui.join] indx_for_clean = lambda: (0, ) serverdaemon.quit_on_stop = [indx_for_clean, server_without_gui.clean] Etrigan_job(srv_config['operation'], serverdaemon)
def sql_update(dbName, infoDict): con = None try: con = sqlite3.connect(dbName) cur = con.cursor() cur.execute( "SELECT * FROM clients WHERE clientMachineId=:clientMachineId AND applicationId=:appId;", infoDict) try: data = cur.fetchone() if not data: # Insert row. cur.execute( "INSERT INTO clients (clientMachineId, machineName, applicationId, \ skuId, licenseStatus, lastRequestTime, requestCount) VALUES (:clientMachineId, :machineName, :appId, :skuId, :licenseStatus, :requestTime, 1);", infoDict) else: # Update data. if data[1] != infoDict["machineName"]: cur.execute( "UPDATE clients SET machineName=:machineName WHERE \ clientMachineId=:clientMachineId AND applicationId=:appId;", infoDict) if data[2] != infoDict["appId"]: cur.execute( "UPDATE clients SET applicationId=:appId WHERE \ clientMachineId=:clientMachineId AND applicationId=:appId;", infoDict) if data[3] != infoDict["skuId"]: cur.execute( "UPDATE clients SET skuId=:skuId WHERE \ clientMachineId=:clientMachineId AND applicationId=:appId;", infoDict) if data[4] != infoDict["licenseStatus"]: cur.execute( "UPDATE clients SET licenseStatus=:licenseStatus WHERE \ clientMachineId=:clientMachineId AND applicationId=:appId;", infoDict) if data[5] != infoDict["requestTime"]: cur.execute( "UPDATE clients SET lastRequestTime=:requestTime WHERE \ clientMachineId=:clientMachineId AND applicationId=:appId;", infoDict) # Increment requestCount cur.execute( "UPDATE clients SET requestCount=requestCount+1 WHERE \ clientMachineId=:clientMachineId AND applicationId=:appId;", infoDict) except sqlite3.Error as e: pretty_printer( log_obj=loggersrv.error, to_exit=True, put_text="{reverse}{red}{bold}Sqlite Error: %s. Exiting...{end}" % str(e)) except sqlite3.Error as e: pretty_printer( log_obj=loggersrv.error, to_exit=True, put_text="{reverse}{red}{bold}Sqlite Error: %s. Exiting...{end}" % str(e)) finally: if con: con.commit() con.close()
def parseRequest(self): request = MSRPCRequestHeader(self.data) pretty_printer(num_text=14, where="srv") request = byterize(request) loggersrv.debug("RPC Message Request Bytes: \n%s\n" % justify(binascii.b2a_hex(self.data).decode('utf-8'))) loggersrv.debug("RPC Message Request: \n%s\n" % justify(request.dump(print_to_stdout=False))) return request
def server_create(): try: server = KeyServer((srv_config['ip'], srv_config['port']), kmsServerHandler) except (socket.gaierror, socket.error) as e: pretty_printer(log_obj = loggersrv.error, to_exit = True, put_text = "{reverse}{red}{bold}Connection failed '%s:%d': %s. Exiting...{end}" %(srv_config['ip'], srv_config['port'], str(e))) server.timeout = srv_config['timeoutidle'] loggersrv.info("TCP server listening at %s on port %d." % (srv_config['ip'], srv_config['port'])) loggersrv.info("HWID: %s" % deco(binascii.b2a_hex(srv_config['hwid']), 'utf-8').upper()) return server
def __init__(self, server_address, RequestHandlerClass, bind_and_activate = True, want_dual = False): socketserver.BaseServer.__init__(self, server_address, RequestHandlerClass) self.__shutdown_request = False self.r_service, self.w_service = socket.socketpair() if hasattr(selectors, 'PollSelector'): self._ServerSelector = selectors.PollSelector else: self._ServerSelector = selectors.SelectSelector if bind_and_activate: try: self.multisock = MultipleListener(server_address, want_dual = want_dual) except Exception as e: if want_dual and str(e) == "dualstack_ipv6 not supported on this platform": try: pretty_printer(log_obj = loggersrv.warning, put_text = "{reverse}{yellow}{bold}%s. Creating not dualstack sockets...{end}" %str(e)) self.multisock = MultipleListener(server_address, want_dual = False) except Exception as e: pretty_printer(log_obj = loggersrv.error, to_exit = True, put_text = "{reverse}{red}{bold}%s. Exiting...{end}" %str(e)) else: pretty_printer(log_obj = loggersrv.error, to_exit = True, put_text = "{reverse}{red}{bold}%s. Exiting...{end}" %str(e)) if self.multisock.cant_dual: delim = ('' if len(self.multisock.cant_dual) == 1 else ', ') pretty_printer(log_obj = loggersrv.warning, put_text = "{reverse}{yellow}{bold}IPv4 [%s] can't be dualstack{end}" %delim.join(self.multisock.cant_dual))
def client_check(): # Setup and some checks. check_setup(clt_config, clt_options, loggerclt, where = "clt") # Check cmid. if clt_config['cmid'] is not None: try: uuid.UUID(clt_config['cmid']) except ValueError: pretty_printer(log_obj = loggerclt.error, to_exit = True, where = "clt", put_text = "{reverse}{red}{bold}argument `-c/--cmid`: invalid with: '%s'. Exiting...{end}" %clt_config['cmid']) # Check machine name. if clt_config['machine'] is not None: try: clt_config['machine'].encode('utf-16le') if len(clt_config['machine']) < 2: pretty_printer(log_obj = loggerclt.error, to_exit = True, where = "clt", put_text = "{reverse}{red}{bold}argument `-n/--name`: too short (required 2 - 63 chars). Exiting...{end}") elif len(clt_config['machine']) > 63: pretty_printer(log_obj = loggerclt.error, to_exit = True, where = "clt", put_text = "{reverse}{red}{bold}argument `-n/--name`: too long (required 2 - 63 chars). Exiting...{end}") except UnicodeEncodeError: pretty_printer(log_obj = loggerclt.error, to_exit = True, where = "clt", put_text = "{reverse}{red}{bold}argument `-n/--name`: invalid with: '%s'. Exiting...{end}" %clt_config['machine']) clt_config['call_id'] = 1 # Check other specific client options. opts = [('timeoutidle', '-t0/--timeout-idle'), ('timeoutsndrcv', '-t1/--timeout-sndrcv')] check_other(clt_config, opts, loggerclt, where = 'clt')
def generateResponse(self, responseBuffer, thehash): response = self.ResponseV4() bodyLength = len(responseBuffer) + len(thehash) response['bodyLength1'] = bodyLength response['bodyLength2'] = bodyLength response['response'] = responseBuffer response['hash'] = thehash response['padding'] = bytes(bytearray(self.getPadding(bodyLength))) ## Debug stuff. pretty_printer(num_text = 16, where = "srv") response = byterize(response) loggersrv.debug("KMS V4 Response: \n%s\n" % justify(response.dump(print_to_stdout = False))) loggersrv.debug("KMS V4 Response Bytes: \n%s\n" % justify(deco(binascii.b2a_hex(enco(str(response), 'latin-1')), 'utf-8'))) return str(response)
def client_options(): client_parser = KmsParser(description = clt_description, epilog = 'version: ' + clt_version, add_help = False) client_parser.add_argument("ip", nargs = "?", action = "store", default = clt_options['ip']['def'], help = clt_options['ip']['help'], type = str) client_parser.add_argument("port", nargs = "?", action = "store", default = clt_options['port']['def'], help = clt_options['port']['help'], type = int) client_parser.add_argument("-m", "--mode", dest = clt_options['mode']['des'], default = clt_options['mode']['def'], choices = clt_options['mode']['choi'], help = clt_options['mode']['help'], type = str) client_parser.add_argument("-c", "--cmid", dest = clt_options['cmid']['des'], default = clt_options['cmid']['def'], help = clt_options['cmid']['help'], type = str) client_parser.add_argument("-n", "--name", dest = clt_options['name']['des'] , default = clt_options['name']['def'], help = clt_options['name']['help'], type = str) client_parser.add_argument("-t0", "--timeout-idle", action = "store", dest = clt_options['time0']['des'], default = clt_options['time0']['def'], help = clt_options['time0']['help'], type = str) client_parser.add_argument("-t1", "--timeout-sndrcv", action = "store", dest = clt_options['time1']['des'], default = clt_options['time1']['def'], help = clt_options['time1']['help'], type = str) client_parser.add_argument("-y", "--async-msg", action = "store_true", dest = clt_options['asyncmsg']['des'], default = clt_options['asyncmsg']['def'], help = clt_options['asyncmsg']['help']) client_parser.add_argument("-V", "--loglevel", dest = clt_options['llevel']['des'], action = "store", choices = clt_options['llevel']['choi'], default = clt_options['llevel']['def'], help = clt_options['llevel']['help'], type = str) client_parser.add_argument("-F", "--logfile", nargs = "+", action = "store", dest = clt_options['lfile']['des'], default = clt_options['lfile']['def'], help = clt_options['lfile']['help'], type = str) client_parser.add_argument("-S", "--logsize", dest = clt_options['lsize']['des'], action = "store", default = clt_options['lsize']['def'], help = clt_options['lsize']['help'], type = float) client_parser.add_argument("-D", "--discovery", dest = clt_options['discovery']['des'], action = "store", default = clt_options['discovery']['def'], help = clt_options['discovery']['help'], type = str) client_parser.add_argument("-h", "--help", action = "help", help = "show this help message and exit") try: userarg = sys.argv[1:] # Run help. if any(arg in ["-h", "--help"] for arg in userarg): KmsParserHelp().printer(parsers = [client_parser]) # Get stored arguments. pykmsclt_zeroarg, pykmsclt_onearg = kms_parser_get(client_parser) # Update pykms options for dict client config. kms_parser_check_optionals(userarg, pykmsclt_zeroarg, pykmsclt_onearg, msg = 'optional py-kms client', exclude_opt_len = ['-F', '--logfile']) kms_parser_check_positionals(clt_config, client_parser.parse_args, msg = 'positional py-kms client') except KmsParserException as e: pretty_printer(put_text = "{reverse}{red}{bold}%s. Exiting...{end}" %str(e), to_exit = True, where = "clt")
def generateResponse(self, iv, encryptedResponse, requestData): response = self.ResponseV5() bodyLength = 2 + 2 + len(iv) + len(encryptedResponse) response['bodyLength1'] = bodyLength response['bodyLength2'] = bodyLength response['versionMinor'] = requestData['versionMinor'] response['versionMajor'] = requestData['versionMajor'] response['salt'] = iv response['encrypted'] = bytes(bytearray(encryptedResponse)) response['padding'] = bytes(bytearray(self.getPadding(bodyLength))) pretty_printer(num_text = 16, where = "srv") response = byterize(response) loggersrv.info("KMS V%d Response: \n%s\n" % (self.ver, justify(response.dump(print_to_stdout = False)))) loggersrv.info("KMS V%d Structure Bytes: \n%s\n" % (self.ver, justify(deco(binascii.b2a_hex(enco(str(response), 'latin-1')), 'utf-8')))) return str(response)
def sql_initialize(dbName): if not os.path.isfile(dbName): # Initialize the database. loggersrv.debug(f'Initializing database file "{dbName}"...') con = None try: con = sqlite3.connect(dbName) cur = con.cursor() cur.execute("CREATE TABLE clients(clientMachineId TEXT, machineName TEXT, applicationId TEXT, skuId TEXT, \ licenseStatus TEXT, lastRequestTime INTEGER, kmsEpid TEXT, requestCount INTEGER)") except sqlite3.Error as e: pretty_printer(log_obj = loggersrv.error, to_exit = True, put_text = "{reverse}{red}{bold}Sqlite Error: %s. Exiting...{end}" %str(e)) finally: if con: con.commit() con.close()
def generateRequest(self, requestBase): thehash = self.generateHash(bytearray(enco(str(requestBase), 'latin-1'))) request = kmsRequestV4.RequestV4() bodyLength = len(requestBase) + len(thehash) request['bodyLength1'] = bodyLength request['bodyLength2'] = bodyLength request['request'] = requestBase request['hash'] = thehash request['padding'] = bytes(bytearray(self.getPadding(bodyLength))) ## Debug stuff. pretty_printer(num_text = 10, where = "clt") request = byterize(request) loggersrv.debug("Request V4 Data: \n%s\n" % justify(request.dump(print_to_stdout = False))) loggersrv.debug("Request V4: \n%s\n" % justify(deco(binascii.b2a_hex(enco(str(request), 'latin-1')), 'utf-8'))) return request
def client_connect(): if clt_config['discovery'] is not None: loggerclt.info(f'Using Domain: {clt_config["discovery"]}') r= None try: r = dns.resolver.resolve('_vlmcs._tcp.' + clt_config['discovery'], dns.rdatatype.SRV) for a in r: loggerclt.debug(f'answer KMS server: {a.target} , port: {a.port}') clt_config['ip'] = socket.gethostbyname(r[0].target.to_text()) clt_config['port'] = r[0].port except (dns.exception.Timeout, dns.resolver.NXDOMAIN) as e: pretty_printer(log_obj = loggerclt.warning, put_text = "{reverse}{red}{bold}Cannot resolve '%s'. Error: '%s'...{end}" %(clt_config['discovery'], str(e))) loggerclt.info("Connecting to %s on port %d" % (clt_config['ip'], clt_config['port'])) try: clt_sock = socket.create_connection((clt_config['ip'], clt_config['port']), timeout = clt_config['timeoutidle']) loggerclt.info("Connection successful !") clt_sock.settimeout(clt_config['timeoutsndrcv']) except socket.timeout: pretty_printer(log_obj = loggerclt.error, to_exit = True, where = "clt", put_text = "{reverse}{red}{bold}Client connection timed out. Exiting...{end}") except (socket.gaierror, socket.error) as e: pretty_printer(log_obj = loggerclt.error, to_exit = True, where = "clt", put_text = "{reverse}{red}{bold}Connection failed '%s:%d': %s. Exiting...{end}" %(clt_config['ip'], clt_config['port'], str(e))) return clt_sock
def client_check(): # Check logfile. clt_config['logfile'] = check_logfile(clt_config['logfile'], clt_options['lfile']['def'], where="clt") # Setup hidden or not messages. ShellMessage.view = (False if any( i in ['STDOUT', 'FILESTDOUT'] for i in clt_config['logfile']) else True) # Create log. logger_create(loggerclt, clt_config, mode='a') # Check cmid. if clt_config['cmid'] is not None: try: uuid.UUID(clt_config['cmid']) except ValueError: pretty_printer( log_obj=loggerclt.error, to_exit=True, where="clt", put_text="{reverse}{red}{bold}Bad CMID. Exiting...{end}") # Check machineName. if clt_config['machineName'] is not None: if len(clt_config['machineName']) < 2 or len( clt_config['machineName']) > 63: pretty_printer( log_obj=loggerclt.error, to_exit=True, where="clt", put_text= "{reverse}{red}{bold}machineName must be between 2 and 63 characters in length. Exiting...{end}" ) clt_config['call_id'] = 1
def server_check(): # Setup and some checks. check_setup(srv_config, srv_options, loggersrv, where="srv") # Random HWID. if srv_config['hwid'] == "RANDOM": randomhwid = uuid.uuid4().hex srv_config['hwid'] = randomhwid[:16] # Sanitize HWID. hexstr = srv_config['hwid'] # Strip 0x from the start of hexstr if hexstr.startswith("0x"): hexstr = hexstr[2:] hexsub = re.sub(r'[^0-9a-fA-F]', '', hexstr) diff = set(hexstr).symmetric_difference(set(hexsub)) if len(diff) != 0: diff = str(diff).replace('{', '').replace('}', '') pretty_printer( log_obj=loggersrv.error, to_exit=True, put_text= "{reverse}{red}{bold}HWID '%s' is invalid. Digit %s non hexadecimal. Exiting...{end}" % (hexstr.upper(), diff)) else: lh = len(hexsub) if lh % 2 != 0: pretty_printer( log_obj=loggersrv.error, to_exit=True, put_text= "{reverse}{red}{bold}HWID '%s' is invalid. Hex string is odd length. Exiting...{end}" % hexsub.upper()) elif lh < 16: pretty_printer( log_obj=loggersrv.error, to_exit=True, put_text= "{reverse}{red}{bold}HWID '%s' is invalid. Hex string is too short. Exiting...{end}" % hexsub.upper()) elif lh > 16: pretty_printer( log_obj=loggersrv.error, to_exit=True, put_text= "{reverse}{red}{bold}HWID '%s' is invalid. Hex string is too long. Exiting...{end}" % hexsub.upper()) else: srv_config['hwid'] = binascii.a2b_hex(hexsub) # Check LCID. srv_config['lcid'] = check_lcid(srv_config['lcid'], loggersrv.warning) # Check sqlite. if srv_config['sqlite']: if isinstance(srv_config['sqlite'], str): check_dir(srv_config['sqlite'], 'srv', log_obj=loggersrv.error, argument='-s/--sqlite', typefile='.db') elif srv_config['sqlite'] is True: srv_config['sqlite'] = srv_options['sql']['file'] try: import sqlite3 except ImportError: pretty_printer( log_obj=loggersrv.warning, put_text= "{reverse}{yellow}{bold}Module 'sqlite3' not installed, database support disabled.{end}" ) srv_config['sqlite'] = False # Check other specific server options. opts = [('clientcount', '-c/--client-count'), ('timeoutidle', '-t0/--timeout-idle'), ('timeoutsndrcv', '-t1/--timeout-sndrcv')] if serverthread.with_gui: opts += [('activation', '-a/--activation-interval'), ('renewal', '-r/--renewal-interval')] check_other(srv_config, opts, loggersrv, where='srv') # Check further addresses / ports. if 'listen' in srv_config: addresses = [] for elem in srv_config['listen']: try: addr, port = elem.split(',') except ValueError: pretty_printer( log_obj=loggersrv.error, to_exit=True, put_text= "{reverse}{red}{bold}argument `-n/--listen`: %s not well defined. Exiting...{end}" % elem) try: port = int(port) except ValueError: pretty_printer( log_obj=loggersrv.error, to_exit=True, put_text= "{reverse}{red}{bold}argument `-n/--listen`: port number '%s' is invalid. Exiting...{end}" % port) if not (1 <= port <= 65535): pretty_printer( log_obj=loggersrv.error, to_exit=True, put_text= "{reverse}{red}{bold}argument `-n/--listen`: port number '%s' is invalid. Enter between 1 - 65535. Exiting...{end}" % port) addresses.append((addr, port)) srv_config['listen'] = addresses
def handle_timeout(self): pretty_printer(log_obj = loggersrv.error, to_exit = True, put_text = "{reverse}{red}{bold}Server connection timed out. Exiting...{end}")
def handle(self): while True: # self.request is the TCP socket connected to the client try: self.data = self.request.recv(1024) if self.data == '' or not self.data: pretty_printer(log_obj = loggersrv.warning, put_text = "{reverse}{yellow}{bold}No data received.{end}") break except socket.error as e: pretty_printer(log_obj = loggersrv.error, put_text = "{reverse}{red}{bold}While receiving: %s{end}" %str(e)) break packetType = MSRPCHeader(self.data)['type'] if packetType == rpcBase.packetType['bindReq']: loggersrv.info("RPC bind request received.") pretty_printer(num_text = [-2, 2], where = "srv") handler = pykms_RpcBind.handler(self.data, srv_config) elif packetType == rpcBase.packetType['request']: loggersrv.info("Received activation request.") pretty_printer(num_text = [-2, 13], where = "srv") handler = pykms_RpcRequest.handler(self.data, srv_config) else: pretty_printer(log_obj = loggersrv.error, put_text = "{reverse}{red}{bold}Invalid RPC request type %s.{end}" %packetType) break res = enco(str(handler.populate()), 'latin-1') if packetType == rpcBase.packetType['bindReq']: loggersrv.info("RPC bind acknowledged.") pretty_printer(num_text = [-3, 5, 6], where = "srv") elif packetType == rpcBase.packetType['request']: loggersrv.info("Responded to activation request.") pretty_printer(num_text = [-3, 18, 19], where = "srv") try: self.request.send(res) if packetType == rpcBase.packetType['request']: break except socket.error as e: pretty_printer(log_obj = loggersrv.error, put_text = "{reverse}{red}{bold}While sending: %s{end}" %str(e)) break
def server_check(): # Setup and some checks. check_setup(srv_config, srv_options, loggersrv, where = "srv") # Random HWID. if srv_config['hwid'] == "RANDOM": randomhwid = uuid.uuid4().hex srv_config['hwid'] = randomhwid[:16] # Sanitize HWID. hexstr = srv_config['hwid'] # Strip 0x from the start of hexstr if hexstr.startswith("0x"): hexstr = hexstr[2:] hexsub = re.sub(r'[^0-9a-fA-F]', '', hexstr) diff = set(hexstr).symmetric_difference(set(hexsub)) if len(diff) != 0: diff = str(diff).replace('{', '').replace('}', '') pretty_printer(log_obj = loggersrv.error, to_exit = True, put_text = "{reverse}{red}{bold}HWID '%s' is invalid. Digit %s non hexadecimal. Exiting...{end}" %(hexstr.upper(), diff)) else: lh = len(hexsub) if lh % 2 != 0: pretty_printer(log_obj = loggersrv.error, to_exit = True, put_text = "{reverse}{red}{bold}HWID '%s' is invalid. Hex string is odd length. Exiting...{end}" %hexsub.upper()) elif lh < 16: pretty_printer(log_obj = loggersrv.error, to_exit = True, put_text = "{reverse}{red}{bold}HWID '%s' is invalid. Hex string is too short. Exiting...{end}" %hexsub.upper()) elif lh > 16: pretty_printer(log_obj = loggersrv.error, to_exit = True, put_text = "{reverse}{red}{bold}HWID '%s' is invalid. Hex string is too long. Exiting...{end}" %hexsub.upper()) else: srv_config['hwid'] = binascii.a2b_hex(hexsub) # Check LCID. srv_config['lcid'] = check_lcid(srv_config['lcid'], loggersrv.warning) # Check sqlite. try: import sqlite3 except: pretty_printer(log_obj = loggersrv.warning, put_text = "{reverse}{yellow}{bold}Module 'sqlite3' is not installed, database support disabled.{end}") srv_config['dbSupport'] = False else: srv_config['dbSupport'] = True # Check other specific server options. list_dest = ['clientcount', 'timeoutidle'] list_opt = ['-c/--client-count', '-t0/--timeout-idle'] if serverthread.with_gui: list_dest += ['activation', 'renewal'] list_opt += ['-a/--activation-interval', '-r/--renewal-interval'] for dest, opt in zip(list_dest, list_opt): value = srv_config[dest] if (value is not None) and (not isinstance(value, int)): pretty_printer(log_obj = loggersrv.error, to_exit = True, put_text = "{reverse}{red}{bold}argument `%s`: invalid with: '%s'. Exiting...{end}" %(opt, value))
def emit_error(self, message, to_exit = True): if not self.mute: pretty_printer(put_text = "{reverse}{red}{bold}%s{end}" %message, to_exit = True)
def emit_message(self, message, to_exit = False): if not self.mute: pretty_printer(put_text = "{reverse}{green}{bold}%s{end}" %message) if to_exit: sys.exit(0)
def emit_opt_err(self, msg): pretty_printer(put_text = "{reverse}{red}{bold}%s{end}" %msg, to_exit = True)
def server_options(): server_parser = KmsParser(description = srv_description, epilog = 'version: ' + srv_version, add_help = False) server_parser.add_argument("ip", nargs = "?", action = "store", default = srv_options['ip']['def'], help = srv_options['ip']['help'], type = str) server_parser.add_argument("port", nargs = "?", action = "store", default = srv_options['port']['def'], help = srv_options['port']['help'], type = int) server_parser.add_argument("-e", "--epid", action = "store", dest = srv_options['epid']['des'], default = srv_options['epid']['def'], help = srv_options['epid']['help'], type = str) server_parser.add_argument("-l", "--lcid", action = "store", dest = srv_options['lcid']['des'], default = srv_options['lcid']['def'], help = srv_options['lcid']['help'], type = int) server_parser.add_argument("-c", "--client-count", action = "store", dest = srv_options['count']['des'] , default = srv_options['count']['def'], help = srv_options['count']['help'], type = str) server_parser.add_argument("-a", "--activation-interval", action = "store", dest = srv_options['activation']['des'], default = srv_options['activation']['def'], help = srv_options['activation']['help'], type = int) server_parser.add_argument("-r", "--renewal-interval", action = "store", dest = srv_options['renewal']['des'], default = srv_options['renewal']['def'], help = srv_options['renewal']['help'], type = int) server_parser.add_argument("-s", "--sqlite", action = "store_true", dest = srv_options['sql']['des'], default = srv_options['sql']['def'], help = srv_options['sql']['help']) server_parser.add_argument("-w", "--hwid", action = "store", dest = srv_options['hwid']['des'], default = srv_options['hwid']['def'], help = srv_options['hwid']['help'], type = str) server_parser.add_argument("-t0", "--timeout-idle", action = "store", dest = srv_options['time0']['des'], default = srv_options['time0']['def'], help = srv_options['time0']['help'], type = str) server_parser.add_argument("-y", "--async-msg", action = "store_true", dest = srv_options['asyncmsg']['des'], default = srv_options['asyncmsg']['def'], help = srv_options['asyncmsg']['help']) server_parser.add_argument("-V", "--loglevel", action = "store", dest = srv_options['llevel']['des'], choices = srv_options['llevel']['choi'], default = srv_options['llevel']['def'], help = srv_options['llevel']['help'], type = str) server_parser.add_argument("-F", "--logfile", nargs = "+", action = "store", dest = srv_options['lfile']['des'], default = srv_options['lfile']['def'], help = srv_options['lfile']['help'], type = str) server_parser.add_argument("-S", "--logsize", action = "store", dest = srv_options['lsize']['des'], default = srv_options['lsize']['def'], help = srv_options['lsize']['help'], type = float) server_parser.add_argument("-h", "--help", action = "help", help = "show this help message and exit") daemon_parser = KmsParser(description = "daemon options inherited from Etrigan", add_help = False) daemon_subparser = daemon_parser.add_subparsers(dest = "mode") etrigan_parser = daemon_subparser.add_parser("etrigan", add_help = False) etrigan_parser.add_argument("-g", "--gui", action = "store_const", dest = 'gui', const = True, default = False, help = "Enable py-kms GUI usage.") etrigan_parser = Etrigan_parser(parser = etrigan_parser) try: userarg = sys.argv[1:] # Run help. if any(arg in ["-h", "--help"] for arg in userarg): KmsParserHelp().printer(parsers = [server_parser, daemon_parser, etrigan_parser]) # Get stored arguments. pykmssrv_zeroarg, pykmssrv_onearg = kms_parser_get(server_parser) etrigan_zeroarg, etrigan_onearg = kms_parser_get(etrigan_parser) pykmssrv_zeroarg += ['etrigan'] # add subparser # Set defaults for config. # example case: # python3 pykms_Server.py srv_config.update(vars(server_parser.parse_args([]))) try: # Eventually set daemon options for dict server config. pos = sys.argv[1:].index('etrigan') # example cases: # python3 pykms_Server.py etrigan start # python3 pykms_Server.py etrigan start --daemon_optionals # python3 pykms_Server.py 1.2.3.4 etrigan start # python3 pykms_Server.py 1.2.3.4 etrigan start --daemon_optionals # python3 pykms_Server.py 1.2.3.4 1234 etrigan start # python3 pykms_Server.py 1.2.3.4 1234 etrigan start --daemon_optionals # python3 pykms_Server.py --pykms_optionals etrigan start # python3 pykms_Server.py --pykms_optionals etrigan start --daemon_optionals # python3 pykms_Server.py 1.2.3.4 --pykms_optionals etrigan start # python3 pykms_Server.py 1.2.3.4 --pykms_optionals etrigan start --daemon_optionals # python3 pykms_Server.py 1.2.3.4 1234 --pykms_optionals etrigan start # python3 pykms_Server.py 1.2.3.4 1234 --pykms_optionals etrigan start --daemon_optionals kms_parser_check_optionals(userarg[0:pos], pykmssrv_zeroarg, pykmssrv_onearg, exclude_opt_len = ['-F', '--logfile']) kms_parser_check_positionals(srv_config, server_parser.parse_args, arguments = userarg[0:pos]) kms_parser_check_optionals(userarg[pos:], etrigan_zeroarg, etrigan_onearg, msg = 'optional etrigan') kms_parser_check_positionals(srv_config, daemon_parser.parse_args, arguments = userarg[pos:], msg = 'positional etrigan') except ValueError: # Update pykms options for dict server config. # example cases: # python3 pykms_Server.py 1.2.3.4 # python3 pykms_Server.py 1.2.3.4 --pykms_optionals # python3 pykms_Server.py 1.2.3.4 1234 # python3 pykms_Server.py 1.2.3.4 1234 --pykms_optionals # python3 pykms_Server.py --pykms_optionals kms_parser_check_optionals(userarg, pykmssrv_zeroarg, pykmssrv_onearg, exclude_opt_len = ['-F', '--logfile']) kms_parser_check_positionals(srv_config, server_parser.parse_args) except KmsParserException as e: pretty_printer(put_text = "{reverse}{red}{bold}%s. Exiting...{end}" %str(e), to_exit = True)
def server_options(): server_parser = KmsParser(description=srv_description, epilog='version: ' + srv_version, add_help=False) server_parser.add_argument("ip", nargs="?", action="store", default=srv_options['ip']['def'], help=srv_options['ip']['help'], type=str) server_parser.add_argument("port", nargs="?", action="store", default=srv_options['port']['def'], help=srv_options['port']['help'], type=int) server_parser.add_argument("-e", "--epid", action="store", dest=srv_options['epid']['des'], default=srv_options['epid']['def'], help=srv_options['epid']['help'], type=str) server_parser.add_argument("-l", "--lcid", action="store", dest=srv_options['lcid']['des'], default=srv_options['lcid']['def'], help=srv_options['lcid']['help'], type=int) server_parser.add_argument("-c", "--client-count", action="store", dest=srv_options['count']['des'], default=srv_options['count']['def'], help=srv_options['count']['help'], type=str) server_parser.add_argument("-a", "--activation-interval", action="store", dest=srv_options['activation']['des'], default=srv_options['activation']['def'], help=srv_options['activation']['help'], type=int) server_parser.add_argument("-r", "--renewal-interval", action="store", dest=srv_options['renewal']['des'], default=srv_options['renewal']['def'], help=srv_options['renewal']['help'], type=int) server_parser.add_argument("-s", "--sqlite", nargs="?", dest=srv_options['sql']['des'], const=True, default=srv_options['sql']['def'], help=srv_options['sql']['help'], type=str) server_parser.add_argument("-w", "--hwid", action="store", dest=srv_options['hwid']['des'], default=srv_options['hwid']['def'], help=srv_options['hwid']['help'], type=str) server_parser.add_argument("-t0", "--timeout-idle", action="store", dest=srv_options['time0']['des'], default=srv_options['time0']['def'], help=srv_options['time0']['help'], type=str) server_parser.add_argument("-t1", "--timeout-sndrcv", action="store", dest=srv_options['time1']['des'], default=srv_options['time1']['def'], help=srv_options['time1']['help'], type=str) server_parser.add_argument("-y", "--async-msg", action="store_true", dest=srv_options['asyncmsg']['des'], default=srv_options['asyncmsg']['def'], help=srv_options['asyncmsg']['help']) server_parser.add_argument("-V", "--loglevel", action="store", dest=srv_options['llevel']['des'], choices=srv_options['llevel']['choi'], default=srv_options['llevel']['def'], help=srv_options['llevel']['help'], type=str) server_parser.add_argument("-F", "--logfile", nargs="+", action="store", dest=srv_options['lfile']['des'], default=srv_options['lfile']['def'], help=srv_options['lfile']['help'], type=str) server_parser.add_argument("-S", "--logsize", action="store", dest=srv_options['lsize']['des'], default=srv_options['lsize']['def'], help=srv_options['lsize']['help'], type=float) server_parser.add_argument("-h", "--help", action="help", help="show this help message and exit") ## Daemon (Etrigan) parsing. daemon_parser = KmsParser( description="daemon options inherited from Etrigan", add_help=False) daemon_subparser = daemon_parser.add_subparsers(dest="mode") etrigan_parser = daemon_subparser.add_parser("etrigan", add_help=False) etrigan_parser.add_argument("-g", "--gui", action="store_const", dest='gui', const=True, default=False, help="Enable py-kms GUI usage.") etrigan_parser = Etrigan_parser(parser=etrigan_parser) ## Connection parsing. connection_parser = KmsParser(description="connect options", add_help=False) connection_subparser = connection_parser.add_subparsers(dest="mode") connect_parser = connection_subparser.add_parser("connect", add_help=False) connect_parser.add_argument("-n", "--listen", action="append", dest=srv_options['listen']['des'], default=[], help=srv_options['listen']['help'], type=str) connect_parser.add_argument("-b", "--backlog", action="append", dest=srv_options['backlog']['des'], default=[], help=srv_options['backlog']['help'], type=int) connect_parser.add_argument("-u", "--no-reuse", action="append_const", dest=srv_options['reuse']['des'], const=False, default=[], help=srv_options['reuse']['help']) connect_parser.add_argument("-d", "--dual", action="store_true", dest=srv_options['dual']['des'], default=srv_options['dual']['def'], help=srv_options['dual']['help']) try: userarg = sys.argv[1:] # Run help. if any(arg in ["-h", "--help"] for arg in userarg): KmsParserHelp().printer(parsers=[ server_parser, ( daemon_parser, etrigan_parser), (connection_parser, connect_parser) ]) # Get stored arguments. pykmssrv_zeroarg, pykmssrv_onearg = kms_parser_get(server_parser) etrigan_zeroarg, etrigan_onearg = kms_parser_get(etrigan_parser) connect_zeroarg, connect_onearg = kms_parser_get(connect_parser) subdict = { 'etrigan': (etrigan_zeroarg, etrigan_onearg, daemon_parser.parse_args), 'connect': (connect_zeroarg, connect_onearg, connection_parser.parse_args) } subpars = list(subdict.keys()) pykmssrv_zeroarg += subpars # add subparsers exclude_kms = ['-F', '--logfile'] exclude_dup = ['-n', '--listen', '-b', '--backlog', '-u', '--no-reuse'] # Set defaults for server dict config. # example case: # python3 pykms_Server.py srv_config.update(vars(server_parser.parse_args([]))) subindx = sorted([(userarg.index(pars), pars) for pars in subpars if pars in userarg], key=lambda x: x[0]) if subindx: # Set `daemon options` and/or `connect options` for server dict config. # example cases: # 1 python3 pykms_Server.py [1.2.3.4] [1234] [--pykms_optionals] etrigan daemon_positional [--daemon_optionals] \ # connect [--connect_optionals] # # 2 python3 pykms_Server.py [1.2.3.4] [1234] [--pykms_optionals] connect [--connect_optionals] etrigan \ # daemon_positional [--daemon_optionals] # # 3 python3 pykms_Server.py [1.2.3.4] [1234] [--pykms_optionals] etrigan daemon_positional [--daemon_optionals] # 4 python3 pykms_Server.py [1.2.3.4] [1234] [--pykms_optionals] connect [--connect_optionals] first = subindx[0][0] # initial. kms_parser_check_optionals(userarg[0:first], pykmssrv_zeroarg, pykmssrv_onearg, exclude_opt_len=exclude_kms) kms_parser_check_positionals(srv_config, server_parser.parse_args, arguments=userarg[0:first], force_parse=True) # middle. for i in range(len(subindx) - 1): posi, posf, typ = subindx[i][0], subindx[i + 1][0], subindx[i][1] kms_parser_check_optionals( userarg[posi:posf], subdict[typ][0], subdict[typ][1], msg='optional %s' % typ, exclude_opt_dup=(exclude_dup if typ == 'connect' else [])) kms_parser_check_positionals(srv_config, subdict[typ][2], arguments=userarg[posi:posf], msg='positional %s' % typ) # final. pos, typ = subindx[-1] kms_parser_check_optionals( userarg[pos:], subdict[typ][0], subdict[typ][1], msg='optional %s' % typ, exclude_opt_dup=(exclude_dup if typ == 'connect' else [])) kms_parser_check_positionals(srv_config, subdict[typ][2], arguments=userarg[pos:], msg='positional %s' % typ) if len(subindx) > 1: srv_config['mode'] = '+'.join(elem[1] for elem in subindx) else: # Update `pykms options` for server dict config. # example case: # 5 python3 pykms_Server.py [1.2.3.4] [1234] [--pykms_optionals] kms_parser_check_optionals(userarg, pykmssrv_zeroarg, pykmssrv_onearg, exclude_opt_len=exclude_kms) kms_parser_check_positionals(srv_config, server_parser.parse_args) kms_parser_check_connect(srv_config, srv_options, userarg, connect_zeroarg, connect_onearg) except KmsParserException as e: pretty_printer(put_text="{reverse}{red}{bold}%s. Exiting...{end}" % str(e), to_exit=True)
def client_create(clt_sock): binder = pykms_RpcBind.handler(None, clt_config) RPC_Bind = enco(str(binder.generateRequest()), 'latin-1') try: loggerclt.info("Sending RPC bind request...") pretty_printer(num_text = [-1, 1], where = "clt") clt_sock.send(RPC_Bind) except socket.error as e: pretty_printer(log_obj = loggerclt.error, to_exit = True, where = "clt", put_text = "{reverse}{red}{bold}While sending: %s. Exiting...{end}" %str(e)) try: bindResponse = clt_sock.recv(1024) if bindResponse == '' or not bindResponse: pretty_printer(log_obj = loggerclt.warning, to_exit = True, where = "clt", put_text = "{reverse}{yellow}{bold}No data received. Exiting...{end}") pretty_printer(num_text = [-4, 7], where = "clt") except socket.error as e: pretty_printer(log_obj = loggerclt.error, to_exit = True, where = "clt", put_text = "{reverse}{red}{bold}While receiving: %s. Exiting...{end}" %str(e)) packetType = MSRPCHeader(bindResponse)['type'] if packetType == rpcBase.packetType['bindAck']: loggerclt.info("RPC bind acknowledged.") pretty_printer(num_text = 8, where = "clt") kmsRequest = createKmsRequest() requester = pykms_RpcRequest.handler(kmsRequest, clt_config) try: loggerclt.info("Sending RPC activation request...") RPC_Actv = enco(str(requester.generateRequest()), 'latin-1') pretty_printer(num_text = [-1, 12], where = "clt") clt_sock.send(RPC_Actv) except socket.error as e: pretty_printer(log_obj = loggerclt.error, to_exit = True, where = "clt", put_text = "{reverse}{red}{bold}While sending: %s. Exiting...{end}" %str(e)) try: response = clt_sock.recv(1024) pretty_printer(num_text = [-4, 20], where = "clt") except socket.error as e: pretty_printer(log_obj = loggerclt.error, to_exit = True, where = "clt", put_text = "{reverse}{red}{bold}While receiving: %s. Exiting...{end}" %str(e)) loggerclt.debug("Response: \n%s\n" % justify(deco(binascii.b2a_hex(response), 'latin-1'))) parsed = MSRPCRespHeader(response) kmsData = readKmsResponse(parsed['pduData'], kmsRequest, clt_config) kmsResp = kmsData['response'] try: hwid = kmsData['hwid'] loggerclt.info("KMS Host HWID: %s" % deco(binascii.b2a_hex(enco(hwid, 'latin-1')).upper(), 'utf-8')) except KeyError: pass loggerclt.info("KMS Host ePID: %s" % kmsResp['kmsEpid'].encode('utf-8').decode('utf-16le')) loggerclt.info("KMS Host Current Client Count: %s" % kmsResp['currentClientCount']) loggerclt.info("KMS VL Activation Interval: %s" % kmsResp['vLActivationInterval']) loggerclt.info("KMS VL Renewal Interval: %s" % kmsResp['vLRenewalInterval']) if clt_config['loglevel'] == 'MININFO': loggerclt.mininfo("", extra = {'host': str(clt_sock.getpeername()), 'status' : kmsBase.licenseStates[requester.srv_config['KMSClientLicenseStatus']], 'product' : clt_config["mode"]}) pretty_printer(num_text = 21, where = "clt") elif packetType == rpcBase.packetType['bindNak']: loggerclt.info(justify(MSRPCBindNak(bindResponse).dump(print_to_stdout = False))) sys.exit(0) else: pretty_printer(log_obj = loggerclt.warning, to_exit = True, where = "clt", put_text = "{reverse}{magenta}{bold}Something went wrong. Exiting...{end}")