Skip to content

Commit e4cbf75

Browse files
committed
fix: URL-encode special characters in credentials for XMLRPC URI in nipap-cli.
Passwords (and usernames) containing special characters such as '/', '@' or ':' would break the XMLRPC URI used by nipap-cli because urllib.parse.quote() defaults to safe='/', leaving '/' unencoded.
1 parent bd3d9b6 commit e4cbf75

2 files changed

Lines changed: 33 additions & 2 deletions

File tree

nipap-cli/nipap_cli/nipap_cli.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@ def setup_connection():
8787
con_params['password'] = getpass.getpass()
8888

8989
# Quote username & password
90-
con_params['username'] = quote(con_params['username'])
91-
con_params['password'] = quote(con_params['password'])
90+
con_params['username'] = quote(con_params['username'], safe='')
91+
con_params['password'] = quote(con_params['password'], safe='')
9292

9393
# build XML-RPC URI
9494
pynipap.xmlrpc_uri = "%(protocol)s://%(username)s:%(password)s@%(hostname)s:%(port)s" % con_params

nipap-cli/tests/cli-test.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
sys.path.insert(0, '..')
1010
from nipap_cli import nipap_cli
1111
from nipap_cli.command import Command, CommandError, InvalidCommand
12+
from urllib.parse import quote, urlparse
1213

1314
#
1415
# command functions
@@ -297,5 +298,35 @@ def test_rest_argument(self):
297298
)
298299

299300

301+
class TestPasswordEncoding(unittest.TestCase):
302+
303+
def _build_uri(self, username, password):
304+
return "http://%(username)s:%(password)s@localhost:1337" % {
305+
'username': quote(username, safe=''),
306+
'password': quote(password, safe=''),
307+
}
308+
309+
def test_slash_in_password(self):
310+
uri = self._build_uri('admin', 'pass/word')
311+
parsed = urlparse(uri)
312+
self.assertEqual(parsed.username, 'admin')
313+
self.assertEqual(parsed.password, 'pass/word')
314+
315+
def test_at_in_password(self):
316+
uri = self._build_uri('admin', 'p@ssword')
317+
parsed = urlparse(uri)
318+
self.assertEqual(parsed.password, 'p@ssword')
319+
320+
def test_colon_in_password(self):
321+
uri = self._build_uri('admin', 'pass:word')
322+
parsed = urlparse(uri)
323+
self.assertEqual(parsed.password, 'pass:word')
324+
325+
def test_multiple_special_chars(self):
326+
uri = self._build_uri('user/name', 'p@ss/w:rd!')
327+
parsed = urlparse(uri)
328+
self.assertEqual(parsed.username, 'user/name')
329+
self.assertEqual(parsed.password, 'p@ss/w:rd!')
330+
300331
if __name__ == '__main__':
301332
unittest.main()

0 commit comments

Comments
 (0)