[Pki-devel] [PATCH] 0151..0155 Add profile component that copies CN to SAN

Fraser Tweedale ftweedal at redhat.com
Wed Feb 1 07:25:58 UTC 2017


Hi all,

The attached patches implement the long-desired feature to copy CN
to SubjectAltName (https://fedorahosted.org/pki/ticket/1710).

I've also pushed the branch to my GitHub repo; feel free to review
the patches there:
https://github.com/frasertweedale/pki/commits/feature/1710-cn-to-san

Thanks,
Fraser
-------------- next part --------------
From 3f913b1857712dd0a962d42f56f29d7faebf244e Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftweedal at redhat.com>
Date: Wed, 1 Feb 2017 16:15:39 +1000
Subject: [PATCH 151/155] DNSName: add method to get value

To implement a profile default that copies CN to SAN dNSName, we
need to examine existing dNSName values.  To support this, add the
'getValue()' method to 'DNSName'.

Part of: https://fedorahosted.org/pki/ticket/1710
---
 base/util/src/netscape/security/x509/DNSName.java | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/base/util/src/netscape/security/x509/DNSName.java b/base/util/src/netscape/security/x509/DNSName.java
index 361c23571f423f635e2026c64c7bcf902f5ff3be..2161adf3701a554040ca4afc5b0c39337ed8452a 100644
--- a/base/util/src/netscape/security/x509/DNSName.java
+++ b/base/util/src/netscape/security/x509/DNSName.java
@@ -79,4 +79,12 @@ public class DNSName implements GeneralNameInterface {
     public String toString() {
         return ("DNSName: " + name);
     }
+
+    /**
+     * Get the raw DNSName value.
+     */
+    public String getValue() {
+        return name;
+    }
+
 }
-- 
2.9.3

-------------- next part --------------
From aaa8d03d36f31894fed3c8d9c7b5126ac5417774 Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftweedal at redhat.com>
Date: Wed, 1 Feb 2017 16:17:51 +1000
Subject: [PATCH 152/155] GeneralName: add method to get at inner value

The 'GeneralNameInterface' interface represents a single X.509
General Name value.  Various types are supported.  The 'GeneralName'
class (which also implements 'GeneralNameInterface') is a singleton
container for another 'GeneralNameInterface' value.

To implement a profile component that copies CN to a SAN dNSName, we
need to examine existing General Names in the SAN extension (if
present), to avoid duplicate values.  We can iterate 'GeneralNames',
but if the value is of type 'GeneralName' we need a way to "unwrap"
the value, down to the innermost value which will be of a specific
General Name type.

Add the 'unwrap' method to 'GeneralName'.

Part of: https://fedorahosted.org/pki/ticket/1710
---
 base/util/src/netscape/security/x509/GeneralName.java | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/base/util/src/netscape/security/x509/GeneralName.java b/base/util/src/netscape/security/x509/GeneralName.java
index a90ac7bf259b519c91bb2f67cf159f7b4178b182..55b5bfcf304c0c8ccf893f9a6ef70d2e5c2ee0e2 100644
--- a/base/util/src/netscape/security/x509/GeneralName.java
+++ b/base/util/src/netscape/security/x509/GeneralName.java
@@ -196,4 +196,19 @@ public class GeneralName implements GeneralNameInterface {
                              constructedForm, (byte) nameType), tmp);
         }
     }
+
+    /**
+     * Unwrap this GeneralName until we reach something that is not
+     * a GeneralName.
+     */
+    public GeneralNameInterface unwrap() {
+        if (this == name)
+            return null;  // can't happen, but just in case...
+
+        if (name instanceof GeneralName)
+            return ((GeneralName) name).unwrap();
+        else
+            return name;
+    }
+
 }
-- 
2.9.3

-------------- next part --------------
From 805b2e2d753f86c39af225d13c7614974e10c154 Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftweedal at redhat.com>
Date: Wed, 1 Feb 2017 16:25:11 +1000
Subject: [PATCH 153/155] SubjectAlternativeNameExtension: add GeneralNames
 getter/setter

