Ejemplo n.º 1
0
    def post(self):
        """
        This function creates new rebind subdomain from json looking something like this:
        {
            "ip_props": {
                "1":{ # <= Order in which domains will be resolved
                    "ip": "88.23.99.110", # <= ip to resolve
                    "repeat": 3 # <= how many times
                }
                "2":{
                    "ip": "169.254.169.254",
                    "repeat": "4ever" # <= forever can be supplied to never stop resolving this domain
                }
            },
            "name": "rbnd_test" # <= name (useful in web ui)
        }

        And half of the code just checks if input is correct if someone reading this has an
        idea how to do it more efficently please contribute
        """
        parser = reqparse.RequestParser()
        parser.add_argument('ip_props',
                            help='This field cannot be blank wtf',
                            required=True,
                            location="json")
        parser.add_argument('name',
                            help='This field cannot be blank wtf',
                            required=True,
                            location="json")
        req_data = parser.parse_args()
        """
        req_data['ip_props'] is a json in string so I need to load it :D
        """
        data = json.loads(req_data['ip_props'].replace('\'', '"'))
        """
        Validate input against base_schema
        """
        req_data['ip_props'] = data
        base_schema = {
            "type": "object",
            "properties": {
                "ip_props": {
                    "type": "object"
                },
                "name": {
                    "type": "string",
                    "maxLength": 120
                }
            }
        }

        try:
            validate(instance=req_data, schema=base_schema)
        except jsonschema.exceptions.ValidationError:
            return {
                'message':
                'Something went wrong, the supplied input doesn\'t seem to be valid'
            }, 500
        """
        Check if
        - Less than 32 IPs are supplied
        - Some retard can't count
        """
        if not len(data.keys()) < 32:
            return {'message': 'Something went wrong, max IPs: 32'}, 500
        elif not checkKeys(data.keys()):
            return {
                'message':
                f"Something went wrong, the str(numbers) go like this: ['1','2','3','4',...] and not {[x for x in data.keys()]}"
            }, 500
        """
        Iterate through every ip_prop and do some checks - details are in comments below
        """

        for i in data.keys():
            """
            This schema checks if
            - repeat is "4ever" or integer greater or equal to 1
            - ip and type is compatibile with one of A,AAAA and CNAME
            """

            prop_schema = {
                "type": "object",
                "properties": {
                    "repeat": {
                        "anyOf": [{
                            "type": "integer",
                            "minimum": 1
                        }, {
                            "type": "string",
                            "pattern": "^4ever$"
                        }]
                    },
                    "ip": {
                        "type":
                        "string",
                        "anyOf": [{
                            "format": "ipv4"
                        }, {
                            "format": "ipv6"
                        }, {
                            "format": "idn-hostname"
                        }]
                    },
                    "type": {
                        "type":
                        "string",
                        "anyOf": [{
                            "pattern": "^A$"
                        }, {
                            "pattern": "^AAAA$"
                        }, {
                            "pattern": "^CNAME$"
                        }]
                    }
                }
            }

            try:
                validate(instance=data[i], schema=prop_schema)
            except jsonschema.exceptions.ValidationError:
                return {
                    'message':
                    f'Something went wrong, the supplied input doesn\'t seem to be valid in [`ip_props`][{int(i)-1}]'
                }, 500
            """
            Check if supplied record type matches ip
            So 127.0.0.1 can't be CNAME
            And google.com can't be answer for A :D
            """
            record_funcs = {"CNAME": checkDomain, "A": ipv4, "AAAA": ipv6}
            if not record_funcs[data[i]['type']](data[i]['ip']):
                return {
                    'message':
                    f"data[{int(i)-1}]['ip'] has to be in {data[{int(i)-1}]['type']} format"
                }, 500
        """
        Then put the data together
        Generate new uuid4
        Put it in database and redis
        Then return the whole domain
        """

        # rbnd_json does not need name parameter - it's meant to be stored in redis and in props column in database
        rbnd_json = {'ip_props': data, 'ip_to_resolve': '1', 'turn': -1}
        uuid = uuid4().hex
        if DnsModel.find_by_uuid(uuid):
            """
            Just in case something bad happens
            """
            return {
                'message':
                'An error occured, please try again (REALLY TRY AGAIN, server generated uuid that exists, I didn\'t know it was possible :d) If you get this error please send it to me on twitter @marek_geleta You can follow me too'
            }, 500

        new_uuid = DnsModel(username=get_jwt_identity(),
                            uuid=uuid,
                            props=json.dumps(rbnd_json),
                            name=req_data['name'])

        try:
            new_uuid.save_to_db()
            setJson(uuid, rbnd_json)
            return {"subdomain": f"{uuid}.{DOMAIN}"}
        except:
            return {'message': 'Something went wrong'}, 500
