Skip to content

Commit fc86cbf

Browse files
Fixed wildcard matching of domains in Subject Alternative Names (#462).
1 parent ac31eaf commit fc86cbf

File tree

2 files changed

+47
-6
lines changed

2 files changed

+47
-6
lines changed

doc/src/release_notes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ Thin Mode Changes
2525
(`issue 455 <https://github.com/oracle/python-oracledb/issues/455>`__).
2626
#) Fixed decoding of nested PL/SQL records
2727
(`issue 456 <https://github.com/oracle/python-oracledb/issues/456>`__).
28+
#) Fixed wildcard matching of domains in Subject Alternative Names
29+
(`issue 462 <https://github.com/oracle/python-oracledb/issues/462>`__).
2830

2931
Thick Mode Changes
3032
++++++++++++++++++

src/oracledb/impl/thin/crypto.pyx

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,45 @@ except Exception as e:
4242
DN_REGEX = '(?:^|,\s?)(?:(?P<name>[A-Z]+)=(?P<val>"(?:[^"]|"")+"|[^,]+))+'
4343
PEM_WALLET_FILE_NAME = "ewallet.pem"
4444

45+
def _name_matches(name_to_check, cert_name):
46+
"""
47+
Returns a boolean indicating if the name to check matches with the
48+
certificate name. The certificate name may contain a wildcard (*)
49+
character.
50+
"""
51+
52+
# check for a full match (case insensitive)
53+
cert_name = cert_name.lower()
54+
name_to_check = name_to_check.lower()
55+
if name_to_check == cert_name:
56+
return True
57+
58+
# ensure that more than one label exists in both the name to check and the
59+
# certificate name
60+
check_pos = name_to_check.find(".")
61+
cert_pos = cert_name.find(".")
62+
if check_pos <= 0 or cert_pos <= 0:
63+
return False
64+
65+
# ensure that the right hand labels all match
66+
if name_to_check[check_pos:] != cert_name[cert_pos:]:
67+
return False
68+
69+
# match wildcards, if applicable
70+
cert_label = cert_name[:cert_pos]
71+
check_label = name_to_check[:check_pos]
72+
if cert_label == "*":
73+
return True
74+
elif cert_label.startswith("*"):
75+
return check_label.endswith(cert_label[1:])
76+
elif cert_label.endswith("*"):
77+
return check_label.startswith(cert_label[:-1])
78+
wildcard_pos = cert_name.find("*")
79+
if wildcard_pos < 0:
80+
return False
81+
return check_label.startswith(cert_label[:wildcard_pos]) \
82+
and check_label.endswith(cert_label[wildcard_pos + 1:])
83+
4584

4685
def check_server_dn(sock, expected_dn, expected_name):
4786
"""
@@ -58,20 +97,20 @@ def check_server_dn(sock, expected_dn, expected_name):
5897
errors._raise_err(errors.ERR_INVALID_SERVER_CERT_DN,
5998
expected_dn=expected_dn)
6099
else:
61-
for name in cert.subject.get_attributes_for_oid(
62-
x509.oid.NameOID.COMMON_NAME
63-
):
64-
if name.value == expected_name:
65-
return
66100
try:
67101
ext = cert.extensions.get_extension_for_oid(
68102
x509.oid.ExtensionOID.SUBJECT_ALTERNATIVE_NAME
69103
)
70104
for name in ext.value.get_values_for_type(x509.DNSName):
71-
if name == expected_name:
105+
if _name_matches(expected_name, name):
72106
return
73107
except x509.ExtensionNotFound:
74108
pass
109+
for name in cert.subject.get_attributes_for_oid(
110+
x509.oid.NameOID.COMMON_NAME
111+
):
112+
if _name_matches(expected_name, name.value):
113+
return
75114
errors._raise_err(errors.ERR_INVALID_SERVER_NAME,
76115
expected_name=expected_name)
77116

0 commit comments

Comments
 (0)