예제 #1
0
def parse_key_pack(data):
    def get_pack_dict(pack):
        tag_dict = dict()
        tag_info = pack.split(b'\xdf')
        if tag_info[0][1] == len(pack[2:]):
            tag_info.pop(0)
            for tag in tag_info:
                if tag[1] == len(tag[2:]):
                    tag_dict.update(
                        {f'DF{hex(tag[0]).replace("0x", "")}': tag[2:]})
                else:
                    resp_gen.set_logging()
                    logging.error(
                        f'ERROR: missing data in tag: DF{hex(tag[0]).replace("0x", "")}\nPack:{pack}'
                    )
        else:
            resp_gen.set_logging()
            logging.error(
                f'ERROR: missing data in package №{tag_info[0][0]}\nPack:{pack}'
            )
        return tag_dict

    res_dict = dict()
    packs = data.split(b'\xff')[1:]
    for p in packs:
        tmp_dict = get_pack_dict(p)
        try:
            res_dict.update({tmp_dict['DF24']: tmp_dict})
        except KeyError:
            resp_gen.set_logging()
            logging.error(
                f'ERROR: missing tag DF24 in package №{p[0]}\nPack:{p}')
    return res_dict
예제 #2
0
def clear_resource(res):
    try:
        if res in INPUT_DATA:
            INPUT_DATA.remove(res)
        if res in OUTPUT_DATA:
            OUTPUT_DATA.remove(res)
        print(f'Connection closed:{str(res.getpeername())}\n')
        resp_gen.set_logging(); logging.info(f'Connection closed:{str(res)}')
        res.close()
    except Exception as e:
        resp_gen.set_logging()
        logging.error(f'ERROR:\n{e}')
예제 #3
0
def handle_writables(writs):
    for resource in writs:
        try:
            if PROTOCOL == 'TPTP':
                req = LAST_REQUEST[resource.getpeername()].decode('utf-8')
                resp = resp_gen.form_answer(req,
                                            RC_DICT,
                                            status_ready(resource.getpeername(), req))
            elif PROTOCOL == 'OWN':
                req = LAST_REQUEST[resource.getpeername()]
                resp = open_way.form_answer(req,
                                            OWN_RC_DICT,
                                            status_ready(resource.getpeername(), req))
            else:
                resp = None

            if resp and ready_to_answer(resource.getpeername(), resp):
                if PROTOCOL == 'TPTP':
                    print(f'RESPONSE TO {resource.getpeername()}:\n{resp_gen.print_req_res(resp)}\n')
                    resp_gen.set_logging()
                    logging.info(f'RESPONSE TO  {resource.getpeername()}:{str(resp)}')

                    if PRINT_HEX: print(resp_gen.print_hex_dump(resp))
                    if PARSE:
                        values = resp_gen.parse_data(resp)
                        if values: resp_gen.print_result(values)
                    resource.send(resp)
                    OUTPUT_DATA.remove(resource)

                    if resp.decode('utf-8').find('SUCCESS') != -1 or resp.decode('utf-8').find('FAILED') != -1:
                        for peer in STATUS_TIMER_LIST:
                            if resource.getpeername() in peer:
                                STATUS_TIMER_LIST.pop(STATUS_TIMER_LIST.index(peer))
                elif PROTOCOL == 'OWN':
                    print(f'RESPONSE TO {resource.getpeername()}:\n{resp}\n')
                    resp_gen.set_logging()
                    logging.info(f'RESPONSE TO  {resource.getpeername()}:{str(resp)}')

                    if PRINT_HEX: print(resp_gen.print_hex_dump(resp[2:]))
                    if PARSE:
                        values = open_way.get_values(resp)
                        if values: open_way.print_result(values)
                    resource.send(resp)
                    OUTPUT_DATA.remove(resource)

                    if resp[2:4] == b'\x06\x30' and resp[43:45] != b'09':
                        for peer in STATUS_TIMER_LIST:
                            if resource.getpeername() in peer:
                                STATUS_TIMER_LIST.pop(STATUS_TIMER_LIST.index(peer))
        except OSError:
            clear_resource(resource)
