fixed the 'status' method of the encrypted_webinterface module
added a method 'create_misc_config_file' to cryptobox.core.settings used this method to create the certificate file improved the description on how to set up an encrypted webinterface connection added description of the 'encrypted_webinterface' plugin to README.ssl moved 'coding_guidelines.txt' to the wiki
This commit is contained in:
parent
4e5b8e088f
commit
2ecc20e905
4 changed files with 93 additions and 60 deletions
47
README.ssl
47
README.ssl
|
@ -4,7 +4,9 @@ This file describes how to encrypt your connection to the CryptoBox webserver.
|
|||
This is highly recommended as the encryption password for your data could be
|
||||
exposed to intruders in your local network otherwise.
|
||||
|
||||
There are several ways for setting up a SSL connection:
|
||||
Below you will find detailed descriptions on how to set up an encrypted
|
||||
connection to the webinterface:
|
||||
- use the plugin "encrypted_webinterface"
|
||||
- run the CryptoBox webserver behind an ssl-enabled webserver
|
||||
- use stunnel to provide an SSL socket
|
||||
- use the a proxy server (e.g. pound)
|
||||
|
@ -17,7 +19,27 @@ need encrypted http connections.
|
|||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
1) CryptoBox behind an ssl-enabled webserver
|
||||
1) using the plugin 'encrypted_webinterface'
|
||||
This plugin is disabled by default. You can enable it in your
|
||||
cryptobox.conf file by removing it from the 'DisabledPlugins' setting.
|
||||
|
||||
The plugin does the following during startup of the CryptoBox:
|
||||
- create a self-signed X.509 certificate if necessary
|
||||
- run stunnel on port 443 (https) with this certificate
|
||||
|
||||
Now you just need to point your browser to the URL of the CryptoBox with
|
||||
'https' instead of 'http' and to accept the certificate permanently
|
||||
(the Internet Explorer is not capable of doing this - use Firefox,
|
||||
Konqueror, Safari, ... instead, if you need this ability). That's it!
|
||||
|
||||
Of course, this will not work, if the port 443 is already in use by
|
||||
another program - in this case, you should better choose one of the
|
||||
other solutions described below.
|
||||
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
2) CryptoBox behind an ssl-enabled webserver
|
||||
Read the documentation of your favourite webserver to learn how to enable
|
||||
ssl encryption.
|
||||
|
||||
|
@ -38,16 +60,16 @@ need encrypted http connections.
|
|||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
2) CryptoBox behind stunnel
|
||||
3) CryptoBox behind stunnel (configured manually)
|
||||
You may want to tunnel the traffic between the cryptobox-server
|
||||
and your browser. "stunnel" is an excellent candidate for this job.
|
||||
|
||||
If you do not have an ssl certificate yet, then you should create
|
||||
one first. On Debian: "apt-get install ssl-cert" and run the following
|
||||
command (replace the <NAMES>; a default CERT_CONF is shipped with the
|
||||
cryptobox-server package):
|
||||
command (the supplied example openssl.conf file resides in the doc
|
||||
directory of the cryptobox-server package):
|
||||
|
||||
make-ssl-cert <CERT_CONF> <CERT_FILE_NAME>
|
||||
make-ssl-cert conf-examples/openssl.conf <CERT_FILE_NAME>
|
||||
|
||||
In case, that you already have a certificate just run this command:
|
||||
|
||||
|
@ -58,9 +80,10 @@ need encrypted http connections.
|
|||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
3) CryptoBox behind a proxy server
|
||||
4) CryptoBox behind a proxy server
|
||||
As there are many proxy servers around, we cannot describe all of them. As
|
||||
an example, we will explain the setup of the load-balancing proxy 'pound'.
|
||||
an example, we will explain the setup of the load-balancing proxy 'pound'
|
||||
(http://www.apsis.ch/pound/).
|
||||
|
||||
Just add the following lines to you /etc/pound/pound.cfg:
|
||||
# Remove the X-SSL-Request header from incoming
|
||||
|
@ -77,13 +100,15 @@ need encrypted http connections.
|
|||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
4) Problems with SSL detection?
|
||||
5) Problems with SSL detection?
|
||||
If the CryptoBox continues to complain about the unencrypted connection, even
|
||||
if it runs behind an ssl-enabled webserver or behind stunnel, then you can do
|
||||
one of the following things:
|
||||
- disable the plugin 'encypted_webinterface' in the cryptobox.conf file
|
||||
if you do not need it
|
||||
- set the request header value "X-SSL-Request" to "1" (the digit 'one')
|
||||
- set the environment setting "HTTPS" to a non-empty value during the
|
||||
startup of the CryptoBox webserver. Maybe /etc/default/cryptobox-server
|
||||
would be the right place for this.
|
||||
startup of the CryptoBox webserver. Maybe
|
||||
/etc/default/cryptobox-server would be the right place for this.
|
||||
- let the CryptoBox webserver listen to port 443
|
||||
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
Maybe we can add some notes here to get a consistent coding experience :)
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
comments:
|
||||
- should be usable for pydoc
|
||||
- ''' or """ at the beginning of every class/method
|
||||
- ## for longterm comments, that are useful for understanding
|
||||
- #blabla for codelines, that are out for experimenting and might be used later again
|
||||
|
||||
error handling:
|
||||
- unspecific error handling is evil (try: "grep -r except: .")
|
||||
|
||||
unit testing:
|
||||
- first write a unittest and then write the relating code until the unittest stops failing :)
|
||||
- 'unittests.ClassName.py' should contain all tests for 'ClassName.py'
|
||||
- commits with broken unit tests are evil (fix or disable the code (not the test ;) ))
|
||||
|
|
@ -69,9 +69,12 @@ class encrypted_webinterface(cryptobox.plugins.base.CryptoBoxPlugin):
|
|||
|
||||
|
||||
def get_status(self):
|
||||
"""Retrieve the status of the feature.
|
||||
"""Retrieve the current state of the webinterface connection
|
||||
"""
|
||||
return "TODO"
|
||||
if self.__is_encrypted():
|
||||
return "1"
|
||||
else:
|
||||
return "0"
|
||||
|
||||
|
||||
def get_warnings(self):
|
||||
|
@ -85,21 +88,32 @@ class encrypted_webinterface(cryptobox.plugins.base.CryptoBoxPlugin):
|
|||
warnings.append((45, "Plugins.%s.MissingModuleM2Crypto" % self.get_name()))
|
||||
if not os.path.isfile(self.root_action.STUNNEL_BIN):
|
||||
warnings.append((44, "Plugins.%s.MissingProgramStunnel" % self.get_name()))
|
||||
## perform some checks for encrypted connections
|
||||
## check an environment setting - this is quite common behind proxies
|
||||
## check if it is a local connection (or via stunnel)
|
||||
## the arbitrarily chosen header is documented in README.proxy
|
||||
if (cherrypy.request.scheme != "https") \
|
||||
and (not os.environ.has_key("HTTPS")) \
|
||||
and (not (cherrypy.request.headers.has_key("Remote-Host") \
|
||||
and (cherrypy.request.headers["Remote-Host"] == "127.0.0.1"))) \
|
||||
and (not (cherrypy.request.headers.has_key("X-SSL-Request") \
|
||||
and (cherrypy.request.headers["X-SSL-Request"] == "1"))):
|
||||
if not self.__is_encrypted():
|
||||
## plaintext connection -> "heavy security risk" (priority=20..39)
|
||||
warnings.append((25, "Plugins.%s.NoSSL" % self.get_name()))
|
||||
return warnings
|
||||
|
||||
|
||||
def __is_encrypted(self):
|
||||
"""perform some checks for encrypted connections
|
||||
"""
|
||||
if cherrypy.request.scheme == "https":
|
||||
return True
|
||||
## check an environment setting - this is quite common behind proxies
|
||||
if os.environ.has_key("HTTPS"):
|
||||
return True
|
||||
## check if it is a local connection (or via stunnel)
|
||||
if cherrypy.request.headers.has_key("Remote-Host") \
|
||||
and (cherrypy.request.headers["Remote-Host"] == "127.0.0.1"):
|
||||
return True
|
||||
## the arbitrarily chosen header is documented in README.proxy
|
||||
if cherrypy.request.headers.has_key("X-SSL-Request") \
|
||||
and (cherrypy.request.headers["X-SSL-Request"] == "1"):
|
||||
return True
|
||||
## it looks like a plain connection
|
||||
return False
|
||||
|
||||
|
||||
def handle_event(self, event, event_info=None):
|
||||
"""Create a certificate during startup (if it does not exist) and run stunnel
|
||||
"""
|
||||
|
@ -107,12 +121,14 @@ class encrypted_webinterface(cryptobox.plugins.base.CryptoBoxPlugin):
|
|||
cert_abs_name = self.cbox.prefs.get_misc_config_filename(CERT_FILENAME)
|
||||
if not os.path.isfile(cert_abs_name):
|
||||
try:
|
||||
self.__create_certificate(cert_abs_name)
|
||||
self.cbox.log.info("Created new SSL certificate: %s" % cert_abs_name)
|
||||
cert = self.__get_certificate()
|
||||
self.cbox.prefs.create_misc_config_file(CERT_FILENAME, cert)
|
||||
self.cbox.log.info("Created new SSL certificate: %s" % \
|
||||
cert_abs_name)
|
||||
except IOError, err_msg:
|
||||
## do not run stunnel without a certificate
|
||||
self.cbox.log.warn("Failed to create new SSL certificate (%s): %s" % \
|
||||
(cert_abs_name, err_msg))
|
||||
self.cbox.log.warn("Failed to create new SSL certificate (%s): %s" \
|
||||
% (cert_abs_name, err_msg))
|
||||
return
|
||||
self.__run_stunnel(cert_abs_name)
|
||||
elif event == "shutdown":
|
||||
|
@ -181,8 +197,8 @@ class encrypted_webinterface(cryptobox.plugins.base.CryptoBoxPlugin):
|
|||
return False
|
||||
|
||||
|
||||
def __create_certificate(self, filename):
|
||||
"""Create a self-signed certificate and store it in a file
|
||||
def __get_certificate(self):
|
||||
"""Create a self-signed certificate and return its pem content
|
||||
|
||||
The code is mainly inspired by:
|
||||
https://dev.tribler.org/browser/m2crypto/trunk/contrib/SimpleX509create.py
|
||||
|
@ -226,17 +242,5 @@ class encrypted_webinterface(cryptobox.plugins.base.CryptoBoxPlugin):
|
|||
result = ""
|
||||
result += cert.as_pem()
|
||||
result += pkey.as_pem(cipher=None)
|
||||
if not os.path.exists(os.path.dirname(filename)):
|
||||
os.mkdir(os.path.dirname(filename))
|
||||
try:
|
||||
certfile = open(filename, "w")
|
||||
except IOError:
|
||||
raise
|
||||
try:
|
||||
certfile.write(result)
|
||||
except IOError:
|
||||
certfile.close()
|
||||
raise
|
||||
certfile.close()
|
||||
os.chmod(filename, 0600)
|
||||
return result
|
||||
|
||||
|
|
|
@ -100,6 +100,28 @@ class CryptoBoxSettings:
|
|||
'name' should not contain slashes (no directory part!)
|
||||
"""
|
||||
return os.path.join(self.prefs["Locations"]["SettingsDir"], "misc", name)
|
||||
|
||||
|
||||
def create_misc_config_file(self, name, content):
|
||||
"""Create a new configuration file in the 'settings' directory
|
||||
|
||||
"name" should be the basename (without a directory)
|
||||
"content" will be directly written to the file
|
||||
this method may throw an IOException
|
||||
"""
|
||||
misc_conf_file = self.get_misc_config_filename(name)
|
||||
misc_conf_dir = os.path.dirname(misc_conf_file)
|
||||
if not os.path.isdir(misc_conf_dir):
|
||||
os.mkdir(misc_conf_dir)
|
||||
cfile = open(misc_conf_file, "w")
|
||||
try:
|
||||
cfile.write(content)
|
||||
except IOError:
|
||||
cfile.close()
|
||||
raise
|
||||
cfile.close()
|
||||
## reread all misc files automatically - this should be ok
|
||||
self.reload_misc_files()
|
||||
|
||||
|
||||
def requires_partition(self):
|
||||
|
|
Loading…
Add table
Reference in a new issue