summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/java-tools/src/com/netscape/cmstools/client/ClientCLI.java1
-rw-r--r--base/java-tools/src/com/netscape/cmstools/client/ClientCertValidateCLI.java194
-rw-r--r--base/server/python/pki/server/__init__.py2
-rw-r--r--base/server/python/pki/server/cli/subsystem.py118
4 files changed, 315 insertions, 0 deletions
diff --git a/base/java-tools/src/com/netscape/cmstools/client/ClientCLI.java b/base/java-tools/src/com/netscape/cmstools/client/ClientCLI.java
index f09ea74e9..8bafd84f6 100644
--- a/base/java-tools/src/com/netscape/cmstools/client/ClientCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/client/ClientCLI.java
@@ -39,6 +39,7 @@ public class ClientCLI extends CLI {
addModule(new ClientCertRemoveCLI(this));
addModule(new ClientCertRequestCLI(this));
addModule(new ClientCertShowCLI(this));
+ addModule(new ClientCertValidateCLI(this));
}
public String getFullName() {
diff --git a/base/java-tools/src/com/netscape/cmstools/client/ClientCertValidateCLI.java b/base/java-tools/src/com/netscape/cmstools/client/ClientCertValidateCLI.java
new file mode 100644
index 000000000..3988c71e2
--- /dev/null
+++ b/base/java-tools/src/com/netscape/cmstools/client/ClientCertValidateCLI.java
@@ -0,0 +1,194 @@
+// --- 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) 2016 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package com.netscape.cmstools.client;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Option;
+import org.apache.commons.lang.StringUtils;
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.CryptoManager.CertificateUsage;
+
+import com.netscape.cmstools.cli.CLI;
+
+/**
+ * @author Ade Lee
+ */
+public class ClientCertValidateCLI extends CLI {
+
+ public ClientCLI clientCLI;
+
+ public ClientCertValidateCLI(ClientCLI clientCLI) {
+ super("cert-validate", "Validate certificate", clientCLI);
+ this.clientCLI = clientCLI;
+
+ createOptions();
+ }
+
+ public void createOptions() {
+ Option option = new Option(null, "certusage", true, "Certificate usage.");
+ option.setArgName("certusage");
+ options.addOption(option);
+ }
+
+ public void printHelp() {
+ formatter.printHelp(getFullName() + " nickname", options);
+ }
+
+ public void execute(String[] args) throws Exception {
+ // Always check for "--help" prior to parsing
+ if (Arrays.asList(args).contains("--help")) {
+ // Display usage
+ printHelp();
+ System.exit(0);
+ }
+
+ CommandLine cmd = null;
+
+ try {
+ cmd = parser.parse(options, args);
+
+ } catch (Exception e) {
+ System.err.println("Error: " + e.getMessage());
+ printHelp();
+ System.exit(-1);
+ }
+
+ String[] cmdArgs = cmd.getArgs();
+
+ if (cmdArgs.length != 1) {
+ System.err.println("Error: Invalid number of arguments.");
+ printHelp();
+ System.exit(-1);
+ }
+
+ // Get nickname from command argument.
+ String nickname = cmdArgs[0];
+
+ // get usages from options
+ String certusage = cmd.getOptionValue("certusage");
+ boolean isValid = false;
+
+ try {
+ isValid = verifySystemCertByNickname(nickname, certusage);
+ } catch (Exception e) {
+ System.err.println("Certificate verification failed: " + e);
+ isValid = false;
+ }
+
+ if (isValid) {
+ System.exit(0);
+ } else {
+ System.exit(1);
+ }
+ }
+
+ public boolean verifySystemCertByNickname(String nickname, String certusage) throws Exception {
+ CertificateUsage cu = getCertificateUsage(certusage);
+ int ccu = 0;
+
+ if (cu == null) {
+ throw new Exception("Unsupported certificate usage " + certusage +
+ " in certificate " + nickname);
+ }
+
+ CryptoManager cm = CryptoManager.getInstance();
+ if (cu.getUsage() != CryptoManager.CertificateUsage.CheckAllUsages.getUsage()) {
+ if (cm.isCertValid(nickname, true, cu)) {
+ System.out.println("Valid certificate: " + nickname);
+ return true;
+ } else {
+ System.out.println("Invalid certificate: " + nickname);
+ return false;
+ }
+
+ } else {
+ // check all possible usages
+ ccu = cm.isCertValid(nickname, true);
+ if (ccu == CertificateUsage.basicCertificateUsages) {
+ /* cert is good for nothing */
+ System.out.println("Cert is good for nothing: " + nickname);
+ return false;
+ } else {
+ List<String> usages = new ArrayList<String>();
+ if ((ccu & CryptoManager.CertificateUsage.SSLServer.getUsage()) != 0)
+ usages.add("SSLServer");
+ if ((ccu & CryptoManager.CertificateUsage.SSLClient.getUsage()) != 0)
+ usages.add("SSLClient");
+ if ((ccu & CryptoManager.CertificateUsage.SSLServerWithStepUp.getUsage()) != 0)
+ usages.add("SSLServerWithStepUp");
+ if ((ccu & CryptoManager.CertificateUsage.SSLCA.getUsage()) != 0)
+ usages.add("SSLCA");
+ if ((ccu & CryptoManager.CertificateUsage.EmailSigner.getUsage()) != 0)
+ usages.add("EmailSigner");
+ if ((ccu & CryptoManager.CertificateUsage.EmailRecipient.getUsage()) != 0)
+ usages.add("EmailRecipient");
+ if ((ccu & CryptoManager.CertificateUsage.ObjectSigner.getUsage()) != 0)
+ usages.add("ObjectSigner");
+ if ((ccu & CryptoManager.CertificateUsage.UserCertImport.getUsage()) != 0)
+ usages.add("UserCertImport");
+ if ((ccu & CryptoManager.CertificateUsage.VerifyCA.getUsage()) != 0)
+ usages.add("VerifyCA");
+ if ((ccu & CryptoManager.CertificateUsage.ProtectedObjectSigner.getUsage()) != 0)
+ usages.add("ProtectedObjectSigner");
+ if ((ccu & CryptoManager.CertificateUsage.StatusResponder.getUsage()) != 0)
+ usages.add("StatusResponder");
+ if ((ccu & CryptoManager.CertificateUsage.AnyCA.getUsage()) != 0)
+ usages.add("AnyCA");
+ System.out.println("Cert has the following usages: " + StringUtils.join(usages, ','));
+ return true;
+ }
+ }
+ }
+
+ public CertificateUsage getCertificateUsage(String certusage) {
+ CertificateUsage cu = null;
+ if ((certusage == null) || certusage.equals(""))
+ cu = CryptoManager.CertificateUsage.CheckAllUsages;
+ else if (certusage.equalsIgnoreCase("CheckAllUsages"))
+ cu = CryptoManager.CertificateUsage.CheckAllUsages;
+ else if (certusage.equalsIgnoreCase("SSLServer"))
+ cu = CryptoManager.CertificateUsage.SSLServer;
+ else if (certusage.equalsIgnoreCase("SSLServerWithStepUp"))
+ cu = CryptoManager.CertificateUsage.SSLServerWithStepUp;
+ else if (certusage.equalsIgnoreCase("SSLClient"))
+ cu = CryptoManager.CertificateUsage.SSLClient;
+ else if (certusage.equalsIgnoreCase("SSLCA"))
+ cu = CryptoManager.CertificateUsage.SSLCA;
+ else if (certusage.equalsIgnoreCase("AnyCA"))
+ cu = CryptoManager.CertificateUsage.AnyCA;
+ else if (certusage.equalsIgnoreCase("StatusResponder"))
+ cu = CryptoManager.CertificateUsage.StatusResponder;
+ else if (certusage.equalsIgnoreCase("ObjectSigner"))
+ cu = CryptoManager.CertificateUsage.ObjectSigner;
+ else if (certusage.equalsIgnoreCase("UserCertImport"))
+ cu = CryptoManager.CertificateUsage.UserCertImport;
+ else if (certusage.equalsIgnoreCase("ProtectedObjectSigner"))
+ cu = CryptoManager.CertificateUsage.ProtectedObjectSigner;
+ else if (certusage.equalsIgnoreCase("VerifyCA"))
+ cu = CryptoManager.CertificateUsage.VerifyCA;
+ else if (certusage.equalsIgnoreCase("EmailSigner"))
+ cu = CryptoManager.CertificateUsage.EmailSigner;
+
+ return cu;
+ }
+}
diff --git a/base/server/python/pki/server/__init__.py b/base/server/python/pki/server/__init__.py
index 64688b3c4..1c590c37e 100644
--- a/base/server/python/pki/server/__init__.py
+++ b/base/server/python/pki/server/__init__.py
@@ -156,6 +156,8 @@ class PKISubsystem(object):
'%s.%s.cert' % (self.name, cert_id), None)
cert['request'] = self.config.get(
'%s.%s.certreq' % (self.name, cert_id), None)
+ cert['certusage'] = self.config.get(
+ '%s.cert.%s.certusage' % (self.name, cert_id), None)
return cert
def update_subsystem_cert(self, cert):
diff --git a/base/server/python/pki/server/cli/subsystem.py b/base/server/python/pki/server/cli/subsystem.py
index 03d48f926..6d60468a6 100644
--- a/base/server/python/pki/server/cli/subsystem.py
+++ b/base/server/python/pki/server/cli/subsystem.py
@@ -24,8 +24,11 @@ import base64
import getopt
import getpass
import nss.nss as nss
+import os
import string
+import subprocess
import sys
+from tempfile import mkstemp
import pki.cli
import pki.nssdb
@@ -299,6 +302,7 @@ class SubsystemCertCLI(pki.cli.CLI):
self.add_module(SubsystemCertShowCLI())
self.add_module(SubsystemCertExportCLI())
self.add_module(SubsystemCertUpdateCLI())
+ self.add_module(SubsystemCertValidateCLI())
@staticmethod
def print_subsystem_cert(cert, show_all=False):
@@ -713,3 +717,117 @@ class SubsystemCertUpdateCLI(pki.cli.CLI):
self.print_message('Updated "%s" subsystem certificate' % cert_id)
SubsystemCertCLI.print_subsystem_cert(subsystem_cert)
+
+
+class SubsystemCertValidateCLI(pki.cli.CLI):
+
+ def __init__(self):
+ super(SubsystemCertValidateCLI, self).__init__(
+ 'validate', 'Validate subsystem certificates')
+
+ def usage(self):
+ print('Usage: pki-server subsystem-cert-validate [OPTIONS] <subsystem ID> [<cert_id>]')
+ print()
+ print(' -i, --instance <instance ID> Instance ID (default: pki-tomcat).')
+ print(' -v, --verbose Run in verbose mode.')
+ print(' --help Show help message.')
+ print()
+
+ def execute(self, argv):
+
+ try:
+ opts, args = getopt.gnu_getopt(argv, 'i:v', [
+ 'instance=',
+ 'verbose', 'help'])
+
+ except getopt.GetoptError as e:
+ print('ERROR: ' + str(e))
+ self.usage()
+ sys.exit(1)
+
+ if len(args) < 1:
+ print('ERROR: missing subsystem ID')
+ self.usage()
+ sys.exit(1)
+
+ subsystem_name = args[0]
+
+ if len(args) >=2:
+ cert_id = args[1]
+ else:
+ cert_id = None
+
+ instance_name = 'pki-tomcat'
+
+ for o, a in opts:
+ if o in ('-i', '--instance'):
+ instance_name = a
+
+ elif o in ('-v', '--verbose'):
+ self.set_verbose(True)
+
+ elif o == '--help':
+ self.print_help()
+ sys.exit()
+
+ else:
+ self.print_message('ERROR: unknown option ' + o)
+ self.usage()
+ sys.exit(1)
+
+ instance = pki.server.PKIInstance(instance_name)
+ instance.load()
+
+ subsystem = instance.get_subsystem(subsystem_name)
+
+ if cert_id is not None:
+ certs = [subsystem.get_subsystem_cert(cert_id)]
+ else:
+ certs = subsystem.find_system_certs()
+
+ certs_valid = True
+ for cert in certs:
+ token = cert['token']
+
+ # get token password and store in temporary file
+ if token == 'Internal Key Storage Token':
+ passwd = instance.get_password('internal')
+ else:
+ passwd = instance.get_password("hardware-%s" % token)
+
+ pwfile_handle, pwfile_path = mkstemp()
+ os.write(pwfile_handle, passwd)
+ os.close(pwfile_handle)
+
+ cmd = ['pki', '-d', instance.nssdb_dir,
+ '-W', pwfile_path ]
+
+ if token != 'Internal Key Storage Token':
+ cmd.extend(['--token', token])
+
+ cmd.extend(
+ ['client-cert-validate',
+ cert['nickname'],
+ '--certusage', cert['certusage']]
+ )
+
+ try:
+ subprocess.check_output(cmd, stderr=subprocess.STDOUT)
+ self.print_message("Valid certificate : %s" %cert['nickname'])
+ except subprocess.CalledProcessError as e:
+ certs_valid = False
+ if e.returncode == 1:
+ self.print_message("Invalid certificate: %s"
+ % cert['nickname'])
+ else:
+ self.print_message("Error in validating certificate: %s"
+ % cert['nickname'])
+ self.print_message(e.output)
+ finally:
+ os.unlink(pwfile_path)
+
+ if certs_valid:
+ sys.exit(0)
+ else:
+ sys.exit(1)
+