BIND 10 master, updated. 6067533e5c4ebded8260ef4b97f2709868bb2799 Merge branch 'trac2641_3'
BIND 10 source code commits
bind10-changes at lists.isc.org
Mon Mar 11 02:29:10 UTC 2013
The branch, master has been updated
via 6067533e5c4ebded8260ef4b97f2709868bb2799 (commit)
via 85a61f11135e898164d5e41e949bb6ba6929531b (commit)
via 0f0c175daf770bf863f32a4798657625704a0c54 (commit)
via 99fbbc37fe2c3e465af2e1e5990b89602b02e8d4 (commit)
via ee109e14bb0c0409c689ca73fb9ddd5f2435e29b (commit)
via e2e93cd2354580d7707c07f8f73e07e0e27f18c0 (commit)
via 60aa5f582f596951f0e14e73164f53edc4f8b8e7 (commit)
via 7c623395e4217f10a57a7c312c2e4066ac7c77bd (commit)
via 90251f717001cf297ea3e203777918b8614b2f0d (commit)
via 4ea6a9c51663de36095fa119698ded5f42d70690 (commit)
via cfc683caf3aa9c700a7b10ab689d949ffae2d207 (commit)
via 27dc1e7a87eb35dfa6a67f44b8ddf2d66d26abab (commit)
via f75fcf0b19faa026baba075f8e76dc5aef4d31da (commit)
via 80b1a680ca8b5ac8eda1b0b6ccb665e243e34182 (commit)
via 77af0818a39b800189928ae950839a43f3d8f2d9 (commit)
via e86811d1938f1f16fc7ecf44d09b08ad9058a756 (commit)
via 1e653cb517d99f96a7eed74a8ca457fe2332a15e (commit)
via 2b9c6a45464d5c064012984665bd3141c4aded27 (commit)
via 77520e9dda0fc9cac5bbd8bdf7225ecc52bd8ed5 (commit)
via 0abfd1c9e17568e36411cfc30e5e084fa84c92df (commit)
via 788685826e01b05cdb12c78bf367192d0139745c (commit)
via 221bb9df74bd6b827ea7dbc13cf07abb3ba939c9 (commit)
via ada6840f0a21dfb6368a22d59e2a24c815eaf997 (commit)
via e363285144493f03d8ba898cf762fc8bccf2f4a9 (commit)
via e1725e2609322cd2c87b0d90bf85b6c5b647dd66 (commit)
via 2133c6ae39aef257ad8c46bbffd0765de83bdce8 (commit)
via f597ce3956c82c48cd5c3623c18bfd01b506047c (commit)
via b6d51351a7935aeddcf3520e33dc5bf5e58a84a7 (commit)
via 544b01dd9fe18dd5ddb914239e5435854042b0d5 (commit)
via 10c4a13810da974778a046128414e392d9395d02 (commit)
via 97d4ccea5736cdc872913ba633154323c17a0e49 (commit)
via 21e0ea894b81e5b6ac02c369b89456b8d8bae9cb (commit)
from 8d178815af6a1eda06930288f3bcb4b261e25bbd (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 6067533e5c4ebded8260ef4b97f2709868bb2799
Merge: 8d17881 85a61f1
Author: Mukund Sivaraman <muks at isc.org>
Date: Mon Mar 11 07:16:40 2013 +0530
Merge branch 'trac2641_3'
-----------------------------------------------------------------------
Summary of changes:
src/bin/bindctl/bindcmd.py | 59 +++++++++---------
src/bin/bindctl/tests/bindctl_test.py | 60 +++++++++++++-----
src/bin/cmdctl/Makefile.am | 6 +-
src/bin/cmdctl/cmdctl.py.in | 9 ++-
src/bin/cmdctl/tests/Makefile.am | 2 +-
src/bin/cmdctl/tests/b10-certgen_test.py | 5 +-
src/bin/cmdctl/tests/cmdctl_test.py | 98 ++++++++++++++++++++++++------
7 files changed, 164 insertions(+), 75 deletions(-)
-----------------------------------------------------------------------
diff --git a/src/bin/bindctl/bindcmd.py b/src/bin/bindctl/bindcmd.py
index f382e2a..5ae82a2 100644
--- a/src/bin/bindctl/bindcmd.py
+++ b/src/bin/bindctl/bindcmd.py
@@ -33,6 +33,7 @@ import inspect
import pprint
import ssl, socket
import os, time, random, re
+import os.path
import getpass
from hashlib import sha1
import csv
@@ -214,22 +215,16 @@ WARNING: Python readline module isn't available, so the command line editor
return True
- def __print_check_ssl_msg(self):
- self._print("Please check the logs of b10-cmdctl, there may "
- "be a problem accepting SSL connections, such "
- "as a permission problem on the server "
- "certificate file.")
-
def _try_login(self, username, password):
'''
- Attempts to log in to cmdctl by sending a POST with
- the given username and password.
- On success of the POST (mind, not the login, only the network
- operation), returns a tuple (response, data).
- On failure, raises a FailToLogin exception, and prints some
- information on the failure.
- This call is essentially 'private', but made 'protected' for
- easier testing.
+ Attempts to log into cmdctl by sending a POST with the given
+ username and password. On success of the POST (not the login,
+ but the network operation), it returns a tuple (response, data).
+ We check for some failures such as SSL errors and socket errors
+ which could happen due to the environment in which BIND 10 runs.
+ On failure, it raises a FailToLogin exception and prints some
+ information on the failure. This call is essentially 'private',
+ but made 'protected' for easier testing.
'''
param = {'username': username, 'password' : password}
try:
@@ -237,16 +232,8 @@ WARNING: Python readline module isn't available, so the command line editor
data = response.read().decode()
# return here (will raise error after try block)
return (response, data)
- except ssl.SSLError as err:
- self._print("SSL error while sending login information: ", err)
- if err.errno == ssl.SSL_ERROR_EOF:
- self.__print_check_ssl_msg()
- except socket.error as err:
- self._print("Socket error while sending login information: ", err)
- # An SSL setup error can also bubble up as a plain CONNRESET...
- # (on some systems it usually does)
- if err.errno == errno.ECONNRESET:
- self.__print_check_ssl_msg()
+ except (ssl.SSLError, socket.error) as err:
+ self._print('Error while sending login information:', err)
pass
raise FailToLogin()
@@ -270,9 +257,21 @@ WARNING: Python readline module isn't available, so the command line editor
# No valid logins were found, prompt the user for a username/password
count = 0
- self._print('No stored password file found, please see sections '
- '"Configuration specification for b10-cmdctl" and "bindctl '
- 'command-line options" of the BIND 10 guide.')
+ if not os.path.exists(self.csv_file_dir + CSV_FILE_NAME):
+ self._print('\nNo stored password file found.\n\n'
+ 'When the system is first set up you need to create '
+ 'at least one user account.\n'
+ 'For information on how to set up a BIND 10 system, '
+ 'please check see the\n'
+ 'BIND 10 Guide: \n\n'
+ 'http://bind10.isc.org/docs/bind10-guide.html#quick-start-auth-dns\n\n'
+
+ 'If a user account has been set up, please check the '
+ 'b10-cmdctl log for other\n'
+ 'information.\n')
+ else:
+ self._print('Login failed: either the user name or password is '
+ 'invalid.\n')
while True:
count = count + 1
if count > 3:
@@ -317,14 +316,14 @@ WARNING: Python readline module isn't available, so the command line editor
return {}
- def send_POST(self, url, post_param = None):
+ def send_POST(self, url, post_param=None):
'''Send POST request to cmdctl, session id is send with the name
'cookie' in header.
Format: /module_name/command_name
parameters of command is encoded as a map
'''
param = None
- if (len(post_param) != 0):
+ if post_param is not None and len(post_param) != 0:
param = json.dumps(post_param)
headers = {"cookie" : self.session_id}
@@ -938,5 +937,3 @@ WARNING: Python readline module isn't available, so the command line editor
if data != "" and data != "{}":
self._print(json.dumps(json.loads(data), sort_keys=True,
indent=4))
-
-
diff --git a/src/bin/bindctl/tests/bindctl_test.py b/src/bin/bindctl/tests/bindctl_test.py
index 0ec9b58..c3262e1 100644
--- a/src/bin/bindctl/tests/bindctl_test.py
+++ b/src/bin/bindctl/tests/bindctl_test.py
@@ -26,6 +26,7 @@ import http.client
import pwd
import getpass
import re
+import json
from optparse import OptionParser
from isc.config.config_data import ConfigData, MultiConfigData
from isc.config.module_spec import ModuleSpec
@@ -386,7 +387,7 @@ class TestConfigCommands(unittest.TestCase):
self.tool.send_POST = send_POST_raiseImmediately
self.assertRaises(FailToLogin, self.tool._try_login, "foo", "bar")
expected_printed_messages.append(
- 'Socket error while sending login information: test error')
+ 'Error while sending login information: test error')
self.__check_printed_messages(expected_printed_messages)
def create_send_POST_raiseOnRead(exception):
@@ -405,7 +406,7 @@ class TestConfigCommands(unittest.TestCase):
create_send_POST_raiseOnRead(socket.error("read error"))
self.assertRaises(FailToLogin, self.tool._try_login, "foo", "bar")
expected_printed_messages.append(
- 'Socket error while sending login information: read error')
+ 'Error while sending login information: read error')
self.__check_printed_messages(expected_printed_messages)
# connection reset
@@ -415,13 +416,7 @@ class TestConfigCommands(unittest.TestCase):
create_send_POST_raiseOnRead(exc)
self.assertRaises(FailToLogin, self.tool._try_login, "foo", "bar")
expected_printed_messages.append(
- 'Socket error while sending login information: '
- 'connection reset')
- expected_printed_messages.append(
- 'Please check the logs of b10-cmdctl, there may be a '
- 'problem accepting SSL connections, such as a permission '
- 'problem on the server certificate file.'
- )
+ 'Error while sending login information: connection reset')
self.__check_printed_messages(expected_printed_messages)
# 'normal' SSL error
@@ -430,7 +425,7 @@ class TestConfigCommands(unittest.TestCase):
create_send_POST_raiseOnRead(exc)
self.assertRaises(FailToLogin, self.tool._try_login, "foo", "bar")
expected_printed_messages.append(
- 'SSL error while sending login information: .*')
+ 'Error while sending login information: .*')
self.__check_printed_messages(expected_printed_messages)
# 'EOF' SSL error
@@ -440,12 +435,7 @@ class TestConfigCommands(unittest.TestCase):
create_send_POST_raiseOnRead(exc)
self.assertRaises(FailToLogin, self.tool._try_login, "foo", "bar")
expected_printed_messages.append(
- 'SSL error while sending login information: .*')
- expected_printed_messages.append(
- 'Please check the logs of b10-cmdctl, there may be a '
- 'problem accepting SSL connections, such as a permission '
- 'problem on the server certificate file.'
- )
+ 'Error while sending login information: .*')
self.__check_printed_messages(expected_printed_messages)
# any other exception should be passed through
@@ -457,6 +447,44 @@ class TestConfigCommands(unittest.TestCase):
finally:
self.tool.send_POST = orig_send_POST
+ def test_try_login_calls_cmdctl(self):
+ # Make sure _try_login() makes the right API call to cmdctl.
+ orig_conn = self.tool.conn
+ try:
+ class MyConn:
+ def __init__(self):
+ self.method = None
+ self.url = None
+ self.param = None
+ self.headers = None
+
+ def request(self, method, url, param, headers):
+ self.method = method
+ self.url = url
+ self.param = param
+ self.headers = headers
+
+ def getresponse(self):
+ class MyResponse:
+ def __init__(self):
+ self.status = http.client.OK
+ def read(self):
+ class MyData:
+ def decode(self):
+ return json.dumps(True)
+ return MyData()
+ return MyResponse()
+
+ self.tool.conn = MyConn()
+ self.assertTrue(self.tool._try_login('user32', 'pass64'))
+ self.assertEqual(self.tool.conn.method, 'POST')
+ self.assertEqual(self.tool.conn.url, '/login')
+ self.assertEqual(json.loads(self.tool.conn.param),
+ {"password": "pass64", "username": "user32"})
+ self.assertIn('cookie', self.tool.conn.headers)
+ finally:
+ self.tool.conn = orig_conn
+
def test_run(self):
def login_to_cmdctl():
return True
diff --git a/src/bin/cmdctl/Makefile.am b/src/bin/cmdctl/Makefile.am
index 8cadf89..72a400a 100644
--- a/src/bin/cmdctl/Makefile.am
+++ b/src/bin/cmdctl/Makefile.am
@@ -11,20 +11,18 @@ pylogmessagedir = $(pyexecdir)/isc/log_messages/
b10_cmdctldir = $(pkgdatadir)
-USERSFILES = cmdctl-accounts.csv
CERTFILES = cmdctl-keyfile.pem cmdctl-certfile.pem
b10_cmdctl_DATA = cmdctl.spec
-EXTRA_DIST = $(USERSFILES)
-
CLEANFILES= b10-cmdctl cmdctl.pyc cmdctl.spec
CLEANFILES += $(PYTHON_LOGMSGPKG_DIR)/work/cmdctl_messages.py
CLEANFILES += $(PYTHON_LOGMSGPKG_DIR)/work/cmdctl_messages.pyc
man_MANS = b10-cmdctl.8 b10-certgen.1
DISTCLEANFILES = $(man_MANS) cmdctl-certfile.pem cmdctl-keyfile.pem
-EXTRA_DIST += $(man_MANS) b10-certgen.xml b10-cmdctl.xml cmdctl_messages.mes
+EXTRA_DIST = $(man_MANS) b10-certgen.xml b10-cmdctl.xml cmdctl_messages.mes
+EXTRA_DIST += cmdctl-accounts.csv
if GENERATE_DOCS
diff --git a/src/bin/cmdctl/cmdctl.py.in b/src/bin/cmdctl/cmdctl.py.in
index 457873b..f9670cf 100755
--- a/src/bin/cmdctl/cmdctl.py.in
+++ b/src/bin/cmdctl/cmdctl.py.in
@@ -97,6 +97,11 @@ def check_file(file_name):
class SecureHTTPRequestHandler(http.server.BaseHTTPRequestHandler):
'''https connection request handler.
Currently only GET and POST are supported. '''
+ def __init__(self, request, client_address, server):
+ http.server.BaseHTTPRequestHandler.__init__(self, request,
+ client_address, server)
+ self.session_id = None
+
def do_GET(self):
'''The client should send its session id in header with
the name 'cookie'
@@ -121,7 +126,7 @@ class SecureHTTPRequestHandler(http.server.BaseHTTPRequestHandler):
return self.server.get_reply_data_for_GET(id, module)
def _is_session_valid(self):
- return self.session_id
+ return self.session_id is not None
def _is_user_logged_in(self):
login_time = self.server.user_sessions.get(self.session_id)
@@ -171,7 +176,7 @@ class SecureHTTPRequestHandler(http.server.BaseHTTPRequestHandler):
is_user_valid, error_info = self._check_user_name_and_pwd()
if is_user_valid:
self.server.save_user_session_id(self.session_id)
- return http.client.OK, ["login success "]
+ return http.client.OK, ["login success"]
else:
return http.client.UNAUTHORIZED, error_info
diff --git a/src/bin/cmdctl/tests/Makefile.am b/src/bin/cmdctl/tests/Makefile.am
index 74b801a..f24cf73 100644
--- a/src/bin/cmdctl/tests/Makefile.am
+++ b/src/bin/cmdctl/tests/Makefile.am
@@ -25,8 +25,8 @@ endif
echo Running test: $$pytest ; \
$(LIBRARY_PATH_PLACEHOLDER) \
PYTHONPATH=$(COMMON_PYTHON_PATH):$(abs_top_builddir)/src/bin/cmdctl \
- CMDCTL_BUILD_PATH=$(abs_top_builddir)/src/bin/cmdctl \
CMDCTL_SRC_PATH=$(abs_top_srcdir)/src/bin/cmdctl \
+ CMDCTL_BUILD_PATH=$(abs_top_builddir)/src/bin/cmdctl \
B10_LOCKFILE_DIR_FROM_BUILD=$(abs_top_builddir) \
$(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
done
diff --git a/src/bin/cmdctl/tests/b10-certgen_test.py b/src/bin/cmdctl/tests/b10-certgen_test.py
index d54efa3..56630bc 100644
--- a/src/bin/cmdctl/tests/b10-certgen_test.py
+++ b/src/bin/cmdctl/tests/b10-certgen_test.py
@@ -172,10 +172,7 @@ class TestCertGenTool(unittest.TestCase):
"""
Tests a few pre-created certificates with the -c option
"""
- if ('CMDCTL_SRC_PATH' in os.environ):
- path = os.environ['CMDCTL_SRC_PATH'] + "/tests/testdata/"
- else:
- path = "testdata/"
+ path = os.environ['CMDCTL_SRC_PATH'] + '/tests/testdata/'
self.validate_certificate(10, path + 'expired-certfile.pem')
self.validate_certificate(100, path + 'mangled-certfile.pem')
self.validate_certificate(17, path + 'noca-certfile.pem')
diff --git a/src/bin/cmdctl/tests/cmdctl_test.py b/src/bin/cmdctl/tests/cmdctl_test.py
index ee44f45..82042fe 100644
--- a/src/bin/cmdctl/tests/cmdctl_test.py
+++ b/src/bin/cmdctl/tests/cmdctl_test.py
@@ -33,7 +33,7 @@ BUILD_FILE_PATH = os.environ['CMDCTL_BUILD_PATH'] + os.sep
# Rewrite the class for unittest.
class MySecureHTTPRequestHandler(SecureHTTPRequestHandler):
def __init__(self):
- pass
+ self.session_id = None
def send_response(self, rcode):
self.rcode = rcode
@@ -41,19 +41,6 @@ class MySecureHTTPRequestHandler(SecureHTTPRequestHandler):
def end_headers(self):
pass
- def do_GET(self):
- self.wfile = open('tmp.file', 'wb')
- super().do_GET()
- self.wfile.close()
- os.remove('tmp.file')
-
- def do_POST(self):
- self.wfile = open("tmp.file", 'wb')
- super().do_POST()
- self.wfile.close()
- os.remove('tmp.file')
-
-
class FakeSecureHTTPServer(SecureHTTPServer):
def __init__(self):
self.user_sessions = {}
@@ -93,13 +80,22 @@ class TestSecureHTTPRequestHandler(unittest.TestCase):
self.handler.server.user_sessions = {}
self.handler.server._user_infos = {}
self.handler.headers = {}
- self.handler.rfile = open("check.tmp", 'w+b')
+ self.handler.rfile = open('input.tmp', 'w+b')
+ self.handler.wfile = open('output.tmp', 'w+b')
def tearDown(self):
sys.stdout.close()
sys.stdout = self.old_stdout
+ self.handler.wfile.close()
+ os.remove('output.tmp')
self.handler.rfile.close()
- os.remove('check.tmp')
+ os.remove('input.tmp')
+
+ def test_is_session_valid(self):
+ self.assertIsNone(self.handler.session_id)
+ self.assertFalse(self.handler._is_session_valid())
+ self.handler.session_id = 4234
+ self.assertTrue(self.handler._is_session_valid())
def test_parse_request_path(self):
self.handler.path = ''
@@ -160,7 +156,7 @@ class TestSecureHTTPRequestHandler(unittest.TestCase):
self.handler.do_GET()
self.assertEqual(self.handler.rcode, http.client.OK)
- def test_user_logged_in(self):
+ def test_is_user_logged_in(self):
self.handler.server.user_sessions = {}
self.handler.session_id = 12345
self.assertTrue(self.handler._is_user_logged_in() == False)
@@ -294,6 +290,68 @@ class TestSecureHTTPRequestHandler(unittest.TestCase):
rcode, reply = self.handler._handle_post_request()
self.assertEqual(http.client.BAD_REQUEST, rcode)
+ def test_handle_login(self):
+ orig_is_user_logged_in = self.handler._is_user_logged_in
+ orig_check_user_name_and_pwd = self.handler._check_user_name_and_pwd
+ try:
+ def create_is_user_logged_in(status):
+ '''Create a replacement _is_user_logged_in() method.'''
+ def my_is_user_logged_in():
+ return status
+ return my_is_user_logged_in
+
+ # Check case where _is_user_logged_in() returns True
+ self.handler._is_user_logged_in = create_is_user_logged_in(True)
+ self.handler.headers['cookie'] = 12345
+ self.handler.path = '/login'
+ self.handler.do_POST()
+ self.assertEqual(self.handler.rcode, http.client.OK)
+ self.handler.wfile.seek(0, 0)
+ d = self.handler.wfile.read()
+ self.assertEqual(json.loads(d.decode()),
+ ['user has already login'])
+
+ # Clear the output
+ self.handler.wfile.seek(0, 0)
+ self.handler.wfile.truncate()
+
+ # Check case where _is_user_logged_in() returns False
+ self.handler._is_user_logged_in = create_is_user_logged_in(False)
+
+ def create_check_user_name_and_pwd(status, error_info=None):
+ '''Create a replacement _check_user_name_and_pwd() method.'''
+ def my_check_user_name_and_pwd():
+ return status, error_info
+ return my_check_user_name_and_pwd
+
+ # (a) Check case where _check_user_name_and_pwd() returns
+ # valid user status
+ self.handler._check_user_name_and_pwd = \
+ create_check_user_name_and_pwd(True)
+ self.handler.do_POST()
+ self.assertEqual(self.handler.rcode, http.client.OK)
+ self.handler.wfile.seek(0, 0)
+ d = self.handler.wfile.read()
+ self.assertEqual(json.loads(d.decode()), ['login success'])
+
+ # Clear the output
+ self.handler.wfile.seek(0, 0)
+ self.handler.wfile.truncate()
+
+ # (b) Check case where _check_user_name_and_pwd() returns
+ # invalid user status
+ self.handler._check_user_name_and_pwd = \
+ create_check_user_name_and_pwd(False, ['login failed'])
+ self.handler.do_POST()
+ self.assertEqual(self.handler.rcode, http.client.UNAUTHORIZED)
+ self.handler.wfile.seek(0, 0)
+ d = self.handler.wfile.read()
+ self.assertEqual(json.loads(d.decode()), ['login failed'])
+
+ finally:
+ self.handler._is_user_logged_in = orig_is_user_logged_in
+ self.handler._check_user_name_and_pwd = orig_check_user_name_and_pwd
+
class MyCommandControl(CommandControl):
def _get_modules_specification(self):
return {}
@@ -470,6 +528,12 @@ class TestSecureHTTPServer(unittest.TestCase):
self.assertEqual(1, len(self.server._user_infos))
self.assertTrue('root' in self.server._user_infos)
+ def test_get_user_info(self):
+ self.assertIsNone(self.server.get_user_info('root'))
+ self.server._create_user_info(SRC_FILE_PATH + 'cmdctl-accounts.csv')
+ self.assertIn('6f0c73bd33101a5ec0294b3ca39fec90ef4717fe',
+ self.server.get_user_info('root'))
+
def test_check_file(self):
# Just some file that we know exists
file_name = BUILD_FILE_PATH + 'cmdctl-keyfile.pem'
More information about the bind10-changes
mailing list