예제 #4
0
def handle_readables(reads, server):
    for resource in reads:
        if resource is server:
            conn, addr = resource.accept()
            conn.setblocking(False)
            INPUT_DATA.append(conn)
            print(f'New connection:{addr}\n')
            resp_gen.set_logging(); logging.info(f'New connection:{str(conn)}')
            if PROTOCOL == 'TPTP':
                conn.send(b'\x05')
        else:
            data = b''
            try:
                data = resource.recv(1024)
            except ConnectionResetError:
                pass

            if data:
                if PROTOCOL == 'TPTP':
                    print(f'REQUEST FROM {resource.getpeername()}:\n{resp_gen.print_req_res(data)}\n')
                elif PROTOCOL == 'OWN':
                    print(f'REQUEST FROM {resource.getpeername()}:\n{data}\n')

                resp_gen.set_logging()
                logging.info(f'REQUEST FROM {resource.getpeername()}:{str(data)}')

                if PRINT_HEX:
                    if PROTOCOL == 'TPTP':
                        print(resp_gen.print_hex_dump(data))
                    elif PROTOCOL == 'OWN':
                        print(resp_gen.print_hex_dump(data[2:]))
                if PARSE:
                    if PROTOCOL == 'OWN':
                        values = open_way.get_values(data)
                        if values: open_way.print_result(values)
                    elif PROTOCOL == 'TPTP':
                        values = resp_gen.parse_data(data)
                        if values: resp_gen.print_result(values)
                if resource.getpeername() not in LAST_REQUEST:
                    LAST_REQUEST.update({resource.getpeername(): data})
                else:
                    LAST_REQUEST[resource.getpeername()] = data

                if resource not in OUTPUT_DATA:
                    OUTPUT_DATA.append(resource)
            else:
                clear_resource(resource)
예제 #5
0
 def get_pack_dict(pack):
     tag_dict = dict()
     tag_info = pack.split(b'\xdf')
     if tag_info[0][1] == len(pack[2:]):
         tag_info.pop(0)
         for tag in tag_info:
             if tag[1] == len(tag[2:]):
                 tag_dict.update(
                     {f'DF{hex(tag[0]).replace("0x", "")}': tag[2:]})
             else:
                 resp_gen.set_logging()
                 logging.error(
                     f'ERROR: missing data in tag: DF{hex(tag[0]).replace("0x", "")}\nPack:{pack}'
                 )
     else:
         resp_gen.set_logging()
         logging.error(
             f'ERROR: missing data in package №{tag_info[0][0]}\nPack:{pack}'
         )
     return tag_dict
예제 #6
0
def ready_to_answer(addr, resp=None):
    for conn in TIMER_CONN_LIST:
        if addr in conn:
            if time.perf_counter() > conn[1]:
                TIMER_CONN_LIST.pop(TIMER_CONN_LIST.index(conn))
                return True
            else:
                return False
    else:
        cur_time = time.perf_counter()
        if len(resp) >= 10:
            try:
                if resp[41:43] == b'00' or resp[2:4] == b'\x94\x30':
                    TIMER_CONN_LIST.append([addr, cur_time + DELAY['VOID']])
                elif resp[41:43] == b'01' or resp[2:4] == b'\x97\x10':
                    TIMER_CONN_LIST.append([addr, cur_time + DELAY['QR_CODE']])
                elif resp[41:43] == b'02' or resp[2:4] == b'\x02\x30':
                    TIMER_CONN_LIST.append([addr, cur_time + DELAY['FINAL']])
                elif resp[41:43] == b'04' or resp[2:4] == b'\x02\x10':
                    TIMER_CONN_LIST.append([addr, cur_time + DELAY['REFUND']])
                elif resp[41:43] == b'36' or resp[2:4] == b'\x06\x30':
                    TIMER_CONN_LIST.append([addr, cur_time + DELAY['STATUS']])
                else:
                    TIMER_CONN_LIST.append([addr, cur_time + DELAY['DEFAULT']])

                for connect in TIMER_CONN_LIST:
                    if addr in connect:
                        if TIMER_CONN_LIST[TIMER_CONN_LIST.index(connect)][1] == cur_time:
                            return True
                        else:
                            return False
            except TypeError as e:
                resp_gen.set_logging(); logging.error(f'ERROR:\n{e}')
                return False
        else:
            if resp:
                TIMER_CONN_LIST.append([addr, cur_time + DELAY['CLOSE_OP']])
            return False
