[Freeipa-devel] [freeipa PR#396][synchronized] Explicitly remove support of SSLv2

2017-02-16 Thread stlaz
   URL: https://github.com/freeipa/freeipa/pull/396
Author: stlaz
 Title: #396: Explicitly remove support of SSLv2
Action: synchronized

To pull the PR as Git branch:
git remote add ghfreeipa https://github.com/freeipa/freeipa
git fetch ghfreeipa pull/396/head:pr396
git checkout pr396
From 661ed55292dda18f1f09f89af883086f9b5a7ab0 Mon Sep 17 00:00:00 2001
From: Stanislav Laznicka 
Date: Fri, 13 Jan 2017 12:31:29 +0100
Subject: [PATCH] Explicitly remove support of SSLv2/3

It was possible to set tls_version_min/max to 'ssl2' or 'ssl3',
even though newer versions of NSS will fail to set this as a valid
TLS version. This patch explicitly checks for deprecated TLS versions
prior to creating a TLS connection.

Also, we don't allow tls_version_min/max to be set to a random
string anymore.

https://fedorahosted.org/freeipa/ticket/6607
---
 ipalib/config.py| 27 ++--
 ipalib/constants.py | 10 +
 ipapython/nsslib.py | 61 +++--
 3 files changed, 94 insertions(+), 4 deletions(-)

diff --git a/ipalib/config.py b/ipalib/config.py
index 20591db..1a59879 100644
--- a/ipalib/config.py
+++ b/ipalib/config.py
@@ -41,8 +41,11 @@
 
 from ipapython.dn import DN
 from ipalib.base import check_name
-from ipalib.constants import CONFIG_SECTION
-from ipalib.constants import OVERRIDE_ERROR, SET_ERROR, DEL_ERROR
+from ipalib.constants import (
+CONFIG_SECTION,
+OVERRIDE_ERROR, SET_ERROR, DEL_ERROR,
+TLS_VERSIONS
+)
 from ipalib import errors
 
 if six.PY3:
@@ -578,6 +581,26 @@ def _finalize_core(self, **defaults):
 
 self._merge(**defaults)
 
+# set the best known TLS version if min/max versions are not set
+if 'tls_version_min' not in self:
+self.tls_version_min = TLS_VERSIONS[-1]
+elif self.tls_version_min not in TLS_VERSIONS:
+raise errors.EnvironmentError(
+"Unknown TLS version '{ver}' set in tls_version_min."
+.format(ver=self.tls_version_min))
+
+if 'tls_version_max' not in self:
+self.tls_version_max = TLS_VERSIONS[-1]
+elif self.tls_version_max not in TLS_VERSIONS:
+raise errors.EnvironmentError(
+"Unknown TLS version '{ver}' set in tls_version_max."
+.format(ver=self.tls_version_max))
+
+if self.tls_version_max < self.tls_version_min:
+raise errors.EnvironmentError(
+"tls_version_min is set to a higher TLS version than "
+"tls_version_max.")
+
 def _finalize(self, **lastchance):
 """
 Finalize and lock environment.
diff --git a/ipalib/constants.py b/ipalib/constants.py
index fa20624..e64324f 100644
--- a/ipalib/constants.py
+++ b/ipalib/constants.py
@@ -283,3 +283,13 @@
 # IPA API Framework user
 IPAAPI_USER = 'ipaapi'
 IPAAPI_GROUP = 'ipaapi'
+
+# TLS related constants
+TLS_VERSIONS = [
+"ssl2",
+"ssl3",
+"tls1.0",
+"tls1.1",
+"tls1.2"
+]
+TLS_VERSION_MINIMAL = "tls1.0"
diff --git a/ipapython/nsslib.py b/ipapython/nsslib.py
index 08d05fc..97bbf64 100644
--- a/ipapython/nsslib.py
+++ b/ipapython/nsslib.py
@@ -23,6 +23,8 @@
 import getpass
 import socket
 from ipapython.ipa_log_manager import root_logger
+from ipapython.ipa_log_manager import log_mgr
+from ipalib.constants import TLS_VERSIONS, TLS_VERSION_MINIMAL
 
 from nss.error import NSPRError
 import nss.io as io
@@ -38,6 +40,9 @@
 # pylint: disable=import-error
 import http.client as httplib
 
+# get a logger for this module
+logger = log_mgr.get_logger(__name__)
+
 # NSS database currently open
 current_dbdir = None
 
@@ -129,6 +134,56 @@ def client_auth_data_callback(ca_names, chosen_nickname, password, certdb):
 socket.AF_UNSPEC: io.PR_AF_UNSPEC
 }
 
+
+def get_proper_tls_version_span(tls_version_min, tls_version_max):
+"""
+This function checks whether the given TLS versions are known in FreeIPA
+and that these versions fulfill the requirements for minimal TLS version
+(see `ipalib.constants: TLS_VERSIONS, TLS_VERSION_MINIMAL`).
+
+:param tls_version_min:
+the lower value in the TLS min-max span, raised to the lowest allowed
+value if too low
+:param tls_version_max:
+the higher value in the TLS min-max span, raised to tls_version_min
+if lower than TLS_VERSION_MINIMAL
+:raises: ValueError
+"""
+min_allowed_idx = TLS_VERSIONS.index(TLS_VERSION_MINIMAL)
+
+try:
+min_version_idx = TLS_VERSIONS.index(tls_version_min)
+except ValueError:
+raise ValueError("tls_version_min ('{val}') is not a known "
+ "TLS version.".format(val=tls_version_min))
+
+try:
+max_version_idx = TLS_VERSIONS.index(tls_version_max)
+except ValueError:
+raise ValueError("tls_version_max ('{val}') is not a known "
+ "TLS version.".format(val=tls_version_max))
+
+

[Freeipa-devel] [freeipa PR#396][synchronized] Explicitly remove support of SSLv2

2017-02-15 Thread stlaz
   URL: https://github.com/freeipa/freeipa/pull/396
Author: stlaz
 Title: #396: Explicitly remove support of SSLv2
Action: synchronized

To pull the PR as Git branch:
git remote add ghfreeipa https://github.com/freeipa/freeipa
git fetch ghfreeipa pull/396/head:pr396
git checkout pr396
From b5bea925775bd07e867ac79db9287d06faa0189b Mon Sep 17 00:00:00 2001
From: Stanislav Laznicka 
Date: Fri, 13 Jan 2017 12:31:29 +0100
Subject: [PATCH] Explicitly remove support of SSLv2

It was possible to set tls_version_min/max to 'ssl2', even though
newer versions of NSS will fail to set this as a valid TLS version.
This patch explicitly checks for deprecated TLS versions prior to
creating a TLS connection.

Also, we don't allow tls_version_min/max to be set to a random
string anymore.

https://fedorahosted.org/freeipa/ticket/6607
---
 ipalib/config.py| 27 ++--
 ipalib/constants.py | 10 +
 ipapython/nsslib.py | 60 +++--
 3 files changed, 93 insertions(+), 4 deletions(-)

diff --git a/ipalib/config.py b/ipalib/config.py
index 20591db..1a59879 100644
--- a/ipalib/config.py
+++ b/ipalib/config.py
@@ -41,8 +41,11 @@
 
 from ipapython.dn import DN
 from ipalib.base import check_name
-from ipalib.constants import CONFIG_SECTION
-from ipalib.constants import OVERRIDE_ERROR, SET_ERROR, DEL_ERROR
+from ipalib.constants import (
+CONFIG_SECTION,
+OVERRIDE_ERROR, SET_ERROR, DEL_ERROR,
+TLS_VERSIONS
+)
 from ipalib import errors
 
 if six.PY3:
@@ -578,6 +581,26 @@ def _finalize_core(self, **defaults):
 
 self._merge(**defaults)
 
+# set the best known TLS version if min/max versions are not set
+if 'tls_version_min' not in self:
+self.tls_version_min = TLS_VERSIONS[-1]
+elif self.tls_version_min not in TLS_VERSIONS:
+raise errors.EnvironmentError(
+"Unknown TLS version '{ver}' set in tls_version_min."
+.format(ver=self.tls_version_min))
+
+if 'tls_version_max' not in self:
+self.tls_version_max = TLS_VERSIONS[-1]
+elif self.tls_version_max not in TLS_VERSIONS:
+raise errors.EnvironmentError(
+"Unknown TLS version '{ver}' set in tls_version_max."
+.format(ver=self.tls_version_max))
+
+if self.tls_version_max < self.tls_version_min:
+raise errors.EnvironmentError(
+"tls_version_min is set to a higher TLS version than "
+"tls_version_max.")
+
 def _finalize(self, **lastchance):
 """
 Finalize and lock environment.
diff --git a/ipalib/constants.py b/ipalib/constants.py
index fa20624..e64324f 100644
--- a/ipalib/constants.py
+++ b/ipalib/constants.py
@@ -283,3 +283,13 @@
 # IPA API Framework user
 IPAAPI_USER = 'ipaapi'
 IPAAPI_GROUP = 'ipaapi'
+
+# TLS related constants
+TLS_VERSIONS = [
+"ssl2",
+"ssl3",
+"tls1.0",
+"tls1.1",
+"tls1.2"
+]
+TLS_VERSION_MINIMAL = "tls1.0"
diff --git a/ipapython/nsslib.py b/ipapython/nsslib.py
index 08d05fc..8b02f4b 100644
--- a/ipapython/nsslib.py
+++ b/ipapython/nsslib.py
@@ -23,6 +23,8 @@
 import getpass
 import socket
 from ipapython.ipa_log_manager import root_logger
+from ipapython.ipa_log_manager import log_mgr
+from ipalib.constants import TLS_VERSIONS, TLS_VERSION_MINIMAL
 
 from nss.error import NSPRError
 import nss.io as io
@@ -38,6 +40,9 @@
 # pylint: disable=import-error
 import http.client as httplib
 
+# get a logger for this module
+logger = log_mgr.get_logger(__name__)
+
 # NSS database currently open
 current_dbdir = None
 
@@ -129,6 +134,55 @@ def client_auth_data_callback(ca_names, chosen_nickname, password, certdb):
 socket.AF_UNSPEC: io.PR_AF_UNSPEC
 }
 