To implement a profile default that copies CN to SAN dNSName, we
need to read and set the 'GeneralNames' of the extension.  This can
be done via the 'get' and 'set' methods but this interface is
awkward and requires the caller to deal with exceptions that aren't
fundamental to the get/set actions.

Add the 'setGeneralNames' and 'getGeneralNames' methods.

Part of: https://fedorahosted.org/pki/ticket/1710
---
 .../security/x509/SubjectAlternativeNameExtension.java    | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/base/util/src/netscape/security/x509/SubjectAlternativeNameExtension.java b/base/util/src/netscape/security/x509/SubjectAlternativeNameExtension.java
index d96c821604308c11723644e8842e1dcc6f224034..82f87e1ef647496353f598a33290d6dcfb5e8f04 100644
--- a/base/util/src/netscape/security/x509/SubjectAlternativeNameExtension.java
+++ b/base/util/src/netscape/security/x509/SubjectAlternativeNameExtension.java
@@ -199,6 +199,21 @@ public class SubjectAlternativeNameExtension extends Extension
     }
 
     /**
+     * Set the GeneralNames of this extension.
+     */
+    public void setGeneralNames(GeneralNames names) {
+        clearValue();
+        this.names = names;
+    }
+
+    /**
+     * Get the GeneralNames of this extension.
+     */
+    public GeneralNames getGeneralNames() {
+        return names;
+    }
+
+    /**
      * Get the attribute value.
      */
     public Object get(String name) throws IOException {
-- 
2.9.3

-------------- next part --------------
From 9a7725cc89500efd7685a70ad2b295f3e33b68bc Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftweedal at redhat.com>
Date: Wed, 1 Feb 2017 16:30:50 +1000
Subject: [PATCH 154/155] X500Name: add method to get all attributes of a given
 type

To implement a profile default that copies the CN to a SAN dNSName,
we need to examine the CN values present in the Subject DN.
Specifically, we want to look at the "most specific" CN value.  The
'getCommonName' method returns the "least specific" value in the
name, thus is not suitable.

Add the 'getAttributesForOid(ObjectIdentifier)' method, which
returns an ordered list of values of the given name attribute type,
from least specific to most specific.

Part of: https://fedorahosted.org/pki/ticket/1710
---
 base/util/src/netscape/security/x509/X500Name.java | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/base/util/src/netscape/security/x509/X500Name.java b/base/util/src/netscape/security/x509/X500Name.java
index 0f75f481c1a95960574246225ceae2774e0aca2d..c8627a93c5f36f39d0484867e2a4b8c68fea0fc9 100644
--- a/base/util/src/netscape/security/x509/X500Name.java
+++ b/base/util/src/netscape/security/x509/X500Name.java
@@ -19,8 +19,10 @@ package netscape.security.x509;
 
 import java.io.IOException;
 import java.security.Principal;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Enumeration;
+import java.util.List;
 import java.util.Vector;
 
 import netscape.security.util.DerInputStream;
@@ -451,6 +453,25 @@ public class X500Name implements Principal, GeneralNameInterface {
     }
 
     /**
+     * Return a list of attributes of the given type.
+     *
+     * The "most specific" value comes last.
+     *
+     * If there are no name attributes of the given type, an empty
+     * list is returned.
+     */
+    public List<String> getAttributesForOid(ObjectIdentifier oid)
+            throws IOException {
+        List<String> xs = new ArrayList<>();
+        for (int i = 0; i < names.length; i++) {
+            DerValue v = names[i].findAttribute(oid);
+            if (v != null)
+                xs.add(getString(v));
+        }
+        return xs;
+    }
+
+    /**
      * Returns a Ldap DN String from the X500Name
      * using the specified LdapDNStrconverter.
      * For example, RFC1779String converter can be passed to convert the
-- 
2.9.3

-------------- next part --------------
From 335405a2831166bb28b22d27944d0de0263bb900 Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftweedal at redhat.com>
Date: Wed, 1 Feb 2017 16:39:14 +1000
Subject: [PATCH 155/155] Add profile component that copies CN to SAN dNSName

Add the 'CommonNameToSANDefault' profile default class.  When used
on a profile, this will examine the (most-specific) Common Name in
the Subject DN, and if it looks like a DNS name, will add it to the
Subject Alternative Name extension, creating the extension if it
does not already exist.

Also add upgrade scriptlet to add the component to registry.cfg in
existing installations.

Fixes: https://fedorahosted.org/pki/ticket/1710
---
 base/ca/shared/conf/registry.cfg                   |   5 +-
 .../cms/profile/def/CommonNameToSANDefault.java    | 215 +++++++++++++++++++++
 .../10.4.0/03-AddCommonNameToSANDefaultToRegistry  |  65 +++++++
 3 files changed, 284 insertions(+), 1 deletion(-)
 create mode 100644 base/server/cms/src/com/netscape/cms/profile/def/CommonNameToSANDefault.java
 create mode 100755 base/server/upgrade/10.4.0/03-AddCommonNameToSANDefaultToRegistry

diff --git a/base/ca/shared/conf/registry.cfg b/base/ca/shared/conf/registry.cfg
index 0bd7c05484f7ac15f82c33fe888b4560477efc48..280c71388e8f1575a8785c2009b3c728b2824876 100644
--- a/base/ca/shared/conf/registry.cfg
+++ b/base/ca/shared/conf/registry.cfg
@@ -45,7 +45,7 @@ constraintPolicy.renewGracePeriodConstraintImpl.name=Renewal Grace Period Constr
 constraintPolicy.uniqueKeyConstraintImpl.class=com.netscape.cms.profile.constraint.UniqueKeyConstraint
 constraintPolicy.uniqueKeyConstraintImpl.desc=Unique Public Key Constraint
 constraintPolicy.uniqueKeyConstraintImpl.name=Unique Public Key Constraint
-defaultPolicy.ids=noDefaultImpl,genericExtDefaultImpl,autoAssignDefaultImpl,subjectNameDefaultImpl,validityDefaultImpl,randomizedValidityDefaultImpl,caValidityDefaultImpl,subjectKeyIdentifierExtDefaultImpl,authorityKeyIdentifierExtDefaultImpl,basicConstraintsExtDefaultImpl,keyUsageExtDefaultImpl,nsCertTypeExtDefaultImpl,extendedKeyUsageExtDefaultImpl,ocspNoCheckExtDefaultImpl,issuerAltNameExtDefaultImpl,subjectAltNameExtDefaultImpl,userSubjectNameDefaultImpl,signingAlgDefaultImpl,userKeyDefaultImpl,userValidityDefaultImpl,userExtensionDefaultImpl,userSigningAlgDefaultImpl,authTokenSubjectNameDefaultImpl,subjectInfoAccessExtDefaultImpl,authInfoAccessExtDefaultImpl,nscCommentExtDefaultImpl,freshestCRLExtDefaultImpl,crlDistributionPointsExtDefaultImpl,policyConstraintsExtDefaultImpl,policyMappingsExtDefaultImpl,nameConstraintsExtDefaultImpl,certificateVersionDefaultImpl,certificatePoliciesExtDefaultImpl,subjectDirAttributesExtDefaultImpl,privateKeyPeriodExtDefaultImpl,inhibitAnyPolicyExtDefaultImpl,imageDefaultImpl,nsTokenDeviceKeySubjectNameDefaultImpl,nsTokenUserKeySubjectNameDefaultImpl,authzRealmDefaultImpl
+defaultPolicy.ids=noDefaultImpl,genericExtDefaultImpl,autoAssignDefaultImpl,subjectNameDefaultImpl,validityDefaultImpl,randomizedValidityDefaultImpl,caValidityDefaultImpl,subjectKeyIdentifierExtDefaultImpl,authorityKeyIdentifierExtDefaultImpl,basicConstraintsExtDefaultImpl,keyUsageExtDefaultImpl,nsCertTypeExtDefaultImpl,extendedKeyUsageExtDefaultImpl,ocspNoCheckExtDefaultImpl,issuerAltNameExtDefaultImpl,subjectAltNameExtDefaultImpl,userSubjectNameDefaultImpl,signingAlgDefaultImpl,userKeyDefaultImpl,userValidityDefaultImpl,userExtensionDefaultImpl,userSigningAlgDefaultImpl,authTokenSubjectNameDefaultImpl,subjectInfoAccessExtDefaultImpl,authInfoAccessExtDefaultImpl,nscCommentExtDefaultImpl,freshestCRLExtDefaultImpl,crlDistributionPointsExtDefaultImpl,policyConstraintsExtDefaultImpl,policyMappingsExtDefaultImpl,nameConstraintsExtDefaultImpl,certificateVersionDefaultImpl,certificatePoliciesExtDefaultImpl,subjectDirAttributesExtDefaultImpl,privateKeyPeriodExtDefaultImpl,inhibitAnyPolicyExtDefaultImpl,imageDefaultImpl,nsTokenDeviceKeySubjectNameDefaultImpl,nsTokenUserKeySubjectNameDefaultImpl,authzRealmDefaultImpl,commonNameToSANDefaultImpl
 defaultPolicy.autoAssignDefaultImpl.class=com.netscape.cms.profile.def.AutoAssignDefault
 defaultPolicy.autoAssignDefaultImpl.desc=Auto Request Assignment Default
 defaultPolicy.autoAssignDefaultImpl.name=Auto Request Assignment Default
@@ -166,6 +166,9 @@ defaultPolicy.subjectDirAttributesExtDefaultImpl.name=Subject Directory Attribut
 defaultPolicy.inhibitAnyPolicyExtDefaultImpl.class=com.netscape.cms.profile.def.InhibitAnyPolicyExtDefault
 defaultPolicy.inhibitAnyPolicyExtDefaultImpl.desc=Inhibit Any-Policy Extension Default
 defaultPolicy.inhibitAnyPolicyExtDefaultImpl.name=Inhibit Any-Policy Extension Default
+defaultPolicy.commonNameToSANDefaultImpl.class=com.netscape.cms.profile.def.CommonNameToSANDefault
+defaultPolicy.commonNameToSANDefaultImpl.desc=Copy Common Name to Subject Alternative Name
+defaultPolicy.commonNameToSANDefaultImpl.name=Copy Common Name to Subject Alternative Name
 profile.ids=caEnrollImpl,caCACertEnrollImpl,caServerCertEnrollImpl,caUserCertEnrollImpl
 profile.caEnrollImpl.class=com.netscape.cms.profile.common.CAEnrollProfile
 profile.caEnrollImpl.desc=Certificate Authority Generic Certificate Enrollment Profile
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/CommonNameToSANDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/CommonNameToSANDefault.java
new file mode 100644
index 0000000000000000000000000000000000000000..33828d11d1365fce18d8242f416cfbf3a9825843
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/CommonNameToSANDefault.java
@@ -0,0 +1,215 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2017 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package com.netscape.cms.profile.def;
+
+import java.io.IOException;
+import java.security.cert.CertificateException;
+import java.util.List;
+import java.util.Locale;
+
+import netscape.security.x509.CertificateSubjectName;
+import netscape.security.x509.DNSName;
+import netscape.security.x509.GeneralName;
+import netscape.security.x509.GeneralNameInterface;
+import netscape.security.x509.GeneralNames;
+import netscape.security.x509.PKIXExtensions;
+import netscape.security.x509.SubjectAlternativeNameExtension;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CertInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * This plugin will examine the most specific CN in the Subject DN,
+ * and if it looks like a DNS name, will add it to the SAN extension.
+ *
+ * It will create the SAN extension if necessary.
+ *
+ * If there is already a SAN dnsName value that matches
+ * (case-insensitively) the CN, it will not add the name.
+ *
+ * If there is no CN in the subject DN, does nothing.
+ *
+ * If the most specific CN does not look like a DNS name, does
+ * nothing.
+ *
+ * This profile component should be configured to execute after
+ * other profile components that set or modify the Subject DN or the
+ * SAN extension.
+ */
+public class CommonNameToSANDefault extends EnrollExtDefault {
+
+    private static final String LOG_PREFIX = "CommonNameToSANDefault: ";
+
+    public void populate(IRequest _req, X509CertInfo info)
+            throws EProfileException {
+        // examine the Subject DN
+        CertificateSubjectName subjectName;
+        try {
+            subjectName = (CertificateSubjectName) info.get(X509CertInfo.SUBJECT);
+        } catch (CertificateException | IOException e) {
+            CMS.debug(LOG_PREFIX + "failed to read Subject DN: " + e);
+            return;
+        }
+        X500Name sdn;
+        try {
+            sdn = (X500Name) subjectName.get(CertificateSubjectName.DN_NAME);
+        } catch (IOException e) {
+            CMS.debug(LOG_PREFIX + "failed to retrieve SDN X500Name: " + e);
+            return;
+        }
+        List<String> cns;
+        try {
+            cns = sdn.getAttributesForOid(X500Name.commonName_oid);
+        } catch (IOException e) {
+            // Couldn't read the CN for some reason.
+            // Not a likely scenario so just log and return.
+            CMS.debug(LOG_PREFIX + "failed to decode CN: " + e);
+            return;
+        }
+        if (cns.size() < 1) {
+            CMS.debug(LOG_PREFIX + "No CN in Subject DN; done");
+            return;  // no Common Name; can't do anything
+        }
+
+        String cn = cns.get(cns.size() - 1); // "most specific" CN is at end
+
+        CMS.debug(LOG_PREFIX + "Examining CN: " + cn);
+
+        if (!isValidDNSName(cn)) {
+            CMS.debug(LOG_PREFIX + "CN is not a DNS name; done");
+            return;  // CN does not look like a DNS name
+        }
+
+        SubjectAlternativeNameExtension san = (SubjectAlternativeNameExtension)
+            getExtension(PKIXExtensions.SubjectAlternativeName_Id.toString(), info);
+
+        if (san != null) {
+            // check for existing name matching CN
+            GeneralNames gns = san.getGeneralNames();
+            for (GeneralNameInterface gn : gns) {
+                if (gn instanceof GeneralName)
+                    gn = ((GeneralName) gn).unwrap();
+                if (gn instanceof DNSName) {
+                    String dnsName = ((DNSName) gn).getValue();
+                    if (cn.equalsIgnoreCase(dnsName)) {
+                        CMS.debug(LOG_PREFIX
+                            + "CN already has corresponding SAN dNSName; done");
+                        return;  // CN is already in SAN
+                    }
+                }
+            }
+            gns.add(new DNSName(cn));  // add CN to SAN
+
+            // reset extension value (encoded value may have been cached)
+            san.setGeneralNames(gns);
+            CMS.debug(LOG_PREFIX + "added CN to SAN; done");
+        } else {
+            GeneralNames gns = new GeneralNames();
+            gns.add(new DNSName(cn));
+            try {
+                san = new SubjectAlternativeNameExtension(gns);
+                addExtension(
+                    PKIXExtensions.SubjectAlternativeName_Id.toString(), san, info);
+            } catch (IOException e) {
+                CMS.debug(LOG_PREFIX + "failed to construct SAN ext: " + e);
+                return;
+            }
+            CMS.debug(LOG_PREFIX + "added SAN extension containing CN; done");
+        }
+    }
+
+    public String getText(Locale locale) {
+        return "This default add the Subject DN Common Name to the Subject "
+            + "Alternative Name extension, if it looks like a DNS name.";
+    }
+
+    public IDescriptor getValueDescriptor(Locale locale, String name) {
+        return null;
+    }
+
+    public String getValue(String name, Locale locale, X509CertInfo info) {
+        return null;
+    }
+
+    public void setValue(
+            String name, Locale locale, X509CertInfo info, String value) {
+    }
+
+    /** Validate DNS name syntax per Section 3.5 of RFC 1034
+     * and Section 2.1 of RFC 1123, and the additional rules
+     * of RFC 5280 Section 4.2.1.6.
+     *
+     * Further to those rules, we also ignore CNs that are valid
+     * DNS names but which only have a single part (e.g. TLDs or
+     * host short names).
+     */
+    public static boolean isValidDNSName(String s) {
+        if (s == null)
+            return false;
+
+        if (s.length() < 1 || s.length() > 255)
+            return false;
+
+        String[] parts = s.split("\\.");
+
+        if (parts.length < 2)
+            return false;
+
+        for (int i = 0; i < parts.length; i++) {
+            char[] cs = parts[i].toCharArray();
+
+            if (cs.length < 1 || cs.length > 63)
+                return false;
+
+            if (!isLetter(cs[0]))
+                return false;
+
+            if (!isLetDig(cs[cs.length - 1]))
+                return false;
+
+            for (int j = 0; j < cs.length; j++) {
+                if (!isLetDigHyp(cs[j]))
+                    return false;
+            }
+        }
+
+        return true;
+    }
+
+    public static boolean isLetter(char c) {
+        return c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z';
+    }
+
+    public static boolean isDigit(char c) {
+        return c >= '0' && c <= '9';
+    }
+
+    public static boolean isLetDig(char c) {
+        return isLetter(c) || isDigit(c);
+    }
+
+    public static boolean isLetDigHyp(char c) {
+        return isLetDig(c) || c == '-';
+    }
+
+}
diff --git a/base/server/upgrade/10.4.0/03-AddCommonNameToSANDefaultToRegistry b/base/server/upgrade/10.4.0/03-AddCommonNameToSANDefaultToRegistry
new file mode 100755
index 0000000000000000000000000000000000000000..5bb7573a9e744e21d4d3b21a6ace7514b338b09c
--- /dev/null
+++ b/base/server/upgrade/10.4.0/03-AddCommonNameToSANDefaultToRegistry
@@ -0,0 +1,65 @@
+#!/usr/bin/python
+# Authors:
+#     Fraser Tweedale <ftweedal at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Copyright (C) 2017 Red Hat, Inc.
+# All rights reserved.
+
+from __future__ import absolute_import
+import os.path
+from pki.server.upgrade import PKIServerUpgradeScriptlet
+
+
+class AddCommonNameToSANDefaultToRegistry(PKIServerUpgradeScriptlet):
+
+    new_config = {
+        'defaultPolicy.commonNameToSANDefaultImpl.class':
+            'com.netscape.cms.profile.def.CommonNameToSANDefault',
+        'defaultPolicy.commonNameToSANDefaultImpl.desc':
+            'Copy Common Name to Subject Alternative Name',
+        'defaultPolicy.commonNameToSANDefaultImpl.name':
+            'Copy Common Name to Subject Alternative Name',
+    }
+
+    default_name = 'commonNameToSANDefaultImpl'
+
+    def __init__(self):
+        super(AddCommonNameToSANDefaultToRegistry, self).__init__()
+        self.message = 'Add CommonNameToSANDefault to registry'
+
+    def upgrade_subsystem(self, instance, subsystem):
+        if subsystem.name == 'ca':
+            self.add_new_entries(instance, subsystem)
+
+    def add_new_entries(self, instance, subsystem):  # pylint: disable=W0613
+        filename = os.path.join(subsystem.conf_dir, 'registry.cfg')
+        self.backup(filename)
+
+        properties = pki.PropertyFile(filename)
+        properties.read()
+
+        # add default to default list
+        defaults = properties.get('defaultPolicy.ids').split(',')
+        if self.default_name in defaults:
+            return  # update not required
+
+        defaults.append(self.default_name)
+        properties.set('defaultPolicy.ids', ','.join(defaults))
+
+        for k, v in self.new_config.items():
+            properties.set(k, v)
+
+        properties.write()
-- 
2.9.3



More information about the Pki-devel mailing list