diff options
author | Matthew Harmsen <mharmsen@redhat.com> | 2012-08-16 20:09:20 -0700 |
---|---|---|
committer | Matthew Harmsen <mharmsen@redhat.com> | 2012-08-17 15:07:19 -0700 |
commit | aaebc76f590a31f6dc44efa98dba950985dc6dd2 (patch) | |
tree | 4c9c653cec8f5841b9c0c56be322762e2744aed1 /base | |
parent | 6028b01f64305eda7540cf96bde658d4ebbec2ed (diff) | |
download | pki-aaebc76f590a31f6dc44efa98dba950985dc6dd2.tar.gz pki-aaebc76f590a31f6dc44efa98dba950985dc6dd2.tar.xz pki-aaebc76f590a31f6dc44efa98dba950985dc6dd2.zip |
PKI Deployment Scriptlets
* TRAC Ticket #266 - for non-master CA subsystems, pkidestroy needs to
contact the security domain to update the domain
* Made Fedora 17 rely upon tomcatjss 7.0.0 or later
* Changed Dogtag 10 build-time and runtime requirements for 'pki-deploy'
* Altered PKI Package Dependency Chain (top-to-bottom):
pki-ca, pki-kra, pki-ocsp, pki-tks --> pki-deploy --> pki-common
* Changed TPS to require a build-time dependency of 'httpd-devel >= 2.4.2'
* Clarified RPM build script's usage message
Diffstat (limited to 'base')
13 files changed, 276 insertions, 19 deletions
diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/DownloadPKCS12.java b/base/common/src/com/netscape/cms/servlet/csadmin/DownloadPKCS12.java index 57a1e6202..7f7929930 100644 --- a/base/common/src/com/netscape/cms/servlet/csadmin/DownloadPKCS12.java +++ b/base/common/src/com/netscape/cms/servlet/csadmin/DownloadPKCS12.java @@ -72,7 +72,8 @@ public class DownloadPKCS12 extends CMSServlet { String pin = (String) httpReq.getSession().getAttribute("pin"); if (pin == null) { CMS.debug("DownloadPKCS12 process: Failed to get the pin from the cookie."); - outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated"); + outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated", + null); return; } @@ -84,7 +85,8 @@ public class DownloadPKCS12 extends CMSServlet { if (!pin.equals(cspin)) { CMS.debug("DownloadPKCS12 process: Wrong pin"); - outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated"); + outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated", + null); return; } diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/GetConfigEntries.java b/base/common/src/com/netscape/cms/servlet/csadmin/GetConfigEntries.java index a9de5a54e..ee013ef48 100644 --- a/base/common/src/com/netscape/cms/servlet/csadmin/GetConfigEntries.java +++ b/base/common/src/com/netscape/cms/servlet/csadmin/GetConfigEntries.java @@ -88,7 +88,8 @@ public class GetConfigEntries extends CMSServlet { log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERR_BAD_SERV_OUT_STREAM", "", e.toString())); - outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated"); + outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated", + null); return; } diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/GetTransportCert.java b/base/common/src/com/netscape/cms/servlet/csadmin/GetTransportCert.java index ae5edf617..649b1214a 100644 --- a/base/common/src/com/netscape/cms/servlet/csadmin/GetTransportCert.java +++ b/base/common/src/com/netscape/cms/servlet/csadmin/GetTransportCert.java @@ -86,13 +86,15 @@ public class GetTransportCert extends CMSServlet { log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERR_BAD_SERV_OUT_STREAM", "", e.toString())); - outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated"); + outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated", + null); return; } if (authToken == null) { CMS.debug("GetTransportCert: authentication failed."); - outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated"); + outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated", + null); return; } diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/ImportTransportCert.java b/base/common/src/com/netscape/cms/servlet/csadmin/ImportTransportCert.java index 859ba845e..b0dc966f3 100644 --- a/base/common/src/com/netscape/cms/servlet/csadmin/ImportTransportCert.java +++ b/base/common/src/com/netscape/cms/servlet/csadmin/ImportTransportCert.java @@ -86,13 +86,15 @@ public class ImportTransportCert extends CMSServlet { log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERR_BAD_SERV_OUT_STREAM", "", e.toString())); - outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated"); + outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated", + null); return; } if (authToken == null) { CMS.debug("ImportTransportCert: authentication failed."); - outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated"); + outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated", + null); return; } diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/RegisterUser.java b/base/common/src/com/netscape/cms/servlet/csadmin/RegisterUser.java index d2cf540c3..74197a4a8 100644 --- a/base/common/src/com/netscape/cms/servlet/csadmin/RegisterUser.java +++ b/base/common/src/com/netscape/cms/servlet/csadmin/RegisterUser.java @@ -103,13 +103,15 @@ public class RegisterUser extends CMSServlet { log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERR_BAD_SERV_OUT_STREAM", "", e.toString())); - outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated"); + outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated", + null); return; } if (authToken == null) { CMS.debug("RegisterUser: authentication failed."); - outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated"); + outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated", + null); return; } diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/UpdateConnector.java b/base/common/src/com/netscape/cms/servlet/csadmin/UpdateConnector.java index 240468d03..b6f64767a 100644 --- a/base/common/src/com/netscape/cms/servlet/csadmin/UpdateConnector.java +++ b/base/common/src/com/netscape/cms/servlet/csadmin/UpdateConnector.java @@ -86,13 +86,15 @@ public class UpdateConnector extends CMSServlet { log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERR_BAD_SERV_OUT_STREAM", "", e.toString())); - outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated"); + outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated", + null); return; } if (authToken == null) { CMS.debug("UpdateConnector: authentication failed."); - outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated"); + outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated", + null); return; } diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/UpdateDomainXML.java b/base/common/src/com/netscape/cms/servlet/csadmin/UpdateDomainXML.java index fe6507f37..b783c359b 100644 --- a/base/common/src/com/netscape/cms/servlet/csadmin/UpdateDomainXML.java +++ b/base/common/src/com/netscape/cms/servlet/csadmin/UpdateDomainXML.java @@ -213,13 +213,16 @@ public class UpdateDomainXML extends CMSServlet { authToken = authenticate(cmsReq); } catch (Exception e) { log(ILogger.LL_FAILURE, - CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); - outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated"); + CMS.getLogMessage("CMSGW_ERR_BAD_SERV_OUT_STREAM", "", + e.toString())); + outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated", + null); return; } if (authToken == null) { CMS.debug("UpdateDomainXML process: authToken is null"); - outputError(httpResp, AUTH_FAILURE, "Error: not authenticated"); + outputError(httpResp, AUTH_FAILURE, "Error: not authenticated", + null); return; } CMS.debug("UpdateDomainXML process: authentication done"); @@ -232,19 +235,18 @@ public class UpdateDomainXML extends CMSServlet { } catch (EAuthzAccessDenied e) { log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); - outputError(httpResp, AUTH_FAILURE, "Error: Not authorized"); + outputError(httpResp, "Error: Not authorized"); return; } catch (Exception e) { log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); outputError(httpResp, - AUTH_FAILURE, "Error: Encountered problem during authorization."); return; } if (authzToken == null) { CMS.debug("UpdateDomainXML process: authorization error"); - outputError(httpResp, AUTH_FAILURE, "Error: Not authorized"); + outputError(httpResp, "Error: Not authorized"); return; } diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/UpdateNumberRange.java b/base/common/src/com/netscape/cms/servlet/csadmin/UpdateNumberRange.java index eb88a1c31..b99a298a9 100644 --- a/base/common/src/com/netscape/cms/servlet/csadmin/UpdateNumberRange.java +++ b/base/common/src/com/netscape/cms/servlet/csadmin/UpdateNumberRange.java @@ -89,7 +89,8 @@ public class UpdateNumberRange extends CMSServlet { IAuthToken authToken = authenticate(cmsReq); if (authToken == null) { CMS.debug("UpdateNumberRange process: authToken is null"); - outputError(httpResp, AUTH_FAILURE, "Error: not authenticated"); + outputError(httpResp, AUTH_FAILURE, "Error: not authenticated", + null); } AuthzToken authzToken = null; diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/UpdateOCSPConfig.java b/base/common/src/com/netscape/cms/servlet/csadmin/UpdateOCSPConfig.java index e1b33ea6a..3d564e955 100644 --- a/base/common/src/com/netscape/cms/servlet/csadmin/UpdateOCSPConfig.java +++ b/base/common/src/com/netscape/cms/servlet/csadmin/UpdateOCSPConfig.java @@ -74,7 +74,8 @@ public class UpdateOCSPConfig extends CMSServlet { IAuthToken authToken = authenticate(cmsReq); if (authToken == null) { CMS.debug("UpdateOCSPConfig process: authToken is null"); - outputError(httpResp, AUTH_FAILURE, "Error: not authenticated"); + outputError(httpResp, AUTH_FAILURE, "Error: not authenticated", + null); } AuthzToken authzToken = null; diff --git a/base/deploy/src/scriptlets/configuration.py b/base/deploy/src/scriptlets/configuration.py index f7a9a66e6..7e99dd4fe 100644 --- a/base/deploy/src/scriptlets/configuration.py +++ b/base/deploy/src/scriptlets/configuration.py @@ -147,6 +147,7 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet): def destroy(self): config.pki_log.info(log.CONFIGURATION_DESTROY_1, __name__, extra=config.PKI_INDENTATION_LEVEL_1) + util.security_domain.deregister() if not config.pki_dry_run_flag: if master['pki_subsystem'] in config.PKI_APACHE_SUBSYSTEMS and\ util.instance.apache_instance_subsystems() == 1: diff --git a/base/deploy/src/scriptlets/pkihelper.py b/base/deploy/src/scriptlets/pkihelper.py index c0dc14d24..038198ad3 100644 --- a/base/deploy/src/scriptlets/pkihelper.py +++ b/base/deploy/src/scriptlets/pkihelper.py @@ -27,6 +27,7 @@ import os import fileinput import pickle import random +import re import shutil import string import subprocess @@ -46,6 +47,7 @@ from pkiconfig import pki_slots_dict as slots from pkiconfig import pki_selinux_config_ports as ports import pkimanifest as manifest import pkimessages as log +from pkiparser import read_simple_configuration_file # PKI Deployment Helper Functions @@ -2400,6 +2402,193 @@ class certutil: return +# PKI Deployment Security Domain Class +class security_domain: + def deregister(self, critical_failure=False): + try: + # process this PKI subsystem instance's 'CS.cfg' + cs_cfg = read_simple_configuration_file(master['pki_target_cs_cfg']) + + # assign key name/value pairs + machinename = cs_cfg.get('service.machineName') + sport = cs_cfg.get('service.securityDomainPort') + ncsport = cs_cfg.get('service.non_clientauth_securePort', '') + sechost = cs_cfg.get('securitydomain.host') + httpport = cs_cfg.get('securitydomain.httpport') + seceeport = cs_cfg.get('securitydomain.httpseeport') + secagentport = cs_cfg.get('securitydomain.httpsagentport') + secadminport = cs_cfg.get('securitydomain.httpsadminport') + secname = cs_cfg.get('securitydomain.name', 'unknown') + secselect = cs_cfg.get('securitydomain.select') + adminsport = cs_cfg.get('pkicreate.admin_secure_port', '') + typeval = cs_cfg.get('cs.type', '') + agentsport = cs_cfg.get('pkicreate.agent_secure_port', '') + token_pwd = None + + # retrieve subsystem nickname + subsystemnick_param = typeval.lower() + ".cert.subsystem.nickname" + subsystemnick = cs_cfg.get(subsystemnick_param) + if subsystemnick is None: + config.pki_log.warning( + log.PKIHELPER_SECURITY_DOMAIN_UPDATE_FAILURE_2, + typeval, + secname, + extra=config.PKI_INDENTATION_LEVEL_2) + config.pki_log.error( + log.PKIHELPER_UNDEFINED_SUBSYSTEM_NICKNAME, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + sys.exit(-1) + else: + return + + # retrieve name of token based upon type (hardware/software) + if ':' in subsystemnick: + token_name = subsystemnick.split(':')[0] + else: + token_name = "internal" + + # NOTE: Don't check for the existence of 'httpport', as this will + # be undefined for a Security Domain that has been migrated! + if sechost is None or\ + seceeport is None or\ + secagentport is None or\ + secadminport is None: + config.pki_log.warning( + log.PKIHELPER_SECURITY_DOMAIN_UPDATE_FAILURE_2, + typeval, + secname, + extra=config.PKI_INDENTATION_LEVEL_2) + config.pki_log.error( + log.PKIHELPER_SECURITY_DOMAIN_UNDEFINED, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + sys.exit(-1) + else: + return + + if secselect != "new": + # This is not a domain master, so we need to update the master + config.pki_log.info(log.PKIHELPER_SECURITY_DOMAIN_CONTACT_1, + secname, + extra=config.PKI_INDENTATION_LEVEL_2) + listval = typeval.lower() + "List" + urlheader = "https://{}:{}".format(sechost, seceeport) + urlagentheader = "https://{}:{}".format(sechost, secagentport) + urladminheader = "https://{}:{}".format(sechost, secadminport) + updateURL = "/ca/agent/ca/updateDomainXML" + + # process this PKI subsystem instance's 'password.conf' + # + # REMINDER: NEVER log this 'sensitive' information! + # + if os.path.exists(master['pki_shared_password_conf']) and\ + os.path.isfile(master['pki_shared_password_conf']) and\ + os.access(master['pki_shared_password_conf'], os.R_OK): + tokens = read_simple_configuration_file( + master['pki_shared_password_conf']) + hardware_token = "hardware-" + token_name + if tokens.has_key(hardware_token): + token_name = hardware_token + token_pwd = tokens[hardware_token] + elif tokens.has_key(token_name): + token_pwd = tokens[token_name] + + if token_pwd is None or token_pwd == '': + # 'pkiremove' prompts with + # "What is the password for this token?" + config.pki_log.warning( + log.PKIHELPER_SECURITY_DOMAIN_UPDATE_FAILURE_2, + typeval, + secname, + extra=config.PKI_INDENTATION_LEVEL_2) + config.pki_log.error(log.PKIHELPER_PASSWORD_NOT_FOUND_1, + token_name, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + sys.exit(-1) + else: + return + + params = "name=" + "\"" + master['pki_instance_path'] + "\"" +\ + "&type=" + str(typeval) +\ + "&list=" + str(listval) +\ + "&host=" + str(machinename) +\ + "&sport=" + str(sport) +\ + "&ncsport=" + str(ncsport) +\ + "&adminsport=" + str(adminsport) +\ + "&agentsport=" + str(agentsport) +\ + "&operation=remove" + + # Compose this "sslget" command + # + # REMINDER: NEVER log this command as it contains + # an exposed password in plaintext! + # + command = "/usr/bin/sslget -n '{}' -p '{}' -d '{}' -e '{}' "\ + "-v -r '{}' {}:{} 2>&1".format( + subsystemnick, token_pwd, + master['pki_database_path'], + params, updateURL, + sechost, secagentport) + # update domainXML + if not config.pki_dry_run_flag: + # Execute this "sslget" command + output = subprocess.check_output(command, + stderr=subprocess.STDOUT, + shell=True) + config.pki_log.debug(log.PKIHELPER_SSLGET_OUTPUT_1, + output, + extra=config.PKI_INDENTATION_LEVEL_2) + # Search the output for Status + status = re.findall("\<Status\>(.*?)\<\/Status\>", output) + if not status: + config.pki_log.warning( + log.PKIHELPER_SECURITY_DOMAIN_UNREACHABLE_1, + secname, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + sys.exit(-1) + elif status[0] != "0": + error = re.findall("\<Error\>(.*?)\<\/Error\>", output) + if not error: + error = "" + config.pki_log.warning( + log.PKIHELPER_SECURITY_DOMAIN_UNREGISTERED_2, + typeval, + secname, + extra=config.PKI_INDENTATION_LEVEL_2) + config.pki_log.error( + log.PKIHELPER_SECURITY_DOMAIN_UPDATE_FAILURE_3, + typeval, + secname, + error[0], + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + sys.exit(-1) + else: + config.pki_log.info( + log.PKIHELPER_SECURITY_DOMAIN_UPDATE_SUCCESS_2, + typeval, + secname, + extra=config.PKI_INDENTATION_LEVEL_2) + except subprocess.CalledProcessError as exc: + config.pki_log.warning( + log.PKIHELPER_SECURITY_DOMAIN_UPDATE_FAILURE_2, + typeval, + secname, + extra=config.PKI_INDENTATION_LEVEL_2) + config.pki_log.warning( + log.PKIHELPER_SECURITY_DOMAIN_UNREACHABLE_1, + secname, + extra=config.PKI_INDENTATION_LEVEL_2) + config.pki_log.error(log.PKI_SUBPROCESS_ERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + sys.exit(-1) + return + + # PKI Deployment 'systemd' Execution Management Class class systemd: def start(self, critical_failure=True): @@ -2535,5 +2724,6 @@ symlink = symlink() war = war() password = password() certutil = certutil() +security_domain = security_domain() systemd = systemd() jython = jython() diff --git a/base/deploy/src/scriptlets/pkimessages.py b/base/deploy/src/scriptlets/pkimessages.py index 2b8a22528..ba3f22898 100644 --- a/base/deploy/src/scriptlets/pkimessages.py +++ b/base/deploy/src/scriptlets/pkimessages.py @@ -216,14 +216,38 @@ PKIHELPER_NAMESPACE_RESERVED_NAME_2 = "PKI instance '%s' is already a "\ PKIHELPER_NOISE_FILE_2 = "generating noise file called '%s' and "\ "filling it with '%d' random bytes" PKIHELPER_PASSWORD_CONF_1 = "generating '%s'" +PKIHELPER_PASSWORD_NOT_FOUND_1 = "no password found for '%s'!" PKIHELPER_PKI_INSTANCE_SUBSYSTEMS_2 = "instance '%s' contains '%d' "\ "PKI subsystems" PKIHELPER_REMOVE_FILTER_SECTION_1 = "removing filter section from '%s'" PKIHELPER_RM_F_1 = "rm -f %s" PKIHELPER_RM_RF_1 = "rm -rf %s" PKIHELPER_RMDIR_1 = "rmdir %s" +PKIHELPER_SECURITY_DOMAIN_CONTACT_1 =\ + "contacting the security domain master to update security domain '%s'" +PKIHELPER_SECURITY_DOMAIN_UNDEFINED =\ + "No security domain defined.\n"\ + "If this is an unconfigured instance, then that is OK.\n"\ + "Otherwise, manually delete the entry from the security domain master." +PKIHELPER_SECURITY_DOMAIN_UNREACHABLE_1 =\ + "security domain '%s' may be offline or unreachable!" +PKIHELPER_SECURITY_DOMAIN_UNREGISTERED_2 =\ + "this '%s' entry may not be registered with security domain '%s'!" +PKIHELPER_SECURITY_DOMAIN_UPDATE_FAILURE_2 =\ + "this '%s' entry will NOT be deleted from security domain '%s'!" +PKIHELPER_SECURITY_DOMAIN_UPDATE_FAILURE_3 =\ + "updateDomainXML FAILED to delete this '%s' entry from "\ + "security domain '%s': '%s'" +PKIHELPER_SECURITY_DOMAIN_UPDATE_SUCCESS_2 =\ + "updateDomainXML SUCCESSFULLY deleted this '%s' entry from "\ + "security domain '%s'" PKIHELPER_SET_MODE_1 = "setting ownerships, permissions, and acls on '%s'" PKIHELPER_SLOT_SUBSTITUTION_2 = "slot substitution: '%s' ==> '%s'" +PKIHELPER_SSLGET_OUTPUT_1 = "\n"\ + "Dump of 'sslget' output:\n"\ + "=====================================================\n"\ + "%s\n"\ + "=====================================================" PKIHELPER_SYSTEMD_COMMAND_1 = "executing '%s'" PKIHELPER_TOMCAT_INSTANCE_SUBSYSTEMS_2 = "instance '%s' contains '%d' "\ "Tomcat PKI subsystems" @@ -236,6 +260,7 @@ PKIHELPER_UNDEFINED_CLIENT_DATABASE_PASSWORD_2 =\ "the randomly generated client pin MUST be used" PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2 =\ "A value for '%s' MUST be defined in '%s'" +PKIHELPER_UNDEFINED_SUBSYSTEM_NICKNAME = "subsystem nickname not defined" PKIHELPER_USER_1 = "retrieving UID for '%s' . . ." PKIHELPER_USER_ADD_2 = "adding UID '%s' for user '%s' . . ." PKIHELPER_USER_ADD_DEFAULT_2 = "adding default UID '%s' for user '%s' . . ." diff --git a/base/deploy/src/scriptlets/pkiparser.py b/base/deploy/src/scriptlets/pkiparser.py index dd1f93bd3..1fe74e835 100644 --- a/base/deploy/src/scriptlets/pkiparser.py +++ b/base/deploy/src/scriptlets/pkiparser.py @@ -188,6 +188,32 @@ def process_command_line_arguments(argv): return +# The following code is based heavily upon +# "http://www.decalage.info/en/python/configparser" +COMMENT_CHAR = '#' +OPTION_CHAR = '=' + +def read_simple_configuration_file(filename): + values = {} + f = open(filename) + for line in f: + # First, remove comments: + if COMMENT_CHAR in line: + # split on comment char, keep only the part before + line, comment = line.split(COMMENT_CHAR, 1) + # Second, find lines with an name=value: + if OPTION_CHAR in line: + # split on name char: + name, value = line.split(OPTION_CHAR, 1) + # strip spaces: + name = name.strip() + value = value.strip() + # store in dictionary: + values[name] = value + f.close() + return values + + def read_pki_configuration_file(): "Read configuration file sections into dictionaries" rv = 0 |