+
+def get_proper_tls_version_span(tls_version_min, tls_version_max):
+"""
+This function checks whether the given TLS versions are known in FreeIPA
+and that these versions fulfill the requirements for minimal TLS version
+(see `ipalib.constants: TLS_VERSIONS, TLS_VERSION_MINIMAL`).
+
+:param tls_version_min:
+the lower value in the TLS min-max span, raised to the lowest allowed
+value if too low
+:param tls_version_max:
+the higher value in the TLS min-max span, raised to tls_version_min
+if lower than TLS_VERSION_MINIMAL
+"""
+min_allowed_idx = TLS_VERSIONS.index(TLS_VERSION_MINIMAL)
+
+try:
+min_version_idx = TLS_VERSIONS.index(tls_version_min)
+except ValueError:
+raise ValueError("tls_version_min ('{val}') is not a known "
+ "TLS version.".format(val=tls_version_min))
+
+try:
+max_version_idx = TLS_VERSIONS.index(tls_version_max)
+except ValueError:
+raise ValueError("tls_version_max ('{val}') is not a known "
+ "TLS version.".format(val=tls_version_max))
+
+if min_version_idx > max_version_idx:

[Freeipa-devel] [freeipa PR#396][synchronized] Explicitly remove support of SSLv2

2017-02-14 Thread stlaz
   URL: https://github.com/freeipa/freeipa/pull/396
Author: stlaz
 Title: #396: Explicitly remove support of SSLv2
Action: synchronized

To pull the PR as Git branch:
git remote add ghfreeipa https://github.com/freeipa/freeipa
git fetch ghfreeipa pull/396/head:pr396
git checkout pr396
From 53aebe8ea2663dc6c57730e797f1e0b06a0b3b69 Mon Sep 17 00:00:00 2001
From: Stanislav Laznicka 
Date: Fri, 13 Jan 2017 12:31:29 +0100
Subject: [PATCH] Explicitly remove support of SSLv2

It was possible to set tls_version_min/max to 'ssl2', even though
newer versions of NSS will fail to set this as a valid TLS version.
This patch explicitly checks for deprecated TLS versions prior to
creating a TLS connection.

Also, we don't allow tls_version_min/max to be set to a random
string anymore.

https://fedorahosted.org/freeipa/ticket/6607
---
 ipalib/config.py| 27 ++--
 ipalib/constants.py | 10 +
 ipapython/nsslib.py | 60 +++--
 3 files changed, 93 insertions(+), 4 deletions(-)

diff --git a/ipalib/config.py b/ipalib/config.py
index 20591db..1a59879 100644
--- a/ipalib/config.py
+++ b/ipalib/config.py
@@ -41,8 +41,11 @@
 
 from ipapython.dn import DN
 from ipalib.base import check_name
-from ipalib.constants import CONFIG_SECTION
-from ipalib.constants import OVERRIDE_ERROR, SET_ERROR, DEL_ERROR
+from ipalib.constants import (
+CONFIG_SECTION,
+OVERRIDE_ERROR, SET_ERROR, DEL_ERROR,
+TLS_VERSIONS
+)
 from ipalib import errors
 
 if six.PY3:
@@ -578,6 +581,26 @@ def _finalize_core(self, **defaults):
 
 self._merge(**defaults)
 
+# set the best known TLS version if min/max versions are not set
+if 'tls_version_min' not in self:
+self.tls_version_min = TLS_VERSIONS[-1]
+elif self.tls_version_min not in TLS_VERSIONS:
+raise errors.EnvironmentError(
+"Unknown TLS version '{ver}' set in tls_version_min."
+.format(ver=self.tls_version_min))
+
+if 'tls_version_max' not in self:
+self.tls_version_max = TLS_VERSIONS[-1]
+elif self.tls_version_max not in TLS_VERSIONS:
+raise errors.EnvironmentError(
+"Unknown TLS version '{ver}' set in tls_version_max."
+.format(ver=self.tls_version_max))
+
+if self.tls_version_max < self.tls_version_min:
+raise errors.EnvironmentError(
+"tls_version_min is set to a higher TLS version than "
+"tls_version_max.")
+
 def _finalize(self, **lastchance):
 """
 Finalize and lock environment.
diff --git a/ipalib/constants.py b/ipalib/constants.py
index 81643da..1e8f51a 100644
--- a/ipalib/constants.py
+++ b/ipalib/constants.py
@@ -276,3 +276,13 @@
 
 # regexp definitions
 PATTERN_GROUPUSER_NAME = '^[a-zA-Z0-9_.][a-zA-Z0-9_.-]*[a-zA-Z0-9_.$-]?$'
+
+# TLS related constants
+TLS_VERSIONS = [
+"ssl2",
+"ssl3",
+"tls1.0",
+"tls1.1",
+"tls1.2"
+]
+TLS_VERSION_MINIMAL = "tls1.0"
diff --git a/ipapython/nsslib.py b/ipapython/nsslib.py
index 08d05fc..8b02f4b 100644
--- a/ipapython/nsslib.py
+++ b/ipapython/nsslib.py
@@ -23,6 +23,8 @@
 import getpass
 import socket
 from ipapython.ipa_log_manager import root_logger
+from ipapython.ipa_log_manager import log_mgr
+from ipalib.constants import TLS_VERSIONS, TLS_VERSION_MINIMAL
 
 from nss.error import NSPRError
 import nss.io as io
@@ -38,6 +40,9 @@
 # pylint: disable=import-error
 import http.client as httplib
 
+# get a logger for this module
+logger = log_mgr.get_logger(__name__)
+
 # NSS database currently open
 current_dbdir = None
 
@@ -129,6 +134,55 @@ def client_auth_data_callback(ca_names, chosen_nickname, password, certdb):
 socket.AF_UNSPEC: io.PR_AF_UNSPEC
 }
 
+
+def get_proper_tls_version_span(tls_version_min, tls_version_max):
+"""
+This function checks whether the given TLS versions are known in FreeIPA
+and that these versions fulfill the requirements for minimal TLS version
+(see `ipalib.constants: TLS_VERSIONS, TLS_VERSION_MINIMAL`).
+
+:param tls_version_min:
+the lower value in the TLS min-max span, raised to the lowest allowed
+value if too low
+:param tls_version_max:
+the higher value in the TLS min-max span, raised to tls_version_min
+if lower than TLS_VERSION_MINIMAL
+"""
+min_allowed_idx = TLS_VERSIONS.index(TLS_VERSION_MINIMAL)
+
+try:
+min_version_idx = TLS_VERSIONS.index(tls_version_min)
+except ValueError:
+raise ValueError("tls_version_min ('{val}') is not a known "
+ "TLS version.".format(val=tls_version_min))
+
+try:
+max_version_idx = TLS_VERSIONS.index(tls_version_max)
+except ValueError:
+raise ValueError("tls_version_max ('{val}') is not a known "
+ "TLS version.".format(val=tls_version_max))
+
+if 

[Freeipa-devel] [freeipa PR#396][synchronized] Explicitly remove support of SSLv2

2017-02-07 Thread stlaz
   URL: https://github.com/freeipa/freeipa/pull/396
Author: stlaz
 Title: #396: Explicitly remove support of SSLv2
Action: synchronized

To pull the PR as Git branch:
git remote add ghfreeipa https://github.com/freeipa/freeipa
git fetch ghfreeipa pull/396/head:pr396
git checkout pr396
From 2761cbf779c97fd590913c21e753e673236d3378 Mon Sep 17 00:00:00 2001
From: Stanislav Laznicka 
Date: Fri, 13 Jan 2017 12:31:29 +0100
Subject: [PATCH] Explicitly remove support of SSLv2

It was possible to set tls_version_min/max to 'ssl2', even though
newer versions of NSS will fail to set this as a valid TLS version.
This patch explicitly checks for deprecated TLS versions prior to
creating a TLS connection.

Also, we don't allow tls_version_min/max to be set to a random
string anymore.

https://fedorahosted.org/freeipa/ticket/6607
---
 ipalib/config.py| 22 ++--
 ipalib/constants.py | 10 +
 ipapython/nsslib.py | 59 +++--
 3 files changed, 87 insertions(+), 4 deletions(-)

diff --git a/ipalib/config.py b/ipalib/config.py
index 20591db..f717732 100644
--- a/ipalib/config.py
+++ b/ipalib/config.py
@@ -41,8 +41,11 @@
 
 from ipapython.dn import DN
 from ipalib.base import check_name
-from ipalib.constants import CONFIG_SECTION
-from ipalib.constants import OVERRIDE_ERROR, SET_ERROR, DEL_ERROR
+from ipalib.constants import (
+CONFIG_SECTION,
+OVERRIDE_ERROR, SET_ERROR, DEL_ERROR,
+TLS_VERSIONS
+)
 from ipalib import errors
 
 if six.PY3:
@@ -578,6 +581,21 @@ def _finalize_core(self, **defaults):
 
 self._merge(**defaults)
 
+# set the best known TLS version if min/max versions are not set
+if 'tls_version_min' not in self:
+self.tls_version_min = TLS_VERSIONS[-1]
+elif self.tls_version_min not in TLS_VERSIONS:
+raise errors.EnvironmentError(
+"Unknown TLS version '{ver}' set in tls_version_min."
+.format(ver=self.tls_version_min))
+
+if 'tls_version_max' not in self:
+self.tls_version_max = TLS_VERSIONS[-1]
+elif self.tls_version_max not in TLS_VERSIONS:
+raise errors.EnvironmentError(
+"Unknown TLS version '{ver}' set in tls_version_max."
+.format(ver=self.tls_version_max))
+
 def _finalize(self, **lastchance):
 """
 Finalize and lock environment.
diff --git a/ipalib/constants.py b/ipalib/constants.py
index 81643da..1e8f51a 100644
--- a/ipalib/constants.py
+++ b/ipalib/constants.py
@@ -276,3 +276,13 @@
 
 # regexp definitions
 PATTERN_GROUPUSER_NAME = '^[a-zA-Z0-9_.][a-zA-Z0-9_.-]*[a-zA-Z0-9_.$-]?$'
+
+# TLS related constants
+TLS_VERSIONS = [
+"ssl2",
+"ssl3",
+"tls1.0",
+"tls1.1",
+"tls1.2"
+]
+TLS_VERSION_MINIMAL = "tls1.0"
diff --git a/ipapython/nsslib.py b/ipapython/nsslib.py
index 08d05fc..ce3e5f6 100644
--- a/ipapython/nsslib.py
+++ b/ipapython/nsslib.py
@@ -23,6 +23,8 @@
 import getpass
 import socket
 from ipapython.ipa_log_manager import root_logger
+from ipapython.ipa_log_manager import log_mgr
+from ipalib.constants import TLS_VERSIONS, TLS_VERSION_MINIMAL
 
 from nss.error import NSPRError
 import nss.io as io
@@ -129,6 +131,57 @@ def client_auth_data_callback(ca_names, chosen_nickname, password, certdb):
 socket.AF_UNSPEC: io.PR_AF_UNSPEC
 }
 