Ejemplo n.º 2
0
    def post(self):
        """
        This function creates new rebind subdomain from json looking something like this:
        {
            "ip_props": {
                "1":{ # <= Order in which domains will be resolved
                    "ip": "88.23.99.110", # <= ip to resolve
                    "repeat": 3 # <= how many times
                }
                "2":{
                    "ip": "169.254.169.254",
                    "repeat": "4ever" # <= forever can be supplied to never stop resolving this domain
                }
            },
            "name": "rbnd_test" # <= name (useful in web ui)
        }

        And half of the code just checks if input is correct if someone reading this has an
        idea how to do it more efficently please contribute
        """
        parser = reqparse.RequestParser()
        parser.add_argument('ip_props',
                            help='This field cannot be blank wtf',
                            required=True,
                            location="json")
        parser.add_argument('name',
                            help='This field cannot be blank wtf',
                            required=True,
                            location="json")
        req_data = parser.parse_args()
        """
        req_data['ip_props'] is a json in string so I need to load it :D
        """
        data = json.loads(req_data['ip_props'].replace('\'', '"'))
        """
        Check if
        - Less than 32 IPs are supplied
        - Some retard can't count
        - Name is not longer than 64
        """
        if not len(data.keys()) < 32:
            return {'message': 'Something went wrong, max IPs: 32'}, 500
        elif not checkKeys(data.keys()):
            return {
                'message':
                f"Something went wrong, the str(numbers) go like this: ['1','2','3','4',...] and not {[x for x in data.keys()]}"
            }, 500
        elif len(req_data['name']) > 64:
            return {'message': 'Something went wrong, max name len: 64'}, 500
        """
        Iterate through every ip_prop and check
        """
        for i in data.keys():
            """
            If repeat
            - Is "4ever" or positive integer
            - Is not 0 - kind of makes no sense to repeat it 0 times
            """
            if (data[i]['repeat'] != '4ever' and type(data[i]['repeat']) != int
                ) or abs(data[i]['repeat']) != data[i]['repeat']:
                repeat = data[i]['repeat']
                return {
                    'message':
                    f'Something went wrong, `repeat` field can only hold positive integers or string `4ever` (in [`ip_props`][{i}][`repeat`])'
                }, 500
            elif data[i]['repeat'] == 0:
                return {
                    'message':
                    f'How am I supposed to repeat it 0 times??? [`ip_props`][{i}][`repeat`]'
                }, 500
            """
            If ip
            - Is in IPV4 format and if it's not a subnet
            because the IP function is a bit weird and idk what to use :D
            """
            try:
                if IP(data[i]['ip']).version() == 4 and IP(
                        data[i]['ip']).strNormal(0) == str(IP(data[i]['ip'])):
                    data[i]['ip'] = IP(data[i]['ip']).strNormal(0)
                else:
                    return {'message': 'IP has to be in IPV4 format'}, 500

            except:
                return {
                    'message':
                    f'An error occured, check [`ip_props`][{i}][`ip`] '
                }, 500
        """
        Then put the data together
        Generate new uuid4
        Put it in database and redis
        Then return the whole domain
        """
        rbnd_json = {'ip_props': data, 'ip_to_resolve': '1', 'turn': -1}
        uuid = uuid4().hex
        if DnsModel.find_by_uuid(uuid):
            """
            Just in case something bad happens
            """
            return {
                'message':
                'An error occured, please try again (REALLY TRY AGAIN, server generated uuid that exists, I didn\'t know it was possible :d) If you get this error please send it to me on twitter @marek_geleta You can follow me too'
            }, 500

        new_uuid = DnsModel(username=get_jwt_identity(),
                            uuid=uuid,
                            props=json.dumps(rbnd_json),
                            name=req_data['name'])

        try:
            new_uuid.save_to_db()
            setJson(uuid, rbnd_json)
            return {"subdomain": f"{uuid}.{DOMAIN}"}
        except:
            return {'message': 'Something went wrong'}, 500