Moved the ip-address check functionality to a separate file to improve
the maintainability of the code.pull/29/head
parent
775e61c248
commit
1a34f61b24
|
@ -8,7 +8,6 @@
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
import simplejson as json
|
import simplejson as json
|
||||||
import re
|
|
||||||
import pgadmin.browser.server_groups as sg
|
import pgadmin.browser.server_groups as sg
|
||||||
from flask import render_template, request, make_response, jsonify, \
|
from flask import render_template, request, make_response, jsonify, \
|
||||||
current_app, url_for
|
current_app, url_for
|
||||||
|
@ -20,6 +19,7 @@ from pgadmin.utils.ajax import make_json_response, bad_request, forbidden, \
|
||||||
make_response as ajax_response, internal_server_error, unauthorized, gone
|
make_response as ajax_response, internal_server_error, unauthorized, gone
|
||||||
from pgadmin.utils.crypto import encrypt, decrypt, pqencryptpassword
|
from pgadmin.utils.crypto import encrypt, decrypt, pqencryptpassword
|
||||||
from pgadmin.utils.menu import MenuItem
|
from pgadmin.utils.menu import MenuItem
|
||||||
|
from pgadmin.utils.ip import is_valid_ipaddress
|
||||||
from pgadmin.tools.sqleditor.utils.query_history import QueryHistory
|
from pgadmin.tools.sqleditor.utils.query_history import QueryHistory
|
||||||
|
|
||||||
import config
|
import config
|
||||||
|
@ -272,31 +272,6 @@ class ServerNode(PGChildNodeView):
|
||||||
'clear_saved_password': [{'put': 'clear_saved_password'}],
|
'clear_saved_password': [{'put': 'clear_saved_password'}],
|
||||||
'clear_sshtunnel_password': [{'put': 'clear_sshtunnel_password'}]
|
'clear_sshtunnel_password': [{'put': 'clear_sshtunnel_password'}]
|
||||||
})
|
})
|
||||||
EXP_IP4 = "^\s*((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\." \
|
|
||||||
"(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\." \
|
|
||||||
"(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\." \
|
|
||||||
"(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))\s*$"
|
|
||||||
EXP_IP6 = '^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|' \
|
|
||||||
'(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|' \
|
|
||||||
'2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d))' \
|
|
||||||
'{3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|' \
|
|
||||||
':((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d' \
|
|
||||||
'|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]' \
|
|
||||||
'{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|' \
|
|
||||||
'[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|' \
|
|
||||||
'(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-' \
|
|
||||||
'Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25' \
|
|
||||||
'[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:)' \
|
|
||||||
'{2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:(' \
|
|
||||||
'(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|' \
|
|
||||||
'[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]' \
|
|
||||||
'{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|'\
|
|
||||||
'1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))' \
|
|
||||||
'|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((' \
|
|
||||||
'25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|' \
|
|
||||||
'[1-9]?\d)){3}))|:)))(%.+)?\s*$'
|
|
||||||
pat4 = re.compile(EXP_IP4)
|
|
||||||
pat6 = re.compile(EXP_IP6)
|
|
||||||
SSL_MODES = ['prefer', 'require', 'verify-ca', 'verify-full']
|
SSL_MODES = ['prefer', 'require', 'verify-ca', 'verify-full']
|
||||||
|
|
||||||
def check_ssl_fields(self, data):
|
def check_ssl_fields(self, data):
|
||||||
|
@ -570,7 +545,7 @@ class ServerNode(PGChildNodeView):
|
||||||
):
|
):
|
||||||
if arg in data:
|
if arg in data:
|
||||||
return forbidden(
|
return forbidden(
|
||||||
errormsg=gettext(
|
errmsg=gettext(
|
||||||
"'{0}' is not allowed to modify, "
|
"'{0}' is not allowed to modify, "
|
||||||
"when server is connected."
|
"when server is connected."
|
||||||
).format(disp_lbl[arg])
|
).format(disp_lbl[arg])
|
||||||
|
@ -771,13 +746,12 @@ class ServerNode(PGChildNodeView):
|
||||||
)
|
)
|
||||||
|
|
||||||
if 'hostaddr' in data and data['hostaddr'] and data['hostaddr'] != '':
|
if 'hostaddr' in data and data['hostaddr'] and data['hostaddr'] != '':
|
||||||
if not self.pat4.match(data['hostaddr']):
|
if not is_valid_ipaddress(data['hostaddr']):
|
||||||
if not self.pat6.match(data['hostaddr']):
|
return make_json_response(
|
||||||
return make_json_response(
|
success=0,
|
||||||
success=0,
|
status=400,
|
||||||
status=400,
|
errormsg=gettext('Not a valid Host address')
|
||||||
errormsg=gettext('Host address not valid')
|
)
|
||||||
)
|
|
||||||
|
|
||||||
# To check ssl configuration
|
# To check ssl configuration
|
||||||
is_ssl, data = self.check_ssl_fields(data)
|
is_ssl, data = self.check_ssl_fields(data)
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
##########################################################################
|
||||||
|
#
|
||||||
|
# pgAdmin 4 - PostgreSQL Tools
|
||||||
|
#
|
||||||
|
# Copyright (C) 2013 - 2020, The pgAdmin Development Team
|
||||||
|
# This software is released under the PostgreSQL Licence
|
||||||
|
#
|
||||||
|
#########################################################################
|
||||||
|
|
||||||
|
"""This File Provides ipv4 and ipv6 address check."""
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
|
IPV4SEG = r'(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])'
|
||||||
|
IPV4ADDR = r'(?:(?:' + IPV4SEG + r'\.){3,3}' + IPV4SEG + r')'
|
||||||
|
IPV6SEG = r'(?:(?:[0-9a-fA-F]){1,4})'
|
||||||
|
IPV6GROUPS = (
|
||||||
|
# 1:2:3:4:5:6:7:8
|
||||||
|
r'(?:' + IPV6SEG + r':){7,7}' + IPV6SEG,
|
||||||
|
# 1:: 1:2:3:4:5:6:7::
|
||||||
|
r'(?:' + IPV6SEG + r':){1,7}:',
|
||||||
|
# 1::8 1:2:3:4:5:6::8 1:2:3:4:5:6::8
|
||||||
|
r'(?:' + IPV6SEG + r':){1,6}:' + IPV6SEG,
|
||||||
|
# 1::7:8 1:2:3:4:5::7:8 1:2:3:4:5::8
|
||||||
|
r'(?:' + IPV6SEG + r':){1,5}(?::' + IPV6SEG + r'){1,2}',
|
||||||
|
# 1::6:7:8 1:2:3:4::6:7:8 1:2:3:4::8
|
||||||
|
r'(?:' + IPV6SEG + r':){1,4}(?::' + IPV6SEG + r'){1,3}',
|
||||||
|
# 1::5:6:7:8 1:2:3::5:6:7:8 1:2:3::8
|
||||||
|
r'(?:' + IPV6SEG + r':){1,3}(?::' + IPV6SEG + r'){1,4}',
|
||||||
|
# 1::4:5:6:7:8 1:2::4:5:6:7:8 1:2::8
|
||||||
|
r'(?:' + IPV6SEG + r':){1,2}(?::' + IPV6SEG + r'){1,5}',
|
||||||
|
# 1::3:4:5:6:7:8 1::3:4:5:6:7:8 1::8
|
||||||
|
IPV6SEG + r':(?:(?::' + IPV6SEG + r'){1,6})',
|
||||||
|
# ::2:3:4:5:6:7:8 ::2:3:4:5:6:7:8 ::8 ::
|
||||||
|
r':(?:(?::' + IPV6SEG + r'){1,7}|:)',
|
||||||
|
# fe80::7:8%eth0 fe80::7:8%1 (link-local IPv6 addresses with zone index)
|
||||||
|
r'fe80:(?::' + IPV6SEG + r'){0,4}%[0-9a-zA-Z]{1,}',
|
||||||
|
# ::255.255.255.255 ::ffff:255.255.255.255 ::ffff:0:255.255.255.255
|
||||||
|
# (IPv4-mapped IPv6 addresses and IPv4-translated addresses)
|
||||||
|
r'::(?:ffff(?::0{1,4}){0,1}:){0,1}[^\s:]' + IPV4ADDR,
|
||||||
|
# 2001:db8:3:4::192.0.2.33 64:ff9b::192.0.2.33
|
||||||
|
# (IPv4-Embedded IPv6 Address)
|
||||||
|
r'(?:' + IPV6SEG + r':){1,4}:[^\s:]' + IPV4ADDR,
|
||||||
|
)
|
||||||
|
# Reverse rows for greedy match
|
||||||
|
IPV6ADDR = '|'.join(['(?:{})'.format(g) for g in IPV6GROUPS[::-1]])
|
||||||
|
|
||||||
|
ip6re = re.compile(IPV6ADDR)
|
||||||
|
ip4re = re.compile(IPV4ADDR)
|
||||||
|
|
||||||
|
|
||||||
|
def is_valid_ip4address(addr):
|
||||||
|
return ip4re.match(addr)
|
||||||
|
|
||||||
|
|
||||||
|
def is_valid_ip6address(addr):
|
||||||
|
return ip6re.match(addr)
|
||||||
|
|
||||||
|
|
||||||
|
def is_valid_ipaddress(addr):
|
||||||
|
return ip4re.match(addr) and is_valid_ip6address(addr)
|
Loading…
Reference in New Issue