+
+def get_proper_tls_version_span(tls_version_min, tls_version_max):
+"""
+This function checks whether the given TLS versions are known in FreeIPA
+and that these versions fulfill the requirements for minimal TLS version
+(see `ipalib.constants: TLS_VERSIONS, TLS_VERSION_MINIMAL`).
+
+:param tls_version_min:
+the lower value in the TLS min-max span, raised to the lowest allowed
+value if too low
+:param tls_version_max:
+the higher value in the TLS min-max span, raised to tls_version_min
+if lower than TLS_VERSION_MINIMAL
+"""
+logger = log_mgr.get_logger(__name__)
+
+min_allowed_idx = TLS_VERSIONS.index(TLS_VERSION_MINIMAL)
+
+try:
+min_version_idx = TLS_VERSIONS.index(tls_version_min)
+except ValueError:
+raise RuntimeError("tls_version_min ('{val}') is not a known "
+   "TLS version.".format(val=tls_version_min))
+
+try:
+max_version_idx = TLS_VERSIONS.index(tls_version_max)
+except ValueError:
+raise RuntimeError("tls_version_max ('{val}') is not a known "
+   "TLS version.".format(val=tls_version_max))
+
+if min_version_idx > max_version_idx:
+raise RuntimeError("tls_version_min is higher than "
+   "tls_version_max.")
+
+if min_version_idx < min_allowed_idx:
+min_version_idx = min_allowed_idx
+logger.warning("tls_version_min set too low ('{old}'),"
+   "using '{new}' instead"
+   

[Freeipa-devel] [freeipa PR#396][synchronized] Explicitly remove support of SSLv2

2017-02-07 Thread stlaz
   URL: https://github.com/freeipa/freeipa/pull/396
Author: stlaz
 Title: #396: Explicitly remove support of SSLv2
Action: synchronized

To pull the PR as Git branch:
git remote add ghfreeipa https://github.com/freeipa/freeipa
git fetch ghfreeipa pull/396/head:pr396
git checkout pr396
From c59b2aef542d4a394283703d24718399af0d5d30 Mon Sep 17 00:00:00 2001
From: Stanislav Laznicka 
Date: Fri, 13 Jan 2017 12:31:29 +0100
Subject: [PATCH] Explicitly remove support of SSLv2

It was possible to set tls_version_min/max to 'ssl2', even though
newer versions of NSS will fail to set this as a valid TLS version.
This patch explicitly checks for deprecated TLS versions prior to
creating a TLS connection.

Also, we don't allow tls_version_min/max to be set to a random
string anymore.

https://fedorahosted.org/freeipa/ticket/6607
---
 ipalib/config.py| 22 --
 ipalib/constants.py | 10 ++
 ipapython/nsslib.py | 46 --
 3 files changed, 74 insertions(+), 4 deletions(-)

diff --git a/ipalib/config.py b/ipalib/config.py
index 20591db..f717732 100644
--- a/ipalib/config.py
+++ b/ipalib/config.py
@@ -41,8 +41,11 @@
 
 from ipapython.dn import DN
 from ipalib.base import check_name
-from ipalib.constants import CONFIG_SECTION
-from ipalib.constants import OVERRIDE_ERROR, SET_ERROR, DEL_ERROR
+from ipalib.constants import (
+CONFIG_SECTION,
+OVERRIDE_ERROR, SET_ERROR, DEL_ERROR,
+TLS_VERSIONS
+)
 from ipalib import errors
 
 if six.PY3:
@@ -578,6 +581,21 @@ def _finalize_core(self, **defaults):
 
 self._merge(**defaults)
 
+# set the best known TLS version if min/max versions are not set
+if 'tls_version_min' not in self:
+self.tls_version_min = TLS_VERSIONS[-1]
+elif self.tls_version_min not in TLS_VERSIONS:
+raise errors.EnvironmentError(
+"Unknown TLS version '{ver}' set in tls_version_min."
+.format(ver=self.tls_version_min))
+
+if 'tls_version_max' not in self:
+self.tls_version_max = TLS_VERSIONS[-1]
+elif self.tls_version_max not in TLS_VERSIONS:
+raise errors.EnvironmentError(
+"Unknown TLS version '{ver}' set in tls_version_max."
+.format(ver=self.tls_version_max))
+
 def _finalize(self, **lastchance):
 """
 Finalize and lock environment.
diff --git a/ipalib/constants.py b/ipalib/constants.py
index 81643da..1e8f51a 100644
--- a/ipalib/constants.py
+++ b/ipalib/constants.py
@@ -276,3 +276,13 @@
 
 # regexp definitions
 PATTERN_GROUPUSER_NAME = '^[a-zA-Z0-9_.][a-zA-Z0-9_.-]*[a-zA-Z0-9_.$-]?$'
+
+# TLS related constants
+TLS_VERSIONS = [
+"ssl2",
+"ssl3",
+"tls1.0",
+"tls1.1",
+"tls1.2"
+]
+TLS_VERSION_MINIMAL = "tls1.0"
diff --git a/ipapython/nsslib.py b/ipapython/nsslib.py
index 08d05fc..9f8fd3c 100644
--- a/ipapython/nsslib.py
+++ b/ipapython/nsslib.py
@@ -23,6 +23,7 @@
 import getpass
 import socket
 from ipapython.ipa_log_manager import root_logger
+from ipalib.constants import TLS_VERSIONS, TLS_VERSION_MINIMAL
 
 from nss.error import NSPRError
 import nss.io as io
@@ -129,6 +130,45 @@ def client_auth_data_callback(ca_names, chosen_nickname, password, certdb):
 socket.AF_UNSPEC: io.PR_AF_UNSPEC
 }
 
+
+def get_proper_tls_version_span(tls_version_min, tls_version_max):
+# every tls version from `tls_versions` prior to min_allowed_idx
+# is deprecated in IPA
+min_allowed_idx = TLS_VERSIONS.index(TLS_VERSION_MINIMAL)
+
+try:
+min_version_idx = TLS_VERSIONS.index(tls_version_min)
+except ValueError:
+raise RuntimeError("tls_version_min ('{val}') is not a known "
+   "TLS version.".format(val=tls_version_min))
+
+try:
+max_version_idx = TLS_VERSIONS.index(tls_version_max)
+except ValueError:
+raise RuntimeError("tls_version_max ('{val}') is not a known "
+   "TLS version.".format(val=tls_version_max))
+
+if min_version_idx > max_version_idx:
+raise RuntimeError("tls_version_min is higher than "
+   "tls_version_max.")
+
+if min_version_idx < min_allowed_idx:
+min_version_idx = min_allowed_idx
+root_logger.warning("tls_version_min set too low ('{old}'),"
+"using '{new}' instead"
+.format(old=tls_version_min,
+new=TLS_VERSIONS[min_version_idx]))
+
+if max_version_idx < min_allowed_idx:
+max_version_idx = min_version_idx
+root_logger.warning("tls_version_max set too low ('{old}'),"
+"using '{new}' instead"
+.format(old=tls_version_max,
+new=TLS_VERSIONS[max_version_idx]))
+
+return TLS_VERSIONS[min_version_idx:max_version_idx+1]
+
+
 class 

[Freeipa-devel] [freeipa PR#396][synchronized] Explicitly remove support of SSLv2

2017-02-07 Thread stlaz
   URL: https://github.com/freeipa/freeipa/pull/396
Author: stlaz
 Title: #396: Explicitly remove support of SSLv2
Action: synchronized

To pull the PR as Git branch:
git remote add ghfreeipa https://github.com/freeipa/freeipa
git fetch ghfreeipa pull/396/head:pr396
git checkout pr396
From db2b762293815c1263b3ce9390f564fe9e611735 Mon Sep 17 00:00:00 2001
From: Stanislav Laznicka 
Date: Fri, 13 Jan 2017 12:31:29 +0100
Subject: [PATCH] Explicitly remove support of SSLv2

It was possible to set tls_version_min/max to 'ssl2', even though
newer versions of NSS will fail to set this as a valid TLS version.
This patch explicitly checks for deprecated TLS versions prior to
creating a TLS connection.

Also, we don't allow tls_version_min/max to be set to a random
string anymore.

https://fedorahosted.org/freeipa/ticket/6607
---
 ipalib/config.py| 19 +--
 ipalib/constants.py | 10 ++
 ipapython/nsslib.py | 46 --
 3 files changed, 71 insertions(+), 4 deletions(-)

diff --git a/ipalib/config.py b/ipalib/config.py
index 20591db..79f7a82 100644
--- a/ipalib/config.py
+++ b/ipalib/config.py
@@ -41,8 +41,11 @@
 
 from ipapython.dn import DN
 from ipalib.base import check_name
-from ipalib.constants import CONFIG_SECTION
-from ipalib.constants import OVERRIDE_ERROR, SET_ERROR, DEL_ERROR
+from ipalib.constants import (
+CONFIG_SECTION,
+OVERRIDE_ERROR, SET_ERROR, DEL_ERROR,
+TLS_VERSIONS
+)
 from ipalib import errors
 
 if six.PY3:
@@ -497,6 +500,7 @@ def _bootstrap(self, **overrides):
 if 'plugins_on_demand' not in self:
 self.plugins_on_demand = (self.context == 'cli')
 
+
 def _finalize_core(self, **defaults):
 """
 Complete initialization of standard IPA environment.
@@ -578,6 +582,17 @@ def _finalize_core(self, **defaults):
 
 self._merge(**defaults)
 
+if self.tls_version_min not in TLS_VERSIONS:
+raise errors.EnvironmentError(
+"Unknown TLS version '{ver}' set in tls_version_min."
+.format(self.tls_version_min))
+
+if self.tls_version_max not in TLS_VERSIONS:
+raise errors.EnvironmentError(
+"Unknown TLS version '{ver}' set in tls_version_max."
+.format(self.tls_version_max))
+
+
 def _finalize(self, **lastchance):
 """
 Finalize and lock environment.
diff --git a/ipalib/constants.py b/ipalib/constants.py
index 81643da..1e8f51a 100644
--- a/ipalib/constants.py
+++ b/ipalib/constants.py
@@ -276,3 +276,13 @@
 
 # regexp definitions
 PATTERN_GROUPUSER_NAME = '^[a-zA-Z0-9_.][a-zA-Z0-9_.-]*[a-zA-Z0-9_.$-]?$'
+
+# TLS related constants
+TLS_VERSIONS = [
+"ssl2",
+"ssl3",
+"tls1.0",
+"tls1.1",
+"tls1.2"
+]
+TLS_VERSION_MINIMAL = "tls1.0"
diff --git a/ipapython/nsslib.py b/ipapython/nsslib.py
index 08d05fc..9f8fd3c 100644
--- a/ipapython/nsslib.py
+++ b/ipapython/nsslib.py
@@ -23,6 +23,7 @@
 import getpass
 import socket
 from ipapython.ipa_log_manager import root_logger
+from ipalib.constants import TLS_VERSIONS, TLS_VERSION_MINIMAL
 
 from nss.error import NSPRError
 import nss.io as io
@@ -129,6 +130,45 @@ def client_auth_data_callback(ca_names, chosen_nickname, password, certdb):
 socket.AF_UNSPEC: io.PR_AF_UNSPEC
 }
 
+
+def get_proper_tls_version_span(tls_version_min, tls_version_max):
+# every tls version from `tls_versions` prior to min_allowed_idx
+# is deprecated in IPA
+min_allowed_idx = TLS_VERSIONS.index(TLS_VERSION_MINIMAL)
+
+try:
+min_version_idx = TLS_VERSIONS.index(tls_version_min)
+except ValueError:
+raise RuntimeError("tls_version_min ('{val}') is not a known "
+   "TLS version.".format(val=tls_version_min))
+
+try:
+max_version_idx = TLS_VERSIONS.index(tls_version_max)
+except ValueError:
+raise RuntimeError("tls_version_max ('{val}') is not a known "
+   "TLS version.".format(val=tls_version_max))
+
+if min_version_idx > max_version_idx:
+raise RuntimeError("tls_version_min is higher than "
+   "tls_version_max.")
+
+if min_version_idx < min_allowed_idx:
+min_version_idx = min_allowed_idx
+root_logger.warning("tls_version_min set too low ('{old}'),"
+"using '{new}' instead"
+.format(old=tls_version_min,
+new=TLS_VERSIONS[min_version_idx]))
+
+if max_version_idx < min_allowed_idx:
+max_version_idx = min_version_idx
+root_logger.warning("tls_version_max set too low ('{old}'),"
+"using '{new}' instead"
+.format(old=tls_version_max,
+new=TLS_VERSIONS[max_version_idx]))
+
+return TLS_VERSIONS[min_version_idx:max_version_idx+1]
+
+
 class 

[Freeipa-devel] [freeipa PR#396][synchronized] Explicitly remove support of SSLv2

2017-02-07 Thread stlaz
   URL: https://github.com/freeipa/freeipa/pull/396
Author: stlaz
 Title: #396: Explicitly remove support of SSLv2
Action: synchronized

To pull the PR as Git branch:
git remote add ghfreeipa https://github.com/freeipa/freeipa
git fetch ghfreeipa pull/396/head:pr396
git checkout pr396
From be99b8327a488440a9991b5d76d2046aae3d74a3 Mon Sep 17 00:00:00 2001
From: Stanislav Laznicka 
Date: Fri, 13 Jan 2017 12:31:29 +0100
Subject: [PATCH] Explicitly remove support of SSLv2

It was possible to set tls_version_min/max to 'ssl2', even though
newer versions of NSS will fail to set this as a valid TLS version.
This patch explicitly checks for deprecated TLS versions prior to
creating a TLS connection.

https://fedorahosted.org/freeipa/ticket/6607
---
 ipalib/config.py| 18 --
 ipalib/constants.py | 10 ++
 ipapython/nsslib.py | 47 +--
 3 files changed, 71 insertions(+), 4 deletions(-)

diff --git a/ipalib/config.py b/ipalib/config.py
index 20591db..22446ca 100644
--- a/ipalib/config.py
+++ b/ipalib/config.py
@@ -41,8 +41,11 @@
 
 from ipapython.dn import DN
 from ipalib.base import check_name
-from ipalib.constants import CONFIG_SECTION
-from ipalib.constants import OVERRIDE_ERROR, SET_ERROR, DEL_ERROR
+from ipalib.constants import (
+CONFIG_SECTION,
+OVERRIDE_ERROR, SET_ERROR, DEL_ERROR,
+TLS_VERSIONS
+)
 from ipalib import errors
 
 if six.PY3:
@@ -497,6 +500,17 @@ def _bootstrap(self, **overrides):
 if 'plugins_on_demand' not in self:
 self.plugins_on_demand = (self.context == 'cli')
 
+if self.tls_version_min not in TLS_VERSIONS:
+raise errors.EnvironmentError(
+"Unknown TLS version '{ver}' set in tls_version_min."
+.format(self.tls_version_min))
+
+if self.tls_version_min not in TLS_VERSIONS:
+raise errors.EnvironmentError(
+"Unknown TLS version '{ver}' set in tls_version_min."
+.format(self.tls_version_min))
+
+
 def _finalize_core(self, **defaults):
 """
 Complete initialization of standard IPA environment.
diff --git a/ipalib/constants.py b/ipalib/constants.py
index 81643da..1e8f51a 100644
--- a/ipalib/constants.py
+++ b/ipalib/constants.py
@@ -276,3 +276,13 @@
 
 # regexp definitions
 PATTERN_GROUPUSER_NAME = '^[a-zA-Z0-9_.][a-zA-Z0-9_.-]*[a-zA-Z0-9_.$-]?$'
+
+# TLS related constants
+TLS_VERSIONS = [
+"ssl2",
+"ssl3",
+"tls1.0",
+"tls1.1",
+"tls1.2"
+]
+TLS_VERSION_MINIMAL = "tls1.0"
diff --git a/ipapython/nsslib.py b/ipapython/nsslib.py
index 08d05fc..5e8bde0 100644
--- a/ipapython/nsslib.py
+++ b/ipapython/nsslib.py
@@ -23,6 +23,8 @@
 import getpass
 import socket
 from ipapython.ipa_log_manager import root_logger
+from ipalib.errors import InvocationError
+from ipalib.constants import TLS_VERSIONS, TLS_VERSION_MINIMAL
 
 from nss.error import NSPRError
 import nss.io as io
@@ -129,6 +131,45 @@ def client_auth_data_callback(ca_names, chosen_nickname, password, certdb):
 socket.AF_UNSPEC: io.PR_AF_UNSPEC
 }
 
+
+def get_proper_tls_version_span(tls_version_min, tls_version_max):
+# every tls version from `tls_versions` prior to min_allowed_idx
+# is deprecated in IPA
+min_allowed_idx = TLS_VERSIONS.index(TLS_VERSION_MINIMAL)
+
+try:
+min_version_idx = TLS_VERSIONS.index(tls_version_min)
+except ValueError:
+raise InvocationError("tls_version_min ('{val}') is not a known "
+  "TLS version.".format(val=tls_version_min))
+
+try:
+max_version_idx = TLS_VERSIONS.index(tls_version_max)
+except ValueError:
+raise InvocationError("tls_version_max ('{val}') is not a known "
+  "TLS version.".format(val=tls_version_max))
+
+if min_version_idx > max_version_idx:
+raise InvocationError("tls_version_min is higher than "
+  "tls_version_max.")
+
+if min_version_idx < min_allowed_idx:
+min_version_idx = min_allowed_idx
+root_logger.warning("tls_version_min set too low ('{old}'),"
+"using '{new}' instead"
+.format(old=tls_version_min,
+new=TLS_VERSIONS[min_version_idx]))
+
+if max_version_idx < min_allowed_idx:
+max_version_idx = min_version_idx
+root_logger.warning("tls_version_max set too low ('{old}'),"
+"using '{new}' instead"
+.format(old=tls_version_max,
+new=TLS_VERSIONS[max_version_idx]))
+
+return TLS_VERSIONS[min_version_idx:max_version_idx+1]
+
+
 class NSSAddressFamilyFallback(object):
 def __init__(self, family):
 self.sock_family = family
@@ -217,8 +258,10 @@ def __init__(self, host, port=None, strict=None,
 
 ssl.set_domestic_policy()