예제 #7
0
def print_result(raw_dict):
    bytes_list = [2, 3, 4, 7, 11, 12, 13, 14, 22, 24, 25, 48, 49, 64]
    string_list = [37, 38, 39, 41, 42, 60, 63]
    try:
        for field in raw_dict:
            if int(field) in bytes_list:
                res = list()
                for value in raw_dict[field]:
                    tmp = hex(value).replace('0x', '')
                    if len(tmp) < 2: tmp = ''.join(['0', tmp])
                    res.append(tmp)
                raw_dict[field] = ''.join(res)
            elif int(field) in string_list:
                raw_dict[field] = raw_dict[field].decode('utf-8')
            elif int(field) == 61:
                raw_dict[field] = raw_dict[field][10:].decode('utf-8')
    except Exception as e:
        resp_gen.set_logging()
        logging.error(f'ERROR:\n{e}')

    for f in raw_dict:
        print('{:3}: {}'.format(f, raw_dict[f]))
    print('\n', end='')
예제 #8
0
def go_to_key_files():
    global INI_KEYS
    INI_KEYS = dict()
    if os.path.exists('keys'):
        file = None
        for term_file in os.listdir('keys'):
            if '.ini' in term_file:
                if ''.join([TERMINAL, '.ini']) == term_file:
                    file = os.path.join('keys', term_file)
                elif ''.join(['NEW_', TERMINAL, '.ini']) == term_file:
                    try:
                        new_conf = Config(os.path.join('keys',
                                                       term_file)).as_args()
                        comp_1 = new_conf[new_conf.index('--KLK-Component-1') +
                                          1].zfill(32).upper()
                        comp_2 = new_conf[new_conf.index('--KLK-Component-2') +
                                          1].zfill(32).upper()
                        if (not re.match(r'[\dABCDEF]{32}', comp_1)
                                or not re.match(r'[\dABCDEF]{32}', comp_2)
                                or comp_1 == '0' * 32 and comp_2 == '0' * 32):
                            raise ValueError
                        new_klk = DES3.new(
                            unhexlify(klk_compile(comp_1, comp_2)),
                            DES3.MODE_ECB)
                        klk_cv = new_klk.encrypt(unhexlify(
                            '0' * 32)).hex().upper()[:6]
                        os.remove(os.path.join(os.getcwd(), 'keys', term_file))
                        INI_KEYS.update({
                            'KLK': {
                                'BODY': klk_compile(comp_1, comp_2),
                                'CV': klk_cv,
                                'INDEX': '0'
                            }
                        })
                        return True
                    except ValueError:
                        print(
                            f'Wrong values in {term_file}, please try again.\n'
                        )
            else:
                try:
                    os.remove(os.path.join(os.getcwd(), 'keys', term_file))
                except PermissionError:
                    shutil.rmtree(os.path.join(os.getcwd(), 'keys', term_file),
                                  ignore_errors=True)
        if file:
            try:
                conf_vals = Config(file).as_args()
                for i in range(len(conf_vals) // 2):
                    key_vals = conf_vals[i * 2 + 1].split('|')
                    if ((not re.match(r'[\dABCDEF]{32}', key_vals[0])
                         or len(key_vals[0]) != 32)
                            or (not re.match(r'[\dABCDEF]{6}', key_vals[1])
                                or len(key_vals[1]) != 6)
                            or not re.match(r'\d+', key_vals[2])):
                        raise IndexError
                    INI_KEYS.update({
                        conf_vals[i * 2].split('-')[-1]: {
                            'BODY': key_vals[0],
                            'CV': key_vals[1],
                            'INDEX': key_vals[2]
                        }
                    })
                if INI_KEYS:
                    return True
                return False
            except IndexError:
                resp_gen.set_logging()
                logging.error(f'Error while parsing file {file}')
                return False
        else:
            gen_new_ini_file()
            return False
    else:
        os.mkdir('keys')
        return go_to_key_files()
예제 #9
0
def form_answer(request, rc_dict, status_ready):
    def qr_code_resp():
        fields_list = [3, 4, 7, 11, 12, 13, 37, 38, 39, 41, 49, 61]
        datetime_dict = get_date_time()

        massage_type = b'\x97\x10'
        bitmap = get_bitmap(fields_list)
        processing_code = b'\x38\x00\x00'                                                                       # 3
        amount = parsed_req['4']                                                                                # 4
        trans_date_time = b''.join([datetime_dict['date'], datetime_dict['time']])                              # 7
        audit_number = parsed_req['11']                                                                         # 11
        trans_time = datetime_dict['time']                                                                      # 12
        trans_date = datetime_dict['date']                                                                      # 13
        retrieval_ref = str(datetime.datetime.now().time()).replace('.', '').replace(':', '').encode('utf-8')   # 37
        auth_code = ''.join([str(randint(0, 9)) for i in range(6)]).encode('utf-8')                             # 38
        resp_code = b'00'                                                                                       # 39
        acceptor_terminal = parsed_req['41']                                                                    # 41
        currency = parsed_req['49']                                                                             # 49
        qr_code = b'\x00\x00\x26\xeb\x18\xf2\x16\xc2\x14\x54https://example.com'                                # 61

        resp_no_len = b''.join([massage_type, bitmap, processing_code, amount, trans_date_time, audit_number,
                                trans_time, trans_date, retrieval_ref, auth_code, resp_code, acceptor_terminal,
                                currency, qr_code])
        response = b''.join([convert_len_to_bytes(len(resp_no_len)), resp_no_len])
        return response

    def status_resp():
        fields_list = [4, 7, 11, 12, 13, 37, 39, 41, 49]
        datetime_dict = get_date_time()

        massage_type = b'\x06\x30'
        bitmap = get_bitmap(fields_list)
        amount = parsed_req['4']                                                    # 4
        trans_date_time = b''.join([datetime_dict['date'], datetime_dict['time']])  # 7
        audit_number = parsed_req['11']                                             # 11
        trans_time = datetime_dict['time']                                          # 12
        trans_date = datetime_dict['date']                                          # 13
        retrieval_ref = parsed_req['37']                                            # 37
        if status_ready:                                                            # -
            if b'SBPAY' in parsed_req['63']:                                        # -
                resp_code = rc_dict['sale_rc']                                      # 39
            else:                                                                   # -
                resp_code = b'00'                                                   # 39
        else:                                                                       # -
            resp_code = b'09'                                                       # 39
        acceptor_terminal = parsed_req['41']                                        # 41
        currency = parsed_req['49']                                                 # 49

        resp_no_len = b''.join([massage_type, bitmap, amount, trans_date_time, audit_number, trans_time, trans_date,
                                retrieval_ref, resp_code, acceptor_terminal, currency])
        response = b''.join([convert_len_to_bytes(len(resp_no_len)), resp_no_len])
        return response

    def final_sale_resp():
        fields_list = [3, 7, 11, 12, 13, 37, 38, 39, 41, 49]
        datetime_dict = get_date_time()

        massage_type = b'\x02\x30'
        bitmap = get_bitmap(fields_list)
        processing_code = b'\x00\x00\x00'                                               # 3
        trans_date_time = b''.join([datetime_dict['date'], datetime_dict['time']])      # 7
        audit_number = parsed_req['11']                                                 # 11
        trans_time = datetime_dict['time']                                              # 12
        trans_date = datetime_dict['date']                                              # 13
        retrieval_ref = parsed_req['37']                                                # 37
        auth_code = ''.join([str(randint(0, 9)) for i in range(6)]).encode('utf-8')     # 38
        resp_code = rc_dict['sale_rc']                                                  # 39
        acceptor_terminal = parsed_req['41']                                            # 41
        currency = parsed_req['49']                                                     # 49

        resp_no_len = b''.join([massage_type, bitmap, processing_code, trans_date_time, audit_number, trans_time,
                                trans_date, retrieval_ref, auth_code, resp_code, acceptor_terminal, currency])
        response = b''.join([convert_len_to_bytes(len(resp_no_len)), resp_no_len])
        return response

    def refund_resp():
        fields_list = [2, 3, 7, 11, 12, 13, 37, 38, 39, 41, 49]
        datetime_dict = get_date_time()

        massage_type = b'\x02\x10'
        bitmap = get_bitmap(fields_list)
        pan = b''.join([get_bytes(str(len(parsed_req['2']) * 2)), parsed_req['2']])         # 2
        processing_code = b'\x25\x00\x00'                                                   # 3
        trans_date_time = b''.join([datetime_dict['date'], datetime_dict['time']])          # 7
        audit_number = parsed_req['11']                                                     # 11
        trans_time = datetime_dict['time']                                                  # 12
        trans_date = datetime_dict['date']                                                  # 13
        retrieval_ref = ''.join([str(randint(0, 9)) for i in range(12)]).encode('utf-8')    # 37
        auth_code = ''.join([str(randint(0, 9)) for i in range(6)]).encode('utf-8')         # 38
        resp_code = rc_dict['refund_rc']                                                    # 39
        acceptor_terminal = parsed_req['41']                                                # 41
        currency = parsed_req['49']                                                         # 49

        resp_no_len = b''.join([massage_type, bitmap, pan, processing_code, trans_date_time, audit_number, trans_time,
                                trans_date, retrieval_ref, auth_code, resp_code, acceptor_terminal, currency])
        response = b''.join([convert_len_to_bytes(len(resp_no_len)), resp_no_len])
        return response

    def qr_rev_resp():
        fields_list = [3, 7, 11, 12, 13, 37, 38, 39, 41, 49]
        datetime_dict = get_date_time()

        massage_type = b'\x94\x30'
        bitmap = get_bitmap(fields_list)
        processing_code = b'\x38\x00\x00'                                                       # 3
        trans_date_time = b''.join([datetime_dict['date'], datetime_dict['time']])              # 7
        audit_number = parsed_req['11']                                                         # 11
        trans_time = datetime_dict['time']                                                      # 12
        trans_date = datetime_dict['date']                                                      # 13
        try:                                                                                    # -
            retrieval_ref = parsed_req['37']                                                    # 37
        except KeyError:                                                                        # -
            retrieval_ref = ''.join([str(randint(0, 9)) for i in range(12)]).encode('utf-8')    # 37
        auth_code = ''.join([str(randint(0, 9)) for i in range(6)]).encode('utf-8')             # 38
        resp_code = b'00'                                                                       # 39
        acceptor_terminal = parsed_req['41']                                                    # 41
        currency = parsed_req['49']                                                             # 49

        resp_no_len = b''.join([massage_type, bitmap, processing_code, trans_date_time, audit_number, trans_time,
                                trans_date, retrieval_ref, auth_code, resp_code, acceptor_terminal, currency])
        response = b''.join([convert_len_to_bytes(len(resp_no_len)), resp_no_len])
        return response

    def close_batch_resp():
        fields_list = [3, 7, 11, 12, 13, 37, 39, 41, 60]
        datetime_dict = get_date_time()

        massage_type = b'\x05\x10'
        bitmap = get_bitmap(fields_list)
        processing_code = b'\x92\x00\x00'                                                   # 3
        trans_date_time = b''.join([datetime_dict['date'], datetime_dict['time']])          # 7
        audit_number = parsed_req['11']                                                     # 11
        trans_time = datetime_dict['time']                                                  # 12
        trans_date = datetime_dict['date']                                                  # 13
        retrieval_ref = ''.join([str(randint(0, 9)) for i in range(12)]).encode('utf-8')    # 37
        if rc_dict['cl_batch']:                                                             # -
            resp_code = b'00'                                                               # 39
        else:                                                                               # -
            resp_code = b'01'                                                               # 39
        acceptor_terminal = parsed_req['41']                                                # 41
        original_element = b''.join([b'\x00\x06', parsed_req['60']])                        # 60

        resp_no_len = b''.join([massage_type, bitmap, processing_code, trans_date_time, audit_number, trans_time,
                                trans_date, retrieval_ref, resp_code, acceptor_terminal, original_element])
        response = b''.join([convert_len_to_bytes(len(resp_no_len)), resp_no_len])
        return response

    def reversal_resp():
        fields_list = [2, 3, 4, 7, 11, 12, 13, 24, 37, 39, 41, 49]
        datetime_dict = get_date_time()

        massage_type = b'\x05\x10'
        bitmap = get_bitmap(fields_list)
        pan = b''.join([get_bytes(str(len(parsed_req['2']) * 2)), parsed_req['2']])         # 2
        processing_code = parsed_req['3']                                                   # 3
        amount = parsed_req['4']                                                            # 4
        trans_date_time = b''.join([datetime_dict['date'], datetime_dict['time']])          # 7
        audit_number = parsed_req['11']                                                     # 11
        trans_time = datetime_dict['time']                                                  # 12
        trans_date = datetime_dict['date']                                                  # 13
        func_code = parsed_req['24']                                                        # 24
        retrieval_ref = ''.join([str(randint(0, 9)) for i in range(12)]).encode('utf-8')    # 37
        resp_code = b'00'                                                                   # 39
        acceptor_terminal = parsed_req['41']                                                # 41
        currency = parsed_req['49']                                                         # 49

        resp_no_len = b''.join([massage_type, bitmap, pan, processing_code, amount, trans_date_time, audit_number, trans_time, trans_date,
                                func_code, retrieval_ref, resp_code, acceptor_terminal, currency])
        response = b''.join([convert_len_to_bytes(len(resp_no_len)), resp_no_len])
        return response

    def key_export_resp():
        fields_list = [3, 7, 11, 12, 13, 39, 41]
        datetime_dict = get_date_time()

        massage_type = b'\x08\x10'
        processing_code = parsed_req['3']                                                   # 3
        trans_date_time = b''.join([datetime_dict['date'], datetime_dict['time']])          # 7
        audit_number = parsed_req['11']                                                     # 11
        trans_time = datetime_dict['time']                                                  # 12
        trans_date = datetime_dict['date']                                                  # 13
        resp_code = rc_dict['key_decline_rc']                                               # 39
        acceptor_terminal = parsed_req['41']                                                # 41
        additional_data = key_manager.gen_key_field(parsed_req['48'], parsed_req['41'])     # 48
        if additional_data:
            resp_code = b'00'
            fields_list.append(48)
            additional_data = b''.join([get_bytes(str(len(additional_data))), additional_data])

        bitmap = get_bitmap(fields_list)
        resp_no_len = b''.join([massage_type, bitmap, processing_code, trans_date_time, audit_number, trans_time,
                                trans_date, resp_code, acceptor_terminal, additional_data])
        response = b''.join([convert_len_to_bytes(len(resp_no_len)), resp_no_len])
        return response

    try:
        parsed_req = get_values(request)
        if request[2:4] == b'\x97\x00':
            return qr_code_resp()
        elif request[2:4] == b'\x06\x20':
            return status_resp()
        elif request[2:4] == b'\x02\x20':
            return final_sale_resp()
        elif request[2:4] == b'\x02\x00':
            return refund_resp()
        elif request[2:4] == b'\x94\x20':
            return qr_rev_resp()
        elif request[2:4] == b'\x05\x00' or request[2:4] == b'\x05\x01':
            return close_batch_resp()
        elif request[2:4] == b'\x04\x20' or request[2:4] == b'\x04\x21':
            return reversal_resp()
        elif request[2:4] == b'\x08\x00':
            return key_export_resp()
        else:
            return None
    except Exception as e:
        resp_gen.set_logging()
        logging.error(f'ERROR:\n{e}')
        return None
예제 #10
0
if __name__ == '__main__':
    os.system('cls')
    setup_vars()  # initiates variables
    time.perf_counter()  # initiates timer
    resp_gen.check_log_files()  # controls maximal log files

    try:
        srv_socket = get_server_socket()
    except OSError:
        print('Program is already running or address/port is wrong!')
        input('Press ENTER to exit.')
        sys.exit()

    INPUT_DATA.append(srv_socket)
    length = shutil.get_terminal_size()[0]
    fin_length = length - ((length - 25) // 2) - 25
    header = f'{"-" * ((length - 25) // 2)}Alipay test server v{version.get_version()}{"-" * fin_length}'
    resp_gen.set_logging(); logging.info(f'Server started {srv_socket}')
    print(header)

    try:
        while INPUT_DATA:
            readables, writables, exceptional = select(INPUT_DATA, OUTPUT_DATA, INPUT_DATA)
            handle_readables(readables, srv_socket)
            handle_writables(writables)
    except KeyboardInterrupt:
        clear_resource(srv_socket)
        print('Server stopped!')
        resp_gen.set_logging(); logging.info('Server stopped!')