16193298 pkgrepo, pkgrecv and pkgsend need SSL support for publishing and info retrieval
authorErik Trauschke <Erik.Trauschke@oracle.com>
Thu, 21 Feb 2013 13:44:55 -0800
changeset 2864 96d3957712da
parent 2863 3ada267d5a98
child 2865 9dea0cb88920
16193298 pkgrepo, pkgrecv and pkgsend need SSL support for publishing and info retrieval
src/man/pkgrecv.1
src/man/pkgrepo.1
src/man/pkgsend.1
src/modules/client/transport/repo.py
src/pkgrepo.py
src/publish.py
src/pull.py
src/tests/cli/t_https.py
src/tests/cli/t_pkgrecv.py
src/tests/cli/t_pkgrepo.py
src/tests/cli/t_pkgsend.py
src/tests/pkg5unittest.py
src/tests/ro_data/signing_certs/generate_certs.py
src/tests/ro_data/signing_certs/produced/combined_cas.pem
--- a/src/man/pkgrecv.1	Wed Feb 20 19:25:25 2013 -0800
+++ b/src/man/pkgrecv.1	Thu Feb 21 13:44:55 2013 -0800
@@ -1,5 +1,5 @@
 '\" te
-.\" Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+.\" Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
 .TH pkgrecv 1 "12 Oct 2012" "SunOS 5.12" "User Commands"
 .SH NAME
 pkgrecv \- Image Packaging System content retrieval utility
@@ -8,7 +8,8 @@
 .nf
 /usr/bin/pkgrecv [-s \fIsrc_uri\fR] [-a] [-d (\fIpath\fR|\fIdest_uri\fR)]
     [-c \fIcache_dir\fR] [-kr] [-m \fImatch\fR] [-n] [--raw]
-    [--key \fIkeyfile\fR --cert \fIcertfile\fR] (\fIfmri\fR|\fIpattern\fR) ...
+    [--key \fIsrc_key\fR --cert \fIsrc_cert\fR] [--dkey \fIdest_key\fR
+    --dcert \fIdest_cert\fR] (\fIfmri\fR|\fIpattern\fR) ...
 .fi
 
 .LP
@@ -158,7 +159,7 @@
 .ne 2
 .mk
 .na
-\fB\fB--cert\fR \fIcertfile\fR\fR
+\fB\fB--cert\fR \fIsrc_cert\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -169,7 +170,7 @@
 .ne 2
 .mk
 .na
-\fB\fB--key\fR \fIkeyfile\fR\fR
+\fB\fB--key\fR \fIsrc_key\fR\fR
 .ad
 .sp .6
 .RS 4n
@@ -180,6 +181,28 @@
 .ne 2
 .mk
 .na
+\fB\fB--dcert\fR \fIdest_cert\fR\fR
+.ad
+.sp .6
+.RS 4n
+Specify a client SSL certificate file to use for package publication to an HTTPS repository.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--dkey\fR \fIdest_key\fR\fR
+.ad
+.sp .6
+.RS 4n
+Specify a client SSL key file to use for package publication to an HTTPS repository.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
 \fB\fB--newest\fR\fR
 .ad
 .sp .6
--- a/src/man/pkgrepo.1	Wed Feb 20 19:25:25 2013 -0800
+++ b/src/man/pkgrepo.1	Thu Feb 21 13:44:55 2013 -0800
@@ -1,5 +1,5 @@
 '\" te
-.\" Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+.\" Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
 .TH pkgrepo 1 "22 Jun 2012" "SunOS 5.12" "User Commands"
 .SH NAME
 pkgrepo \- Image Packaging System repository management utility
@@ -17,31 +17,35 @@
 .LP
 .nf
 /usr/bin/pkgrepo get [-F \fIformat\fR] [-H] [-p \fIpublisher\fR ...]
-    -s \fIrepo_uri_or_path\fR [\fIsection/property\fR ...]
+    -s \fIrepo_uri_or_path\fR [--key \fIssl_key\fR ... --cert \fIssl_cert\fR ...]
+    [\fIsection/property\fR ...]
 .fi
 
 .LP
 .nf
 /usr/bin/pkgrepo info [-F \fIformat\fR] [-H] [-p \fIpublisher\fR ...]
-    -s \fIrepo_uri_or_path\fR
+    -s \fIrepo_uri_or_path\fR [--key \fIssl_key\fR ... --cert \fIssl_cert\fR ...]
 .fi
 
 .LP
 .nf
 /usr/bin/pkgrepo list [-F \fIformat\fR] [-H] [-p \fIpublisher\fR ...]
-    -s \fIrepo_uri_or_path\fR [\fIpkg_fmri_pattern\fR ...]
+    -s \fIrepo_uri_or_path\fR [--key \fIssl_key\fR ... --cert \fIssl_cert\fR ...]
+    [\fIpkg_fmri_pattern\fR ...]
 .fi
 
 .LP
 .nf
 /usr/bin/pkgrepo rebuild [-p \fIpublisher\fR ...]
-    -s \fIrepo_uri_or_path\fR [--no-catalog] [--no-index]
+    -s \fIrepo_uri_or_path\fR [--key \fIssl_key\fR ... --cert \fIssl_cert\fR ...]
+    [--no-catalog] [--no-index]
 .fi
 
 .LP
 .nf
 /usr/bin/pkgrepo refresh [-p \fIpublisher\fR ...]
-    -s \fIrepo_uri_or_path\fR [--no-catalog] [--no-index]
+    -s \fIrepo_uri_or_path\fR [--key \fIssl_key\fR ... --cert \fIssl_cert\fR ...]
+    [--no-catalog] [--no-index]
 .fi
 
 .LP
@@ -162,7 +166,7 @@
 .ne 2
 .mk
 .na
-\fB\fBpkgrepo get\fR [\fB-F\fR \fIformat\fR] [\fB-H\fR] [\fB-p\fR \fIpublisher\fR ...] \fB-s\fR \fIrepo_uri_or_path\fR [\fIsection/property\fR ...]\fR
+\fB\fBpkgrepo get\fR [\fB-F\fR \fIformat\fR] [\fB-H\fR] [\fB-p\fR \fIpublisher\fR ...] \fB-s\fR \fIrepo_uri_or_path\fR [\fB--key\fR \fIssl_key\fR ... \fB--cert\fR \fIssl_cert\fR ...] [\fIsection/property\fR ...]\fR
 .ad
 .sp .6
 .RS 4n
@@ -227,6 +231,28 @@
 .ne 2
 .mk
 .na
+\fB\fB--key\fR \fIssl_key\fR\fR
+.ad
+.sp .6
+.RS 4n
+Specify a client SSL key file to use for package retrieval from an HTTPS repository.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--cert\fR \fIssl_cert\fR\fR
+.ad
+.sp .6
+.RS 4n
+Specify a client SSL certificate file to use for package retrieval from an HTTPS repository.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
 \fB\fIsection/property\fR\fR
 .ad
 .sp .6
@@ -240,7 +266,7 @@
 .ne 2
 .mk
 .na
-\fB\fBpkgrepo info\fR [\fB-F\fR \fIformat\fR] [\fB-H\fR] [\fB-p\fR \fIpublisher\fR ...] \fB-s\fR \fIrepo_uri_or_path\fR\fR
+\fB\fBpkgrepo info\fR [\fB-F\fR \fIformat\fR] [\fB-H\fR] [\fB-p\fR \fIpublisher\fR ...] \fB-s\fR \fIrepo_uri_or_path\fR [\fB--key\fR \fIssl_key\fR ... \fB--cert\fR \fIssl_cert\fR ...]\fR
 .ad
 .sp .6
 .RS 4n
@@ -289,13 +315,35 @@
 Operate on the repository located at the given URI or file system path.
 .RE
 
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--key\fR \fIssl_key\fR\fR
+.ad
+.sp .6
+.RS 4n
+Specify a client SSL key file to use for package retrieval from an HTTPS repository.
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBpkgrepo list\fR [\fB-F\fR \fIformat\fR] [\fB-H\fR] [\fB-p\fR \fIpublisher\fR ...] \fB-s\fR \fIrepo_uri_or_path\fR [\fIpkg_fmri_pattern\fR ...]\fR
+\fB\fB--cert\fR \fIssl_cert\fR\fR
+.ad
+.sp .6
+.RS 4n
+Specify a client SSL certificate file to use for package retrieval from an HTTPS repository.
+.RE
+
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkgrepo list\fR [\fB-F\fR \fIformat\fR] [\fB-H\fR] [\fB-p\fR \fIpublisher\fR ...] \fB-s\fR \fIrepo_uri_or_path\fR [\fB--key\fR \fIssl_key\fR ... \fB--cert\fR \fIssl_cert\fR ...] [\fIpkg_fmri_pattern\fR ...]\fR
 .ad
 .sp .6
 .RS 4n
@@ -346,13 +394,35 @@
 Operate on the repository located at the given URI or file system path.
 .RE
 
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--key\fR \fIssl_key\fR\fR
+.ad
+.sp .6
+.RS 4n
+Specify a client SSL key file to use for package retrieval from an HTTPS repository.
 .RE
 
 .sp
 .ne 2
 .mk
 .na
-\fB\fBpkgrepo rebuild\fR [\fB-p\fR \fIpublisher\fR ...] \fB-s\fR \fIrepo_uri_or_path\fR [\fB--no-catalog\fR] [\fB--no-index\fR]\fR
+\fB\fB--cert\fR \fIssl_cert\fR\fR
+.ad
+.sp .6
+.RS 4n
+Specify a client SSL certificate file to use for package retrieval from an HTTPS repository.
+.RE
+
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fBpkgrepo rebuild\fR [\fB-p\fR \fIpublisher\fR ...] \fB-s\fR \fIrepo_uri_or_path\fR [\fB--key\fR \fIssl_key\fR ... \fB--cert\fR \fIssl_cert\fR ...] [\fB--no-catalog\fR] [\fB--no-index\fR]\fR
 .ad
 .sp .6
 .RS 4n
@@ -383,6 +453,28 @@
 .ne 2
 .mk
 .na
+\fB\fB--key\fR \fIssl_key\fR\fR
+.ad
+.sp .6
+.RS 4n
+Specify a client SSL key file to use for package retrieval from an HTTPS repository.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--cert\fR \fIssl_cert\fR\fR
+.ad
+.sp .6
+.RS 4n
+Specify a client SSL certificate file to use for package retrieval from an HTTPS repository.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
 \fB\fB--no-catalog\fR\fR
 .ad
 .sp .6
@@ -407,7 +499,7 @@
 .ne 2
 .mk
 .na
-\fB\fBpkgrepo refresh\fR [\fB-p\fR \fIpublisher\fR ...] \fB-s\fR \fIrepo_uri_or_path\fR [\fB--no-catalog\fR] [\fB--no-index\fR]\fR
+\fB\fBpkgrepo refresh\fR [\fB-p\fR \fIpublisher\fR ...] \fB-s\fR \fIrepo_uri_or_path\fR [\fB--key\fR \fIssl_key\fR ... \fB--cert\fR \fIssl_cert\fR ...] [\fB--no-catalog\fR] [\fB--no-index\fR]\fR
 .ad
 .sp .6
 .RS 4n
@@ -438,6 +530,28 @@
 .ne 2
 .mk
 .na
+\fB\fB--key\fR \fIssl_key\fR\fR
+.ad
+.sp .6
+.RS 4n
+Specify a client SSL key file to use for package retrieval from an HTTPS repository.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--cert\fR \fIssl_cert\fR\fR
+.ad
+.sp .6
+.RS 4n
+Specify a client SSL certificate file to use for package retrieval from an HTTPS repository.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
 \fB\fB--no-catalog\fR\fR
 .ad
 .sp .6
--- a/src/man/pkgsend.1	Wed Feb 20 19:25:25 2013 -0800
+++ b/src/man/pkgsend.1	Thu Feb 21 13:44:55 2013 -0800
@@ -1,5 +1,5 @@
 '\" te
-.\" Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+.\" Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
 .TH pkgsend 1 "12 Oct 2012" "SunOS 5.12" "User Commands"
 .SH NAME
 pkgsend \- Image Packaging System publication client
@@ -18,8 +18,8 @@
 .LP
 .nf
 /usr/bin/pkgsend publish [-b \fIbundle\fR ...] [-d \fIsource\fR ...]
-    [-s \fIrepo_uri_or_path\fR] [-T \fIpattern\fR] [--no-catalog]
-    [\fImanifest\fR ...]
+    [-s \fIrepo_uri_or_path\fR] [--key \fIssl_key\fR ... --cert \fIssl_cert\fR ...]
+    [-T \fIpattern\fR] [--no-catalog] [\fImanifest\fR ...]
 .fi
 
 .SH DESCRIPTION
@@ -146,7 +146,7 @@
 .ne 2
 .mk
 .na
-\fB\fBpkgsend publish\fR [\fB-b\fR \fIbundle\fR ...] [\fB-d\fR \fIsource\fR ...] [\fB-s\fR \fIrepo_uri_or_path\fR] [\fB-T\fR \fIpattern\fR] [\fB--no-catalog\fR] [\fImanifest\fR ...]\fR
+\fB\fBpkgsend publish\fR [\fB-b\fR \fIbundle\fR ...] [\fB-d\fR \fIsource\fR ...] [\fB-s\fR \fIrepo_uri_or_path\fR] [\fB--key\fR \fIssl_key\fR ... \fB--cert\fR \fIssl_cert\fR ...] [\fB-T\fR \fIpattern\fR] [\fB--no-catalog\fR] [\fImanifest\fR ...]\fR
 .ad
 .sp .6
 .RS 4n
@@ -190,6 +190,28 @@
 .ne 2
 .mk
 .na
+\fB\fB--key\fR \fIssl_key\fR\fR
+.ad
+.sp .6
+.RS 4n
+Specify a client SSL key file to use for package retrieval from an HTTPS repository.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB--cert\fR \fIssl_cert\fR\fR
+.ad
+.sp .6
+.RS 4n
+Specify a client SSL certificate file to use for package retrieval from an HTTPS repository.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
 \fB\fB--no-catalog\fR\fR
 .ad
 .sp .6
--- a/src/modules/client/transport/repo.py	Wed Feb 20 19:25:25 2013 -0800
+++ b/src/modules/client/transport/repo.py	Thu Feb 21 13:44:55 2013 -0800
@@ -1115,12 +1115,14 @@
                     proxy=self._repouri.proxy)
 
         def _post_url(self, url, data=None, header=None, ccancel=None,
-            data_fobj=None, data_fp=None, failonerror=True):
+            data_fobj=None, data_fp=None, failonerror=True, progclass=None,
+            progtrack=None):
                 return self._engine.send_data(url, data=data, header=header,
                     sslcert=self._repouri.ssl_cert,
                     sslkey=self._repouri.ssl_key, repourl=self._url,
                     ccancel=ccancel, data_fobj=data_fobj,
                     data_fp=data_fp, failonerror=failonerror,
+                    progclass=progclass, progtrack=progtrack,
                     runtime_proxy=self._repouri.runtime_proxy,
                     proxy=self._repouri.proxy)
 
--- a/src/pkgrepo.py	Wed Feb 20 19:25:25 2013 -0800
+++ b/src/pkgrepo.py	Thu Feb 21 13:44:55 2013 -0800
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 PKG_CLIENT_NAME = "pkgrepo"
@@ -55,6 +55,7 @@
 import warnings
 
 from pkg.client import global_settings
+from pkg.client.debugvalues import DebugValues
 from pkg.misc import msg, PipeError
 import pkg
 import pkg.catalog
@@ -134,20 +135,20 @@
 
      pkgrepo add-publisher -s repo_uri_or_path publisher ...
 
-     pkgrepo get [-F format] [-p publisher ...] -s repo_uri_or_path
-         [section/property ...]
+     pkgrepo get [-F format] [-p publisher ...] -s repo_uri_or_path 
+         [--key ssl_key ... --cert ssl_cert ...] [section/property ...]
 
-     pkgrepo info [-F format] [-H] [-p publisher ...]
-         -s repo_uri_or_path
+     pkgrepo info [-F format] [-H] [-p publisher ...] -s repo_uri_or_path
+         [--key ssl_key ... --cert ssl_cert ...]
 
-     pkgrepo list [-F format] [-H] [-p publisher ...] -s repo_uri_or_path
-         [pkg_fmri_pattern ...]
+     pkgrepo list [-F format] [-H] [-p publisher ...] -s repo_uri_or_path 
+         [--key ssl_key ... --cert ssl_cert ...] [pkg_fmri_pattern ...]
 
-     pkgrepo rebuild [-p publisher ...] -s repo_uri_or_path
-         [--no-catalog] [--no-index]
+     pkgrepo rebuild [-p publisher ...] -s repo_uri_or_path [--key ssl_key ...
+         --cert ssl_cert ...] [--no-catalog] [--no-index]
 
-     pkgrepo refresh [-p publisher ...] -s repo_uri_or_path
-         [--no-catalog] [--no-index]
+     pkgrepo refresh [-p publisher ...] -s repo_uri_or_path [--key ssl_key ...
+         --cert ssl_cert ...] [--no-catalog] [--no-index]
 
      pkgrepo remove [-n] [-p publisher ...] -s repo_uri_or_path
          pkg_fmri_pattern ...
@@ -261,7 +262,8 @@
         return sr.Repository(read_only=read_only, root=path)
 
 
-def setup_transport(conf, subcommand=None, verbose=False):
+def setup_transport(conf, subcommand=None, verbose=False, ssl_key=None,
+    ssl_cert=None):
         repo_uri = conf.get("repo_uri", None)
         if not repo_uri:
                 usage(_("No repository location specified."), cmd=subcommand)
@@ -284,7 +286,7 @@
 
         # Configure target publisher.
         src_pub = transport.setup_publisher(str(repo_uri), "target", xport,
-            xport_cfg, remote_prefix=True)
+            xport_cfg, remote_prefix=True, ssl_key=ssl_key, ssl_cert=ssl_cert)
 
         return xport, src_pub, tmp_dir
 
@@ -398,8 +400,10 @@
         omit_headers = False
         out_format = "default"
         pubs = set()
+        key = None
+        cert = None
 
-        opts, pargs = getopt.getopt(args, "F:Hp:s:")
+        opts, pargs = getopt.getopt(args, "F:Hp:s:", ["key=", "cert="])
         for opt, arg in opts:
                 if opt == "-F":
                         out_format = arg
@@ -415,12 +419,17 @@
                         pubs.add(arg)
                 elif opt == "-s":
                         conf["repo_uri"] = parse_uri(arg)
+                elif opt == "--key":
+                        key = arg
+                elif opt == "--cert":
+                        cert = arg
 
         # Setup transport so configuration can be retrieved.
         if not conf.get("repo_uri", None):
                 usage(_("A package repository location must be provided "
                     "using -s."), cmd=subcommand)
-        xport, xpub, tmp_dir = setup_transport(conf, subcommand=subcommand)
+        xport, xpub, tmp_dir = setup_transport(conf, subcommand=subcommand,
+            ssl_key=key, ssl_cert=cert)
 
         # Get properties.
         if pubs:
@@ -660,8 +669,10 @@
         omit_headers = False
         out_format = "default"
         pubs = set()
+        key = None
+        cert = None
 
-        opts, pargs = getopt.getopt(args, "F:Hp:s:")
+        opts, pargs = getopt.getopt(args, "F:Hp:s:", ["key=", "cert="])
         for opt, arg in opts:
                 if opt == "-F":
                         if arg not in LISTING_FORMATS:
@@ -677,6 +688,10 @@
                         pubs.add(arg)
                 elif opt == "-s":
                         conf["repo_uri"] = parse_uri(arg)
+                elif opt == "--key":
+                        key = arg
+                elif opt == "--cert":
+                        cert = arg
 
         if pargs:
                 usage(_("command does not take operands"), cmd=subcommand)
@@ -685,7 +700,8 @@
         if not conf.get("repo_uri", None):
                 usage(_("A package repository location must be provided "
                     "using -s."), cmd=subcommand)
-        xport, xpub, tmp_dir = setup_transport(conf, subcommand=subcommand)
+        xport, xpub, tmp_dir = setup_transport(conf, subcommand=subcommand,
+            ssl_key=key, ssl_cert=cert)
 
         # Retrieve repository status information.
         stat_idx = xport.get_status(xpub)
@@ -760,8 +776,10 @@
         omit_headers = False
         out_format = "default"
         pubs = set()
+        key = None
+        cert = None
 
-        opts, pargs = getopt.getopt(args, "F:Hp:s:")
+        opts, pargs = getopt.getopt(args, "F:Hp:s:", ["key=", "cert="])
         for opt, arg in opts:
                 if opt == "-F":
                         out_format = arg
@@ -777,12 +795,18 @@
                         pubs.add(arg)
                 elif opt == "-s":
                         conf["repo_uri"] = parse_uri(arg)
+                elif opt == "--key":
+                        key = arg
+                elif opt == "--cert":
+                        cert = arg
+
 
         # Setup transport so configuration can be retrieved.
         if not conf.get("repo_uri", None):
                 usage(_("A package repository location must be provided "
                     "using -s."), cmd=subcommand)
-        xport, xpub, tmp_dir = setup_transport(conf, subcommand=subcommand)
+        xport, xpub, tmp_dir = setup_transport(conf, subcommand=subcommand,
+            ssl_key=key, ssl_cert=cert)
 
         rval, found, pub_data = _get_matching_pubs(subcommand, pubs, xport,
             xpub, out_format=out_format, use_transport=True)
@@ -914,8 +938,11 @@
         subcommand = "rebuild"
         build_catalog = True
         build_index = True
+        key = None
+        cert = None
 
-        opts, pargs = getopt.getopt(args, "p:s:", ["no-catalog", "no-index"])
+        opts, pargs = getopt.getopt(args, "p:s:", ["no-catalog", "no-index",
+            "key=", "cert="])
         pubs = set()
         for opt, arg in opts:
                 if opt == "-p":
@@ -929,6 +956,10 @@
                         build_catalog = False
                 elif opt == "--no-index":
                         build_index = False
+                elif opt == "--key":
+                        key = arg
+                elif opt == "--cert":
+                        cert = arg
 
         if pargs:
                 usage(_("command does not take operands"), cmd=subcommand)
@@ -950,7 +981,8 @@
                 elif build_index:
                         xport.publish_rebuild_indexes(xpub)
 
-        xport, xpub, tmp_dir = setup_transport(conf, subcommand=subcommand)
+        xport, xpub, tmp_dir = setup_transport(conf, subcommand=subcommand,
+            ssl_key=key, ssl_cert=cert)
         rval, found, pub_data = _get_matching_pubs(subcommand, pubs, xport,
             xpub)
         if rval == EXIT_OOPS:
@@ -970,8 +1002,11 @@
         subcommand = "refresh"
         add_content = True
         refresh_index = True
+        key = None
+        cert = None
 
-        opts, pargs = getopt.getopt(args, "p:s:", ["no-catalog", "no-index"])
+        opts, pargs = getopt.getopt(args, "p:s:", ["no-catalog", "no-index",
+            "key=", "cert="])
         pubs = set()
         for opt, arg in opts:
                 if opt == "-p":
@@ -985,6 +1020,10 @@
                         add_content = False
                 elif opt == "--no-index":
                         refresh_index = False
+                elif opt == "--key":
+                        key = arg
+                elif opt == "--cert":
+                        cert = arg
 
         if pargs:
                 usage(_("command does not take operands"), cmd=subcommand)
@@ -1006,7 +1045,8 @@
                 elif refresh_index:
                         xport.publish_refresh_indexes(xpub)
 
-        xport, xpub, tmp_dir = setup_transport(conf, subcommand=subcommand)
+        xport, xpub, tmp_dir = setup_transport(conf, subcommand=subcommand,
+            ssl_key=key, ssl_cert=cert)
         rval, found, pub_data = _get_matching_pubs(subcommand, pubs, xport,
             xpub)
         if rval == EXIT_OOPS:
@@ -1446,8 +1486,8 @@
         global_settings.client_name = PKG_CLIENT_NAME
 
         try:
-                opts, pargs = getopt.getopt(sys.argv[1:], "s:?",
-                    ["help"])
+                opts, pargs = getopt.getopt(sys.argv[1:], "s:D:?",
+                    ["help", "debug="])
         except getopt.GetoptError, e:
                 usage(_("illegal global option -- %s") % e.opt)
 
@@ -1458,6 +1498,14 @@
                         conf["repo_uri"] = parse_uri(arg)
                 elif opt in ("--help", "-?"):
                         show_usage = True
+                elif opt == "-D" or opt == "--debug":
+                        try:
+                                key, value = arg.split("=", 1)
+                        except (AttributeError, ValueError):
+                                usage(_("%(opt)s takes argument of form "
+                                   "name=value, not %(arg)s") % {
+                                   "opt":  opt, "arg": arg })
+                        DebugValues.set_value(key, value)
 
         subcommand = None
         if pargs:
--- a/src/publish.py	Wed Feb 20 19:25:25 2013 -0800
+++ b/src/publish.py	Thu Feb 21 13:44:55 2013 -0800
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 import fnmatch
@@ -85,7 +85,8 @@
 Packager subcommands:
         pkgsend generate [-T pattern] [--target file] source ...
         pkgsend publish [-b bundle ...] [-d source ...] [-s repo_uri_or_path]
-            [-T pattern] [--no-catalog] [manifest ...]
+            [-T pattern] [--key ssl_key ... --cert ssl_cert ...]
+            [--no-catalog] [manifest ...]
 
 Options:
         --help or -?    display usage message
@@ -296,12 +297,14 @@
         # --no-index is now silently ignored as the publication process no
         # longer builds search indexes automatically.
         opts, pargs = getopt.getopt(fargs, "b:d:s:T:", ["fmri-in-manifest",
-            "no-index", "no-catalog"])
+            "no-index", "no-catalog", "key=", "cert="])
 
         add_to_catalog = True
         basedirs = []
         bundles = []
         timestamp_files = []
+        key = None
+        cert = None
         for opt, arg in opts:
                 if opt == "-b":
                         bundles.append(arg)
@@ -315,6 +318,10 @@
                         timestamp_files.append(arg)
                 elif opt == "--no-catalog":
                         add_to_catalog = False
+                elif opt == "--key":
+                        key = arg
+                elif opt == "--cert":
+                        cert = arg
 
         if not repo_uri:
                 usage(_("A destination package repository must be provided "
@@ -380,7 +387,8 @@
                 error(_("Manifest does not set pkg.fmri"))
                 return 1
 
-        xport, pub = setup_transport_and_pubs(repo_uri)
+        xport, pub = setup_transport_and_pubs(repo_uri, ssl_key=key,
+            ssl_cert=cert)
         t = trans.Transaction(repo_uri, pkg_name=pkg_name,
             xport=xport, pub=pub)
         t.open()
@@ -686,14 +694,16 @@
                 return 1
         return 0
 
-def setup_transport_and_pubs(repo_uri, remote=True):
+def setup_transport_and_pubs(repo_uri, remote=True, ssl_key=None,
+    ssl_cert=None):
 
         if repo_uri.startswith("null:"):
                 return None, None
 
         xport, xport_cfg = transport.setup_transport()
         targ_pub = transport.setup_publisher(repo_uri, "default",
-            xport, xport_cfg, remote_prefix=remote)
+            xport, xport_cfg, remote_prefix=remote, ssl_key=ssl_key,
+            ssl_cert=ssl_cert)
 
         return xport, targ_pub
 
@@ -706,11 +716,11 @@
         show_usage = False
         global_settings.client_name = "pkgsend"
         try:
-                opts, pargs = getopt.getopt(sys.argv[1:], "s:D:?", ["help"])
+                opts, pargs = getopt.getopt(sys.argv[1:], "s:D:?", ["help", "debug="])
                 for opt, arg in opts:
                         if opt == "-s":
                                 repo_uri = arg
-                        elif opt == "-D":
+                        elif opt == "-D" or opt == "--debug":
                                 if arg == "allow-timestamp":
                                         key = arg
                                         value = True
--- a/src/pull.py	Wed Feb 20 19:25:25 2013 -0800
+++ b/src/pull.py	Thu Feb 21 13:44:55 2013 -0800
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 import calendar
@@ -92,7 +92,8 @@
         msg(_("""\
 Usage:
         pkgrecv [-s src_uri] [-a] [-d (path|dest_uri)] [-c cache_dir]
-            [-kr] [-m match] [-n] [--raw] [--key keyfile --cert certfile]
+            [-kr] [-m match] [-n] [--raw] [--key src_key --cert src_cert]
+            [--dkey dest_key --dcert dest_cert]
             (fmri|pattern) ...
         pkgrecv [-s src_repo_uri] --newest
 
@@ -145,10 +146,16 @@
                         perhaps by correcting file contents or providing
                         additional package metadata.
 
-        --key keyfile   Specify a client SSL key file to use for pkg retrieval.
+        --key src_key   Specify a client SSL key file to use for pkg retrieval.
+
+        --cert src_cert Specify a client SSL certificate file to use for pkg
+                        retrieval.
 
-        --cert certfile Specify a client SSL certificate file to use for pkg
-                        retrieval.
+        --dkey dest_key Specify a client SSL key file to use for pkg
+                        publication.
+
+        --dcert dest_cert Specify a client SSL certificate file to use for pkg
+                          publication.
 
 Environment:
         PKG_DEST        Destination directory or URI
@@ -357,6 +364,8 @@
         raw = False
         key = None
         cert = None
+        dkey = None
+        dcert = None
 
         temp_root = misc.config_temp_root()
 
@@ -369,7 +378,7 @@
 
         try:
                 opts, pargs = getopt.getopt(sys.argv[1:], "ac:D:d:hkm:nrs:",
-                    ["cert=", "key=", "newest", "raw"])
+                    ["cert=", "key=", "dcert=", "dkey=", "newest", "raw", "debug="])
         except getopt.GetoptError, e:
                 usage(_("Illegal option -- %s") % e.opt)
 
@@ -380,7 +389,7 @@
                         cache_dir = arg
                 elif opt == "-d":
                         target = arg
-                elif opt == "-D":
+                elif opt == "-D" or opt == "--debug":
                         if arg in ["plan", "transport"]:
                                 key = arg
                                 value = "True"
@@ -417,6 +426,10 @@
                         key = arg
                 elif opt == "--cert":
                         cert = arg
+                elif opt == "--dkey":
+                        dkey = arg
+                elif opt == "--dcert":
+                        dcert = arg
 
         if not list_newest and not target:
                 usage(_("a destination must be provided"))
@@ -456,7 +469,7 @@
 
         args = (pargs, target, list_newest, all_versions,
             all_timestamps, keep_compressed, raw, recursive, dry_run,
-            dest_xport_cfg, src_uri)
+            dest_xport_cfg, src_uri, dkey, dcert)
 
         if archive:
                 # Retrieving package data for archival requires a different mode
@@ -519,7 +532,8 @@
         return matches
 
 def archive_pkgs(pargs, target, list_newest, all_versions, all_timestamps,
-    keep_compresed, raw, recursive, dry_run, dest_xport_cfg, src_uri):
+    keep_compresed, raw, recursive, dry_run, dest_xport_cfg, src_uri, dkey,
+    dcert):
         """Retrieve source package data completely and then archive it."""
 
         global cache_dir, download_start, xport, xport_cfg
@@ -668,7 +682,8 @@
         return pkgdefs.EXIT_OK
 
 def transfer_pkgs(pargs, target, list_newest, all_versions, all_timestamps,
-    keep_compressed, raw, recursive, dry_run, dest_xport_cfg, src_uri):
+    keep_compressed, raw, recursive, dry_run, dest_xport_cfg, src_uri, dkey,
+    dcert):
         """Retrieve source package data and optionally republish it as each
         package is retrieved.
         """
@@ -714,7 +729,8 @@
 
                         # Setup target for transport.
                         targ_pub = transport.setup_publisher(target,
-                            src_pub.prefix, dest_xport, dest_xport_cfg)
+                            src_pub.prefix, dest_xport, dest_xport_cfg,
+                            ssl_key=dkey, ssl_cert=dcert)
 
                         # Files have to be decompressed for republishing.
                         keep_compressed = False
@@ -854,7 +870,8 @@
                         if not targ_pub:
                                 targ_pub = transport.setup_publisher(target,
                                     src_pub.prefix, dest_xport, dest_xport_cfg,
-                                    remote_prefix=True)
+                                    remote_prefix=True, ssl_key=dkey,
+                                    ssl_cert=dcert)
 
                         try:
                                 t = trans.Transaction(target, pkg_name=pkg_name,
--- a/src/tests/cli/t_https.py	Wed Feb 20 19:25:25 2013 -0800
+++ b/src/tests/cli/t_https.py	Thu Feb 21 13:44:55 2013 -0800
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 import sys
 
@@ -37,9 +37,8 @@
 from pkg.client.debugvalues import DebugValues
 from pkg.client.transport.exception import TransportFailures
 
-class TestHTTPS(pkg5unittest.ApacheDepotTestCase):
-        # Tests in this suite use the read only data directory.
-        need_ro_data = True
+
+class TestHTTPS(pkg5unittest.HTTPSTestClass):
 
         example_pkg10 = """
             open [email protected],5.11-0
@@ -48,107 +47,17 @@
 
         misc_files = ["tmp/example_file"]
 
-        def pkg(self, command, *args, **kwargs):
-                # The value for ssl_ca_file is pulled from DebugValues because
-                # ssl_ca_file needs to be set there so the api object calls work
-                # as desired.
-                command = "--debug ssl_ca_file=%s %s" % \
-                    (DebugValues["ssl_ca_file"], command)
-                return pkg5unittest.ApacheDepotTestCase.pkg(self, command,
-                    *args, **kwargs)
+        def setUp(self):
+                pub_name = "test"
 
-        def seed_ta_dir(self, certs, dest_dir=None):
-                if isinstance(certs, basestring):
-                        certs = [certs]
-                if not dest_dir:
-                        dest_dir = self.ta_dir
-                self.assert_(dest_dir)
-                self.assert_(self.raw_trust_anchor_dir)
-                for c in certs:
-                        name = "%s_cert.pem" % c
-                        portable.copyfile(
-                            os.path.join(self.raw_trust_anchor_dir, name),
-                            os.path.join(dest_dir, name))
-                        DebugValues["ssl_ca_file"] = os.path.join(dest_dir,
-                            name)
-
-        def setUp(self):
-                pkg5unittest.ApacheDepotTestCase.setUp(self, ["test"],
+                pkg5unittest.HTTPSTestClass.setUp(self, [pub_name],
                     start_depots=True)
-                self.testdata_dir = os.path.join(self.test_root, "testdata")
-                self.make_misc_files(self.misc_files)
-
-                self.durl1 = self.dcs[1].get_depot_url()
+                
                 self.rurl1 = self.dcs[1].get_repo_url()
 
-                # Set up the directories that apache needs.
-                self.apache_dir = os.path.join(self.test_root, "apache")
-                os.makedirs(self.apache_dir)
-                self.apache_log_dir = os.path.join(self.apache_dir,
-                    "apache_logs")
-                os.makedirs(self.apache_log_dir)
-                self.apache_content_dir = os.path.join(self.apache_dir,
-                    "apache_content")
-                self.pidfile = os.path.join(self.apache_dir, "httpd.pid")
-                self.common_config_dir = os.path.join(self.test_root,
-                    "apache-serve")
-
-                # Choose ports for apache to run on.
-                self.https_port = self.next_free_port
-                self.next_free_port += 1
-                self.proxy_port = self.next_free_port
-                self.next_free_port += 1
-                self.bad_proxy_port = self.next_free_port
-                self.next_free_port += 1
-
-                # Set up the paths to the certificates that will be needed.
-                self.path_to_certs = os.path.join(self.ro_data_root,
-                    "signing_certs", "produced")
-                self.keys_dir = os.path.join(self.path_to_certs, "keys")
-                self.cs_dir = os.path.join(self.path_to_certs,
-                    "code_signing_certs")
-                self.chain_certs_dir = os.path.join(self.path_to_certs,
-                    "chain_certs")
-                self.pub_cas_dir = os.path.join(self.path_to_certs,
-                    "publisher_cas")
-                self.inter_certs_dir = os.path.join(self.path_to_certs,
-                    "inter_certs")
-                self.raw_trust_anchor_dir = os.path.join(self.path_to_certs,
-                    "trust_anchors")
-                self.crl_dir = os.path.join(self.path_to_certs, "crl")
-
+                self.make_misc_files(self.misc_files)
                 self.pkgsend_bulk(self.rurl1, self.example_pkg10)
-
-                conf_dict = {
-                    "common_log_format": "%h %l %u %t \\\"%r\\\" %>s %b",
-                    "https_port": self.https_port,
-                    "proxy_port": self.proxy_port,
-                    "bad_proxy_port": self.bad_proxy_port,
-                    "log_locs": self.apache_log_dir,
-                    "pidfile": self.pidfile,
-                    "port": self.https_port,
-                    "proxied-server": self.durl1,
-                    "serve_root": self.apache_content_dir,
-                    "server-ssl-cert":os.path.join(self.cs_dir,
-                        "cs1_ta7_cert.pem"),
-                    "server-ssl-key":os.path.join(self.keys_dir,
-                        "cs1_ta7_key.pem"),
-                    "server-ca-cert":os.path.join(self.raw_trust_anchor_dir,
-                        "ta6_cert.pem"),
-                    "server-ca-taname": "ta6",
-                    "ssl-special": "%{SSL_CLIENT_I_DN_OU}",
-                }
-
-                self.https_conf_path = os.path.join(self.test_root,
-                    "https.conf")
-                with open(self.https_conf_path, "wb") as fh:
-                        fh.write(self.https_conf % conf_dict)
-                
-                ac = pkg5unittest.ApacheController(self.https_conf_path,
-                    self.https_port, self.common_config_dir, https=True,
-                    testcase=self)
-                self.register_apache_controller("default", ac)
-                self.acurl = self.ac.url
+                self.acurl = self.ac.url + "/%s" % pub_name 
                 # Our proxy is served by the same Apache controller, but uses
                 # a different port.
                 self.proxyurl = self.ac.url.replace("https", "http")
@@ -171,18 +80,18 @@
                 # contain the trust anchor to verify the server's identity.
                 self.pkg("set-publisher -k %(key)s -c %(cert)s -p %(url)s" % {
                     "url": self.acurl,
-                    "cert": os.path.join(self.cs_dir, "cs1_ta6_cert.pem"),
-                    "key": os.path.join(self.keys_dir, "cs1_ta6_key.pem"),
-                }, exit=1)
+                    "cert": os.path.join(self.cs_dir, self.get_cli_cert("test")),
+                    "key": os.path.join(self.keys_dir, self.get_cli_key("test")),
+                    }, exit=1)
 
                 # Add the trust anchor needed to verify the server's identity to
                 # the image.
                 self.seed_ta_dir("ta7")
                 self.pkg("set-publisher -k %(key)s -c %(cert)s -p %(url)s" % {
                     "url": self.acurl,
-                    "cert": os.path.join(self.cs_dir, "cs1_ta6_cert.pem"),
-                    "key": os.path.join(self.keys_dir, "cs1_ta6_key.pem"),
-                })
+                    "cert": os.path.join(self.cs_dir, self.get_cli_cert("test")),
+                    "key": os.path.join(self.keys_dir, self.get_cli_key("test")),
+                    })
                 api_obj = self.get_img_api_obj()
                 self._api_install(api_obj, ["example_pkg"])
 
@@ -214,8 +123,8 @@
                 self.pkg("set-publisher --proxy %(proxy)s "
                     "-k %(key)s -c %(cert)s -p %(url)s" % {
                     "url": self.acurl,
-                    "cert": os.path.join(self.cs_dir, "cs1_ta6_cert.pem"),
-                    "key": os.path.join(self.keys_dir, "cs1_ta6_key.pem"),
+                    "cert": os.path.join(self.cs_dir, self.get_cli_cert("test")),
+                    "key": os.path.join(self.keys_dir, self.get_cli_key("test")),
                     "proxy": self.proxyurl})
                 self.pkg("install example_pkg")
 
@@ -229,8 +138,8 @@
                 self.pkg("set-publisher --proxy %(proxy)s "
                     "-k %(key)s -c %(cert)s -p %(url)s" % {
                     "url": self.acurl,
-                    "cert": os.path.join(self.cs_dir, "cs1_ta6_cert.pem"),
-                    "key": os.path.join(self.keys_dir, "cs1_ta6_key.pem"),
+                    "cert": os.path.join(self.cs_dir, self.get_cli_cert("test")),
+                    "key": os.path.join(self.keys_dir, self.get_cli_key("test")),
                     "proxy": bad_proxyurl}, exit=1)
 
                 # Set the bad proxy in the image, verify we can't refresh,
@@ -239,8 +148,8 @@
                 self.pkg("set-publisher --no-refresh --proxy %(proxy)s "
                     "-k %(key)s -c %(cert)s -g %(url)s test" % {
                     "url": self.acurl,
-                    "cert": os.path.join(self.cs_dir, "cs1_ta6_cert.pem"),
-                    "key": os.path.join(self.keys_dir, "cs1_ta6_key.pem"),
+                    "cert": os.path.join(self.cs_dir, self.get_cli_cert("test")),
+                    "key": os.path.join(self.keys_dir, self.get_cli_key("test")),
                     "proxy": bad_proxyurl}, exit=0)
                 self.pkg("refresh", exit=1)
                 proxy_env = {"https_proxy": self.proxyurl}
@@ -248,279 +157,6 @@
                 self.pkg("install example_pkg", env_arg=proxy_env)
 
 
-        https_conf = """\
-# Configuration and logfile names: If the filenames you specify for many
-# of the server's control files begin with "/" (or "drive:/" for Win32), the
-# server will use that explicit path.  If the filenames do *not* begin
-# with "/", the value of ServerRoot is prepended -- so "/var/apache2/2.2/logs/foo_log"
-# with ServerRoot set to "/usr/apache2/2.2" will be interpreted by the
-# server as "/usr/apache2/2.2//var/apache2/2.2/logs/foo_log".
-
-#
-# ServerRoot: The top of the directory tree under which the server's
-# configuration, error, and log files are kept.
-#
-# Do not add a slash at the end of the directory path.  If you point
-# ServerRoot at a non-local disk, be sure to point the LockFile directive
-# at a local disk.  If you wish to share the same ServerRoot for multiple
-# httpd daemons, you will need to change at least LockFile and PidFile.
-#
-ServerRoot "/usr/apache2/2.2"
-
-PidFile "%(pidfile)s"
-
-#
-# Listen: Allows you to bind Apache to specific IP addresses and/or
-# ports, instead of the default. See also the <VirtualHost>
-# directive.
-#
-# Change this to Listen on specific IP addresses as shown below to 
-# prevent Apache from glomming onto all bound IP addresses.
-#
-Listen 0.0.0.0:%(https_port)s
-
-# We also make ourselves a general-purpose proxy. This is not needed for the
-# SSL reverse-proxying to the pkg.depotd, but allows us to test that pkg(1)
-# can communicate to HTTPS origins using a proxy.
-Listen 0.0.0.0:%(proxy_port)s
-Listen 0.0.0.0:%(bad_proxy_port)s
-
-#
-# Dynamic Shared Object (DSO) Support
-#
-# To be able to use the functionality of a module which was built as a DSO you
-# have to place corresponding `LoadModule' lines within the appropriate 
-# (32-bit or 64-bit module) /etc/apache2/2.2/conf.d/modules-*.load file so that
-# the directives contained in it are actually available _before_ they are used.
-#
-<IfDefine 64bit>
-Include /etc/apache2/2.2/conf.d/modules-64.load
-</IfDefine>
-<IfDefine !64bit>
-Include /etc/apache2/2.2/conf.d/modules-32.load
-</IfDefine>
-
-<IfModule !mpm_netware_module>
-#
-# If you wish httpd to run as a different user or group, you must run
-# httpd as root initially and it will switch.  
-#
-# User/Group: The name (or #number) of the user/group to run httpd as.
-# It is usually good practice to create a dedicated user and group for
-# running httpd, as with most system services.
-#
-User webservd
-Group webservd
-
-</IfModule>
-
-# 'Main' server configuration
-#
-# The directives in this section set up the values used by the 'main'
-# server, which responds to any requests that aren't handled by a
-# <VirtualHost> definition.  These values also provide defaults for
-# any <VirtualHost> containers you may define later in the file.
-#
-# All of these directives may appear inside <VirtualHost> containers,
-# in which case these default settings will be overridden for the
-# virtual host being defined.
-#
-
-#
-# ServerName gives the name and port that the server uses to identify itself.
-# This can often be determined automatically, but we recommend you specify
-# it explicitly to prevent problems during startup.
-#
-# If your host doesn't have a registered DNS name, enter its IP address here.
-#
-ServerName 127.0.0.1
-
-#
-# DocumentRoot: The directory out of which you will serve your
-# documents. By default, all requests are taken from this directory, but
-# symbolic links and aliases may be used to point to other locations.
-#
-DocumentRoot "/"
-
-#
-# Each directory to which Apache has access can be configured with respect
-# to which services and features are allowed and/or disabled in that
-# directory (and its subdirectories). 
-#
-# First, we configure the "default" to be a very restrictive set of 
-# features.  
-#
-<Directory />
-    Options None
-    AllowOverride None
-    Order deny,allow
-    Deny from all
-</Directory>
-
-#
-# Note that from this point forward you must specifically allow
-# particular features to be enabled - so if something's not working as
-# you might expect, make sure that you have specifically enabled it
-# below.
-#
-
-#
-# This should be changed to whatever you set DocumentRoot to.
-#
-
-#
-# DirectoryIndex: sets the file that Apache will serve if a directory
-# is requested.
-#
-<IfModule dir_module>
-    DirectoryIndex index.html
-</IfModule>
-
-#
-# The following lines prevent .htaccess and .htpasswd files from being 
-# viewed by Web clients. 
-#
-<FilesMatch "^\.ht">
-    Order allow,deny
-    Deny from all
-    Satisfy All
-</FilesMatch>
-
-#
-# ErrorLog: The location of the error log file.
-# If you do not specify an ErrorLog directive within a <VirtualHost>
-# container, error messages relating to that virtual host will be
-# logged here.  If you *do* define an error logfile for a <VirtualHost>
-# container, that host's errors will be logged there and not here.
-#
-ErrorLog "%(log_locs)s/error_log"
-
-#
-# LogLevel: Control the number of messages logged to the error_log.
-# Possible values include: debug, info, notice, warn, error, crit,
-# alert, emerg.
-#
-LogLevel debug
-
-
-
-<IfModule log_config_module>
-    #
-    # The following directives define some format nicknames for use with
-    # a CustomLog directive (see below).
-    #
-    LogFormat "%(common_log_format)s" common
-    LogFormat "PROXY %(common_log_format)s" proxylog
-
-    #
-    # The location and format of the access logfile (Common Logfile Format).
-    # If you do not define any access logfiles within a <VirtualHost>
-    # container, they will be logged here.  Contrariwise, if you *do*
-    # define per-<VirtualHost> access logfiles, transactions will be
-    # logged therein and *not* in this file.
-    #
-    CustomLog "%(log_locs)s/access_log" common
-</IfModule>
-
-#
-# DefaultType: the default MIME type the server will use for a document
-# if it cannot otherwise determine one, such as from filename extensions.
-# If your server contains mostly text or HTML documents, "text/plain" is
-# a good value.  If most of your content is binary, such as applications
-# or images, you may want to use "application/octet-stream" instead to
-# keep browsers from trying to display binary files as though they are
-# text.
-#
-DefaultType text/plain
-
-<IfModule mime_module>
-    #
-    # TypesConfig points to the file containing the list of mappings from
-    # filename extension to MIME-type.
-    #
-    TypesConfig /etc/apache2/2.2/mime.types
-
-    #
-    # AddType allows you to add to or override the MIME configuration
-    # file specified in TypesConfig for specific file types.
-    #
-    AddType application/x-compress .Z
-    AddType application/x-gzip .gz .tgz
-
-    # Add a new mime.type for .p5i file extension so that clicking on
-    # this file type on a web page launches PackageManager in a Webinstall mode.
-    AddType application/vnd.pkg5.info .p5i
-</IfModule>
-
-#
-# Note: The following must must be present to support
-#       starting without SSL on platforms with no /dev/random equivalent
-#       but a statically compiled-in mod_ssl.
-#
-<IfModule ssl_module>
-SSLRandomSeed startup builtin
-SSLRandomSeed connect builtin
-</IfModule>
-
-<VirtualHost 0.0.0.0:%(https_port)s>
-        AllowEncodedSlashes On
-        ProxyRequests Off
-        MaxKeepAliveRequests 10000
-
-        SSLEngine On
-
-        # Cert paths
-        SSLCertificateFile %(server-ssl-cert)s
-        SSLCertificateKeyFile %(server-ssl-key)s
-
-        # Combined product CA certs for client verification
-        SSLCACertificateFile %(server-ca-cert)s
-
-	SSLVerifyClient require
-
-        <Location />
-                SSLVerifyDepth 1
-
-	        # The client's certificate must pass verification, and must have
-	        # a CN which matches this repository.
-                SSLRequire ( %(ssl-special)s =~ m/%(server-ca-taname)s/ )
-
-                # set max to number of threads in depot
-                ProxyPass %(proxied-server)s/ nocanon max=500
-        </Location>
-</VirtualHost>
-
-#
-# We configure this Apache instance as a general-purpose HTTP proxy, accepting
-# requests from localhost, and allowing CONNECTs to our HTTPS port
-#
-<VirtualHost 0.0.0.0:%(proxy_port)s>
-        <Proxy *>
-                Order Deny,Allow
-                Deny from all
-                Allow from 127.0.0.1
-        </Proxy>
-        AllowCONNECT %(https_port)s
-        ProxyRequests on
-        CustomLog "%(log_locs)s/proxy_access_log" proxylog
-</VirtualHost>
-
-<VirtualHost 0.0.0.0:%(bad_proxy_port)s>
-        <Proxy *>
-                Order Deny,Allow
-                Deny from all
-                Allow from 127.0.0.1
-        </Proxy>
-#  We purposely prevent this proxy from being able to connect to our SSL
-#  port, making sure that when we point pkg(1) to this bad proxy, operations
-#  will fail - the following line is commented out:
-#        AllowCONNECT %(https_port)s
-        ProxyRequests on
-        CustomLog "%(log_locs)s/badproxy_access_log" proxylog
-
-</VirtualHost>
-"""
-
 class TestDepotHTTPS(pkg5unittest.SingleDepotTestCase):
         # Tests in this suite use the read only data directory.
         need_ro_data = True
--- a/src/tests/cli/t_pkgrecv.py	Wed Feb 20 19:25:25 2013 -0800
+++ b/src/tests/cli/t_pkgrecv.py	Thu Feb 21 13:44:55 2013 -0800
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 import testutils
@@ -787,5 +787,151 @@
                         __test_rec(duri, arg_string, self.published[4:7])
 
 
+class TestPkgrecvHTTPS(pkg5unittest.HTTPSTestClass):
+
+        example_pkg10 = """
+            open [email protected],5.11-0
+            add file tmp/example_file mode=0555 owner=root group=bin path=/usr/bin/example_path
+            close"""
+
+        misc_files = ["tmp/example_file", "tmp/empty", "tmp/verboten"]
+
+        def setUp(self):
+                pubs = ["src", "dst"]
+
+                pkg5unittest.HTTPSTestClass.setUp(self, pubs,
+                    start_depots=True)
+                
+                self.srurl = self.dcs[1].get_repo_url()
+                self.make_misc_files(self.misc_files)
+                self.pkgsend_bulk(self.srurl, self.example_pkg10)
+
+                self.surl = self.ac.url + "/%s" % pubs[0]
+                self.durl = self.ac.url + "/%s" % pubs[1]
+
+                #set permissions of tmp/verboten to make it non-readable
+                self.verboten = os.path.join(self.test_root, "tmp/verboten")
+                os.system("chmod 600 %s" % self.verboten) 
+                
+
+        def test_01_basics(self):
+                """Test that transfering a package from an https repo to
+                another https repo works"""
+
+                self.ac.start()
+
+                arg_dict = {
+                    "cert": os.path.join(self.cs_dir, self.get_cli_cert("src")),
+                    "key": os.path.join(self.keys_dir, self.get_cli_key("src")),
+                    "dst": self.durl,
+                    "dcert": os.path.join(self.cs_dir, self.get_cli_cert("dst")),
+                    "dkey": os.path.join(self.keys_dir, self.get_cli_key("dst")),
+                    "pkg": "[email protected],5.11-0",
+                    "empty": os.path.join(self.test_root, "tmp/empty"),
+                    "noexist": os.path.join(self.test_root, "octopus"),
+                    "verboten": self.verboten,
+                }
+
+                # We need an image for seed_ta_dir() to work.
+                # TODO: there might be a cleaner way of doing this
+                self.image_create()
+                # Add the trust anchor needed to verify the server's identity.
+                self.seed_ta_dir("ta7")
+
+                # We try to receive a pkg from a secured repo and publish it to
+                # another secured repo where both repos require different
+                # credentials
+                self.pkgrecv(self.surl, "--key %(key)s --cert %(cert)s "
+                    "-d %(dst)s --dkey %(dkey)s --dcert %(dcert)s "
+                    "%(pkg)s" % arg_dict)
+
+                # Now try to use the same credentials for source and dest.
+                # This should fail.
+                self.pkgrecv(self.surl, "--key %(key)s --cert %(cert)s "
+                    "-d %(dst)s --dkey %(key)s --dcert %(cert)s "
+                    "%(pkg)s" % arg_dict, exit=1)
+
+                # Make sure we don't traceback when credential files are invalid
+                # Src certificate option missing
+                self.pkgrecv(self.surl, "--key %(key)s -d %(dst)s "
+                    "--dkey %(dkey)s --dcert %(dcert)s "
+                    "%(pkg)s" % arg_dict, exit=1)
+
+                # Dst certificate option missing
+                self.pkgrecv(self.surl, "--key %(key)s --cert %(cert)s "
+                    "-d %(dst)s --dkey %(dkey)s "
+                    "%(pkg)s" % arg_dict, exit=1)
+
+                # Src key option missing
+                self.pkgrecv(self.surl, "--cert %(cert)s "
+                    "-d %(dst)s --dkey %(dkey)s --dcert %(dcert)s "
+                    "%(pkg)s" % arg_dict, exit=1)
+
+                # Dst key option missing
+                self.pkgrecv(self.surl, "--key %(key)s --cert %(cert)s "
+                    "-d %(dst)s --dcert %(dcert)s "
+                    "%(pkg)s" % arg_dict, exit=1)
+
+                # Src certificate not found
+                self.pkgrecv(self.surl, "--key %(key)s --cert %(noexist)s "
+                    "-d %(dst)s --dkey %(dkey)s --dcert %(dcert)s "
+                    "%(pkg)s" % arg_dict, exit=1)
+
+                # Dst certificate not found
+                self.pkgrecv(self.surl, "--key %(key)s --cert %(cert)s "
+                    "-d %(dst)s --dkey %(dkey)s --dcert %(noexist)s "
+                    "%(pkg)s" % arg_dict, exit=1)
+
+                # Src key not found
+                self.pkgrecv(self.surl, "--key %(noexist)s --cert %(cert)s "
+                    "-d %(dst)s --dkey %(dkey)s --dcert %(dcert)s "
+                    "%(pkg)s" % arg_dict, exit=1)
+
+                # Dst key not found
+                self.pkgrecv(self.surl, "--key %(key)s --cert %(cert)s "
+                    "-d %(dst)s --dkey %(noexist)s --dcert %(dcert)s "
+                    "%(pkg)s" % arg_dict, exit=1)
+
+                # Src certificate is empty file
+                self.pkgrecv(self.surl, "--key %(key)s --cert %(empty)s "
+                    "-d %(dst)s --dkey %(dkey)s --dcert %(dcert)s "
+                    "%(pkg)s" % arg_dict, exit=1)
+
+                # Dst certificate is empty file
+                self.pkgrecv(self.surl, "--key %(key)s --cert %(cert)s "
+                    "-d %(dst)s --dkey %(dkey)s --dcert %(empty)s "
+                    "%(pkg)s" % arg_dict, exit=1)
+
+                # Src key is empty file
+                self.pkgrecv(self.surl, "--key %(empty)s --cert %(cert)s "
+                    "-d %(dst)s --dkey %(dkey)s --dcert %(dcert)s "
+                    "%(pkg)s" % arg_dict, exit=1)
+
+                # Dst key is empty file
+                self.pkgrecv(self.surl, "--key %(key)s --cert %(cert)s "
+                    "-d %(dst)s --dkey %(empty)s --dcert %(dcert)s "
+                    "%(pkg)s" % arg_dict, exit=1)
+                
+                # No permissions to read src certificate 
+                self.pkgrecv(self.surl, "--key %(key)s --cert %(verboten)s "
+                    "-d %(dst)s --dkey %(dkey)s --dcert %(dcert)s "
+                    "%(pkg)s" % arg_dict, su_wrap=True, exit=1)
+
+                # No permissions to read dst certificate 
+                self.pkgrecv(self.surl, "--key %(key)s --cert %(cert)s "
+                    "-d %(dst)s --dkey %(dkey)s --dcert %(verboten)s "
+                    "%(pkg)s" % arg_dict, su_wrap=True, exit=1)
+
+                # No permissions to read src key 
+                self.pkgrecv(self.surl, "--key %(verboten)s --cert %(cert)s "
+                    "-d %(dst)s --dkey %(dkey)s --dcert %(dcert)s "
+                    "%(pkg)s" % arg_dict, su_wrap=True, exit=1)
+
+                # No permissions to read dst key 
+                self.pkgrecv(self.surl, "--key %(key)s --cert %(cert)s "
+                    "-d %(dst)s --dkey %(verboten)s --dcert %(dcert)s "
+                    "%(pkg)s" % arg_dict, su_wrap=True, exit=1)
+
+
 if __name__ == "__main__":
         unittest.main()
--- a/src/tests/cli/t_pkgrepo.py	Wed Feb 20 19:25:25 2013 -0800
+++ b/src/tests/cli/t_pkgrepo.py	Thu Feb 21 13:44:55 2013 -0800
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 import testutils
@@ -2161,5 +2161,113 @@
                 self.assert_("no matching publishers" in self.errout)
 
 
+class TestPkgrepoHTTPS(pkg5unittest.HTTPSTestClass):
+
+        example_pkg10 = """
+            open [email protected],5.11-0
+            add file tmp/example_file mode=0555 owner=root group=bin path=/usr/bin/example_path
+            close"""
+
+        misc_files = ["tmp/example_file", "tmp/empty", "tmp/verboten"]
+
+        def setUp(self):
+                pub = "test"
+
+                pkg5unittest.HTTPSTestClass.setUp(self, [pub],
+                    start_depots=True)
+                
+                self.url = self.ac.url + "/%s" % pub
+
+                # publish a simple test package
+                self.srurl = self.dcs[1].get_repo_url()
+                self.make_misc_files(self.misc_files)
+                self.pkgsend_bulk(self.srurl, self.example_pkg10)
+
+                #set permissions of tmp/verboten to make it non-readable
+                self.verboten = os.path.join(self.test_root, "tmp/verboten")
+                os.system("chmod 600 %s" % self.verboten) 
+                
+
+        def test_01_basics(self):
+                """Test that running pkgrepo on an SSL-secured repo works for
+                all operations which are valid for network repos"""
+
+                self.ac.start()
+
+                arg_dict = {
+                    "cert": os.path.join(self.cs_dir,
+                    self.get_cli_cert("test")),
+                    "key": os.path.join(self.keys_dir,
+                    self.get_cli_key("test")),
+                    "url": self.url,
+                    "empty": os.path.join(self.test_root, "tmp/empty"),
+                    "noexist": os.path.join(self.test_root, "octopus"),
+                    "verboten": self.verboten,
+                }
+
+                # We need an image for seed_ta_dir() to work.
+                # TODO: there might be a cleaner way of doing this
+                self.image_create()
+                # Add the trust anchor needed to verify the server's identity.
+                self.seed_ta_dir("ta7")
+
+                # Try all pkgrepo operations which are valid for network repos.
+                # pkgrepo info
+                self.pkgrepo("-s %(url)s info --key %(key)s --cert %(cert)s"
+                    % arg_dict)
+
+                # pkgrepo list
+                self.pkgrepo("-s %(url)s list --key %(key)s --cert %(cert)s"
+                    % arg_dict)
+
+                # pkgrepo get
+                self.pkgrepo("-s %(url)s get --key %(key)s --cert %(cert)s"
+                    % arg_dict)
+
+                # pkgrepo refresh
+                self.pkgrepo("-s %(url)s refresh --key %(key)s --cert %(cert)s"
+                    % arg_dict)
+
+                # pkgrepo rebuild
+                self.pkgrepo("-s %(url)s rebuild --key %(key)s --cert %(cert)s"
+                    % arg_dict)
+
+                # Try without key and cert (should fail)
+                self.pkgrepo("-s %(url)s rebuild" % arg_dict, exit=1)
+
+                # Make sure we don't traceback when credential files are invalid
+                # Certificate option missing
+                self.pkgrepo("-s %(url)s rebuild --key %(key)s" % arg_dict,
+                    exit=1)
+
+                # Key option missing
+                self.pkgrepo("-s %(url)s rebuild --cert %(cert)s" % arg_dict,
+                    exit=1)
+
+                # Certificate not found
+                self.pkgrepo("-s %(url)s rebuild --key %(key)s "
+                    "--cert %(noexist)s" % arg_dict, exit=1)
+
+                # Key not found
+                self.pkgrepo("-s %(url)s rebuild --key %(noexist)s "
+                    "--cert %(cert)s" % arg_dict, exit=1)
+
+                # Certificate is empty file
+                self.pkgrepo("-s %(url)s rebuild --key %(key)s "
+                    "--cert %(empty)s" % arg_dict, exit=1)
+
+                # Key is empty file
+                self.pkgrepo("-s %(url)s rebuild --key %(empty)s "
+                    "--cert %(cert)s" % arg_dict, exit=1)
+
+                # No permissions to read certificate 
+                self.pkgrepo("-s %(url)s rebuild --key %(key)s "
+                    "--cert %(verboten)s" % arg_dict, su_wrap=True, exit=1)
+
+                # No permissions to read key 
+                self.pkgrepo("-s %(url)s rebuild --key %(verboten)s "
+                    "--cert %(cert)s" % arg_dict, su_wrap=True, exit=1)
+
+
 if __name__ == "__main__":
         unittest.main()
--- a/src/tests/cli/t_pkgsend.py	Wed Feb 20 19:25:25 2013 -0800
+++ b/src/tests/cli/t_pkgsend.py	Thu Feb 21 13:44:55 2013 -0800
@@ -20,7 +20,7 @@
 # CDDL HEADER END
 #
 
-# Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
 
 import testutils
 if __name__ == "__main__":
@@ -1407,5 +1407,101 @@
                 do_test("d1/f1", "d1/f2", "d2/f3")
 
 
+class TestPkgsendHTTPS(pkg5unittest.HTTPSTestClass):
+
+        misc_files = ["tmp/empty", "tmp/verboten"]
+
+        def setUp(self):
+                pub = "test"
+
+                pkg5unittest.HTTPSTestClass.setUp(self, [pub],
+                    start_depots=True)
+
+                self.url = self.ac.url + "/%s" % pub
+                self.make_misc_files(self.misc_files)
+                #set permissions of tmp/verboten to make it non-readable
+                self.verboten = os.path.join(self.test_root, "tmp/verboten")
+                os.system("chmod 600 %s" % self.verboten) 
+
+        def test_01_basics(self):
+                """Test that publishing to an SSL-secured repo works"""
+
+                self.ac.start()
+
+                rootdir = self.test_root
+                dir_1 = os.path.join(rootdir, "dir_1")
+                os.mkdir(dir_1)
+                file(os.path.join(dir_1, "A"), "wb").close()
+                file(os.path.join(dir_1, "B"), "wb").close()
+                mfpath = os.path.join(rootdir, "manifest_test")
+                with open(mfpath, "wb") as mf:
+                        mf.write("""file NOHASH mode=0755 owner=root group=bin path=/A
+                            file NOHASH mode=0755 owner=root group=bin path=/B
+                            set name=pkg.fmri [email protected],5.10
+                            """)
+
+                arg_dict = {
+                    "cert": os.path.join(self.cs_dir, self.get_cli_cert("test")),
+                    "key": os.path.join(self.keys_dir, self.get_cli_key("test")),
+                    "url": self.url,
+                    "dir": dir_1,
+                    "mani": mfpath,
+                    "empty": os.path.join(self.test_root, "tmp/empty"),
+                    "noexist": os.path.join(self.test_root, "octopus"),
+                    "verboten": self.verboten,
+
+                }
+
+                # We need an image for seed_ta_dir() to work.
+                # TODO: there might be a cleaner way of doing this
+                self.image_create()
+                # Add the trust anchor needed to verify the server's identity.
+                self.seed_ta_dir("ta7")
+
+                # Try to publish a simple package to SSL-secured repo  
+                self.pkgsend(self.url, "publish --key %(key)s --cert %(cert)s "
+                    "-d %(dir)s %(mani)s" % arg_dict)
+        
+                # Try to publish a simple package to SSL-secured repo without
+                # prvoviding certs (should fail).  
+                self.pkgsend(self.url, "publish -d %(dir)s %(mani)s" % arg_dict,
+                    exit=1)
+
+                # Make sure we don't traceback when credential files are invalid
+                # Certificate option missing
+                self.pkgsend(self.url, "publish --key %(key)s "
+                    "-d %(dir)s %(mani)s" % arg_dict, exit=1)
+
+                # Key option missing
+                self.pkgsend(self.url, "publish --cert %(cert)s "
+                    "-d %(dir)s %(mani)s" % arg_dict, exit=1)
+
+                # Certificate not found
+                self.pkgsend(self.url, "publish --key %(key)s "
+                    "--cert %(noexist)s -d %(dir)s %(mani)s" % arg_dict, exit=1)
+
+                # Key not found
+                self.pkgsend(self.url, "publish --key %(noexist)s "
+                    "--cert %(cert)s -d %(dir)s %(mani)s" % arg_dict, exit=1)
+
+                # Certificate is empty file
+                self.pkgsend(self.url, "publish --key %(key)s --cert %(empty)s "
+                    "-d %(dir)s %(mani)s" % arg_dict, exit=1)
+
+                # Key is empty file
+                self.pkgsend(self.url, "publish --key %(empty)s "
+                    "--cert %(cert)s -d %(dir)s %(mani)s" % arg_dict, exit=1)
+
+                # No permissions to read certificate 
+                self.pkgsend(self.url, "publish --key %(key)s "
+                    "--cert %(verboten)s -d %(dir)s %(mani)s" % arg_dict,
+                    su_wrap=True, exit=1)
+
+                # No permissions to read key 
+                self.pkgsend(self.url, "publish --key %(verboten)s "
+                    "--cert %(cert)s -d %(dir)s %(mani)s" % arg_dict,
+                    su_wrap=True, exit=1)
+
+
 if __name__ == "__main__":
         unittest.main()
--- a/src/tests/pkg5unittest.py	Wed Feb 20 19:25:25 2013 -0800
+++ b/src/tests/pkg5unittest.py	Thu Feb 21 13:44:55 2013 -0800
@@ -2407,7 +2407,7 @@
                     comment=comment, stderr=True, env_arg=env_arg)
 
         def pkgrecv(self, server_url=None, command=None, exit=0, out=False,
-            comment="", env_arg=None):
+            comment="", env_arg=None, su_wrap=False):
                 args = []
                 if server_url:
                         args.append("-s %s" % server_url)
@@ -2417,8 +2417,9 @@
 
                 cmdline = "%s/usr/bin/pkgrecv %s" % (g_proto_area,
                     " ".join(args))
+
                 return self.cmdline_run(cmdline, comment=comment, exit=exit,
-                    out=out, env_arg=env_arg)
+                    out=out, su_wrap=su_wrap, env_arg=env_arg)
 
         def pkgmerge(self, args, comment="", exit=0, su_wrap=False,
             env_arg=None):
@@ -3339,6 +3340,446 @@
         # test cases.
         ac = property(fget=__get_ac)
 
+class HTTPSTestClass(ApacheDepotTestCase):
+        # Tests in this suite use the read only data directory.
+        need_ro_data = True
+
+        def pkg(self, command, *args, **kwargs):
+                # The value for ssl_ca_file is pulled from DebugValues because
+                # ssl_ca_file needs to be set there so the api object calls work
+                # as desired.
+                command = "--debug ssl_ca_file=%s %s" % \
+                    (DebugValues["ssl_ca_file"], command)
+                return ApacheDepotTestCase.pkg(self, command,
+                    *args, **kwargs)
+
+        def pkgrecv(self, command, *args, **kwargs):
+                # The value for ssl_ca_file is pulled from DebugValues because
+                # ssl_ca_file needs to be set there so the api object calls work
+                # as desired.
+                command = "%s --debug ssl_ca_file=%s" % \
+                    (command, DebugValues["ssl_ca_file"])
+                return ApacheDepotTestCase.pkgrecv(self, command,
+                    *args, **kwargs)
+
+        def pkgsend(self, command, *args, **kwargs):
+                # The value for ssl_ca_file is pulled from DebugValues because
+                # ssl_ca_file needs to be set there so the api object calls work
+                # as desired.
+                command = "%s --debug ssl_ca_file=%s" % \
+                    (command, DebugValues["ssl_ca_file"])
+                return ApacheDepotTestCase.pkgsend(self, command,
+                    *args, **kwargs)
+
+        def pkgrepo(self, command, *args, **kwargs):
+                # The value for ssl_ca_file is pulled from DebugValues because
+                # ssl_ca_file needs to be set there so the api object calls work
+                # as desired.
+                command = "--debug ssl_ca_file=%s %s" % \
+                    (DebugValues["ssl_ca_file"], command)
+                return ApacheDepotTestCase.pkgrepo(self, command,
+                    *args, **kwargs)
+
+        def seed_ta_dir(self, certs, dest_dir=None):
+                if isinstance(certs, basestring):
+                        certs = [certs]
+                if not dest_dir:
+                        dest_dir = self.ta_dir
+                self.assert_(dest_dir)
+                self.assert_(self.raw_trust_anchor_dir)
+                for c in certs:
+                        name = "%s_cert.pem" % c
+                        portable.copyfile(
+                            os.path.join(self.raw_trust_anchor_dir, name),
+                            os.path.join(dest_dir, name))
+                        DebugValues["ssl_ca_file"] = os.path.join(dest_dir,
+                            name)
+
+        def get_cli_cert(self, publisher):
+                ta = self.pub_ta_map[publisher]
+                return "cs1_ta%d_cert.pem" % ta
+
+        def get_cli_key(self, publisher):
+                ta = self.pub_ta_map[publisher]
+                return "cs1_ta%d_key.pem" % ta
+
+        def setUp(self, publishers, start_depots=True):
+                # We only have 5 usable CA certs and there are not many usecases
+                # for setting up more than 5 different SSL-secured depots.
+                assert len(publishers) < 6
+
+                # Maintains a mapping of which TA is used for which publisher
+                self.pub_ta_map = {}
+
+                ApacheDepotTestCase.setUp(self, publishers,
+                    start_depots=True)
+                self.testdata_dir = os.path.join(self.test_root, "testdata")
+
+                # Set up the directories that apache needs.
+                self.apache_dir = os.path.join(self.test_root, "apache")
+                os.makedirs(self.apache_dir)
+                self.apache_log_dir = os.path.join(self.apache_dir,
+                    "apache_logs")
+                os.makedirs(self.apache_log_dir)
+                self.apache_content_dir = os.path.join(self.apache_dir,
+                    "apache_content")
+                self.pidfile = os.path.join(self.apache_dir, "httpd.pid")
+                self.common_config_dir = os.path.join(self.test_root,
+                    "apache-serve")
+
+                # Choose ports for apache to run on.
+                self.https_port = self.next_free_port
+                self.next_free_port += 1
+                self.proxy_port = self.next_free_port
+                self.next_free_port += 1
+                self.bad_proxy_port = self.next_free_port
+                self.next_free_port += 1
+
+                # Set up the paths to the certificates that will be needed.
+                self.path_to_certs = os.path.join(self.ro_data_root,
+                    "signing_certs", "produced")
+                self.keys_dir = os.path.join(self.path_to_certs, "keys")
+                self.cs_dir = os.path.join(self.path_to_certs,
+                    "code_signing_certs")
+                self.chain_certs_dir = os.path.join(self.path_to_certs,
+                    "chain_certs")
+                self.pub_cas_dir = os.path.join(self.path_to_certs,
+                    "publisher_cas")
+                self.inter_certs_dir = os.path.join(self.path_to_certs,
+                    "inter_certs")
+                self.raw_trust_anchor_dir = os.path.join(self.path_to_certs,
+                    "trust_anchors")
+                self.crl_dir = os.path.join(self.path_to_certs, "crl")
+
+                location_tags = ""
+                # Usable CA certs are ta6 to ta11 with the exception of ta7.
+                # We already checked that not more than 5 publishers have been
+                # requested.
+                count = 6
+                for dc in self.dcs:
+                        # Create a <Location> tag for each publisher. The server
+                        # path is set to the publisher name.
+                        if count == 7:
+                                # TA7 needs password to unlock cert, don't use
+                                count += 1
+                        dc_pub = self.dcs[dc].get_property("publisher",
+                            "prefix")
+                        self.pub_ta_map[dc_pub] = count
+                        loc_dict = {
+                            "server-path":dc_pub,
+                            "server-ca-taname":"ta%d" % count,
+                            "ssl-special":"%{SSL_CLIENT_I_DN_OU}",
+                            "proxied-server":self.dcs[dc].get_depot_url(),
+                        }
+
+                        location_tags += loc_tag % (loc_dict)
+                        count += 1
+
+                conf_dict = {
+                    "common_log_format": "%h %l %u %t \\\"%r\\\" %>s %b",
+                    "https_port": self.https_port,
+                    "proxy_port": self.proxy_port,
+                    "bad_proxy_port": self.bad_proxy_port,
+                    "log_locs": self.apache_log_dir,
+                    "pidfile": self.pidfile,
+                    "port": self.https_port,
+                    "serve_root": self.apache_content_dir,
+                    "server-ssl-cert":os.path.join(self.cs_dir,
+                        "cs1_ta7_cert.pem"),
+                    "server-ssl-key":os.path.join(self.keys_dir,
+                        "cs1_ta7_key.pem"),
+                    "server-ca-cert":os.path.join(self.path_to_certs, "combined_cas.pem"),
+                    "location-tags":location_tags,
+                }
+
+                self.https_conf_path = os.path.join(self.test_root,
+                    "https.conf")
+                with open(self.https_conf_path, "wb") as fh:
+                        fh.write(self.https_conf % conf_dict)
+                
+                ac = ApacheController(self.https_conf_path,
+                    self.https_port, self.common_config_dir, https=True,
+                    testcase=self)
+                self.register_apache_controller("default", ac)
+
+        https_conf = """\
+# Configuration and logfile names: If the filenames you specify for many
+# of the server's control files begin with "/" (or "drive:/" for Win32), the
+# server will use that explicit path.  If the filenames do *not* begin
+# with "/", the value of ServerRoot is prepended -- so "/var/apache2/2.2/logs/foo_log"
+# with ServerRoot set to "/usr/apache2/2.2" will be interpreted by the
+# server as "/usr/apache2/2.2//var/apache2/2.2/logs/foo_log".
+
+#
+# ServerRoot: The top of the directory tree under which the server's
+# configuration, error, and log files are kept.
+#
+# Do not add a slash at the end of the directory path.  If you point
+# ServerRoot at a non-local disk, be sure to point the LockFile directive
+# at a local disk.  If you wish to share the same ServerRoot for multiple
+# httpd daemons, you will need to change at least LockFile and PidFile.
+#
+ServerRoot "/usr/apache2/2.2"
+
+PidFile "%(pidfile)s"
+
+#
+# Listen: Allows you to bind Apache to specific IP addresses and/or
+# ports, instead of the default. See also the <VirtualHost>
+# directive.
+#
+# Change this to Listen on specific IP addresses as shown below to 
+# prevent Apache from glomming onto all bound IP addresses.
+#
+Listen 0.0.0.0:%(https_port)s
+
+# We also make ourselves a general-purpose proxy. This is not needed for the
+# SSL reverse-proxying to the pkg.depotd, but allows us to test that pkg(1)
+# can communicate to HTTPS origins using a proxy.
+Listen 0.0.0.0:%(proxy_port)s
+Listen 0.0.0.0:%(bad_proxy_port)s
+
+#
+# Dynamic Shared Object (DSO) Support
+#
+# To be able to use the functionality of a module which was built as a DSO you
+# have to place corresponding `LoadModule' lines within the appropriate 
+# (32-bit or 64-bit module) /etc/apache2/2.2/conf.d/modules-*.load file so that
+# the directives contained in it are actually available _before_ they are used.
+#
+<IfDefine 64bit>
+Include /etc/apache2/2.2/conf.d/modules-64.load
+</IfDefine>
+<IfDefine !64bit>
+Include /etc/apache2/2.2/conf.d/modules-32.load
+</IfDefine>
+
+<IfModule !mpm_netware_module>
+#
+# If you wish httpd to run as a different user or group, you must run
+# httpd as root initially and it will switch.  
+#
+# User/Group: The name (or #number) of the user/group to run httpd as.
+# It is usually good practice to create a dedicated user and group for
+# running httpd, as with most system services.
+#
+User webservd
+Group webservd
+
+</IfModule>
+
+# 'Main' server configuration
+#
+# The directives in this section set up the values used by the 'main'
+# server, which responds to any requests that aren't handled by a
+# <VirtualHost> definition.  These values also provide defaults for
+# any <VirtualHost> containers you may define later in the file.
+#
+# All of these directives may appear inside <VirtualHost> containers,
+# in which case these default settings will be overridden for the
+# virtual host being defined.
+#
+
+#
+# ServerName gives the name and port that the server uses to identify itself.
+# This can often be determined automatically, but we recommend you specify
+# it explicitly to prevent problems during startup.
+#
+# If your host doesn't have a registered DNS name, enter its IP address here.
+#
+ServerName 127.0.0.1
+
+#
+# DocumentRoot: The directory out of which you will serve your
+# documents. By default, all requests are taken from this directory, but
+# symbolic links and aliases may be used to point to other locations.
+#
+DocumentRoot "/"
+
+#
+# Each directory to which Apache has access can be configured with respect
+# to which services and features are allowed and/or disabled in that
+# directory (and its subdirectories). 
+#
+# First, we configure the "default" to be a very restrictive set of 
+# features.  
+#
+<Directory />
+    Options None
+    AllowOverride None
+    Order deny,allow
+    Deny from all
+</Directory>
+
+#
+# Note that from this point forward you must specifically allow
+# particular features to be enabled - so if something's not working as
+# you might expect, make sure that you have specifically enabled it
+# below.
+#
+
+#
+# This should be changed to whatever you set DocumentRoot to.
+#
+
+#
+# DirectoryIndex: sets the file that Apache will serve if a directory
+# is requested.
+#
+<IfModule dir_module>
+    DirectoryIndex index.html
+</IfModule>
+
+#
+# The following lines prevent .htaccess and .htpasswd files from being 
+# viewed by Web clients. 
+#
+<FilesMatch "^\.ht">
+    Order allow,deny
+    Deny from all
+    Satisfy All
+</FilesMatch>
+
+#
+# ErrorLog: The location of the error log file.
+# If you do not specify an ErrorLog directive within a <VirtualHost>
+# container, error messages relating to that virtual host will be
+# logged here.  If you *do* define an error logfile for a <VirtualHost>
+# container, that host's errors will be logged there and not here.
+#
+ErrorLog "%(log_locs)s/error_log"
+
+#
+# LogLevel: Control the number of messages logged to the error_log.
+# Possible values include: debug, info, notice, warn, error, crit,
+# alert, emerg.
+#
+LogLevel debug
+
+
+
+<IfModule log_config_module>
+    #
+    # The following directives define some format nicknames for use with
+    # a CustomLog directive (see below).
+    #
+    LogFormat "%(common_log_format)s" common
+    LogFormat "PROXY %(common_log_format)s" proxylog
+
+    #
+    # The location and format of the access logfile (Common Logfile Format).
+    # If you do not define any access logfiles within a <VirtualHost>
+    # container, they will be logged here.  Contrariwise, if you *do*
+    # define per-<VirtualHost> access logfiles, transactions will be
+    # logged therein and *not* in this file.
+    #
+    CustomLog "%(log_locs)s/access_log" common
+</IfModule>
+
+#
+# DefaultType: the default MIME type the server will use for a document
+# if it cannot otherwise determine one, such as from filename extensions.
+# If your server contains mostly text or HTML documents, "text/plain" is
+# a good value.  If most of your content is binary, such as applications
+# or images, you may want to use "application/octet-stream" instead to
+# keep browsers from trying to display binary files as though they are
+# text.
+#
+DefaultType text/plain
+
+<IfModule mime_module>
+    #
+    # TypesConfig points to the file containing the list of mappings from
+    # filename extension to MIME-type.
+    #
+    TypesConfig /etc/apache2/2.2/mime.types
+
+    #
+    # AddType allows you to add to or override the MIME configuration
+    # file specified in TypesConfig for specific file types.
+    #
+    AddType application/x-compress .Z
+    AddType application/x-gzip .gz .tgz
+
+    # Add a new mime.type for .p5i file extension so that clicking on
+    # this file type on a web page launches PackageManager in a Webinstall mode.
+    AddType application/vnd.pkg5.info .p5i
+</IfModule>
+
+#
+# Note: The following must must be present to support
+#       starting without SSL on platforms with no /dev/random equivalent
+#       but a statically compiled-in mod_ssl.
+#
+<IfModule ssl_module>
+SSLRandomSeed startup builtin
+SSLRandomSeed connect builtin
+</IfModule>
+
+<VirtualHost 0.0.0.0:%(https_port)s>
+        AllowEncodedSlashes On
+        ProxyRequests Off
+        MaxKeepAliveRequests 10000
+
+        SSLEngine On
+
+        # Cert paths
+        SSLCertificateFile %(server-ssl-cert)s
+        SSLCertificateKeyFile %(server-ssl-key)s
+
+        # Combined product CA certs for client verification
+        SSLCACertificateFile %(server-ca-cert)s
+
+	SSLVerifyClient require
+
+        %(location-tags)s
+
+</VirtualHost>
+
+#
+# We configure this Apache instance as a general-purpose HTTP proxy, accepting
+# requests from localhost, and allowing CONNECTs to our HTTPS port
+#
+<VirtualHost 0.0.0.0:%(proxy_port)s>
+        <Proxy *>
+                Order Deny,Allow
+                Deny from all
+                Allow from 127.0.0.1
+        </Proxy>
+        AllowCONNECT %(https_port)s
+        ProxyRequests on
+        CustomLog "%(log_locs)s/proxy_access_log" proxylog
+</VirtualHost>
+
+<VirtualHost 0.0.0.0:%(bad_proxy_port)s>
+        <Proxy *>
+                Order Deny,Allow
+                Deny from all
+                Allow from 127.0.0.1
+        </Proxy>
+#  We purposely prevent this proxy from being able to connect to our SSL
+#  port, making sure that when we point pkg(1) to this bad proxy, operations
+#  will fail - the following line is commented out:
+#        AllowCONNECT %(https_port)s
+        ProxyRequests on
+        CustomLog "%(log_locs)s/badproxy_access_log" proxylog
+
+</VirtualHost>
+"""
+
+loc_tag = """
+        <Location /%(server-path)s>
+                SSLVerifyDepth 1
+
+	        # The client's certificate must pass verification, and must have
+	        # a CN which matches this repository.
+                SSLRequire ( %(ssl-special)s =~ m/%(server-ca-taname)s/ )
+
+                # set max to number of threads in depot
+                ProxyPass %(proxied-server)s nocanon max=500
+        </Location>
+"""
+
 
 class SingleDepotTestCase(ManyDepotTestCase):
 
@@ -3366,6 +3807,7 @@
         # for convenience of writing test cases.
         dc = property(fget=__get_dc)
 
+
 class SingleDepotTestCaseCorruptImage(SingleDepotTestCase):
         """ A class which allows manipulation of the image directory that
         SingleDepotTestCase creates. Specifically, it supports removing one
--- a/src/tests/ro_data/signing_certs/generate_certs.py	Wed Feb 20 19:25:25 2013 -0800
+++ b/src/tests/ro_data/signing_certs/generate_certs.py	Thu Feb 21 13:44:55 2013 -0800
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
 #
 
 import os
@@ -34,8 +34,8 @@
 cnf_file = "openssl.cnf"
 mk_file = "Makefile"
 
-subj_str = "/C=US/ST=California/L=Menlo Park/O=pkg5/CN=%s/emailAddress=%s"
-https_subj_str = "/C=US/ST=California/L=Menlo Park/O=pkg5/OU=%s/" \
+subj_str = "/C=US/ST=California/L=Santa Clara/O=pkg5/CN=%s/emailAddress=%s"
+https_subj_str = "/C=US/ST=California/L=Santa Clara/O=pkg5/OU=%s/" \
     "CN=localhost/emailAddress=%s"
 
 def convert_pem_to_text(tmp_pth, out_pth, kind="x509"):
@@ -351,5 +351,17 @@
         make_cs_cert("code_signing_certs", "cs1_ta11", "trust_anchors", "ta11",
             https=True)
 
+        # Create a combined CA file to test different client certs with Apache
+        fhw = open("combined_cas.pem", "w")
+        for x in range(6,12):
+                if x == 7:
+                        # ta requires a password to unlock cert, don't use 
+                        continue
+                fn = "ta%d/ta%d_cert.pem" % (x,x)
+                fhr = open(fn, "r")
+                fhw.write(fhr.read())
+                fhr.close()
+        fhw.close()
+
         os.remove(cnf_file)
         os.chdir("../")
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/tests/ro_data/signing_certs/produced/combined_cas.pem	Thu Feb 21 13:44:55 2013 -0800
@@ -0,0 +1,322 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            93:ae:7e:2d:c9:61:8f:4b
+        Signature Algorithm: sha256WithRSAEncryption
+        Issuer: C=US, ST=California, L=Menlo Park, O=pkg5, OU=ta6, CN=localhost/emailAddress=ta6
+        Validity
+            Not Before: Apr 11 22:37:52 2011 GMT
+            Not After : Jan  5 22:37:52 2014 GMT
+        Subject: C=US, ST=California, L=Menlo Park, O=pkg5, OU=ta6, CN=localhost/emailAddress=ta6
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (1024 bit)
+                Modulus (1024 bit):
+                    00:c5:41:a2:3d:00:af:e2:71:29:e6:18:c2:73:65:
+                    fc:4a:9d:e3:f7:1a:6e:7a:f5:09:81:87:cd:cf:a9:
+                    74:a9:e4:47:da:e2:fa:bd:0e:0a:ae:ba:06:e8:1b:
+                    66:e3:8a:5e:bb:87:90:5e:d1:38:7d:12:93:72:a0:
+                    4b:88:77:dd:ce:02:67:9f:c5:be:49:cb:b7:e8:0e:
+                    bd:f0:78:37:55:bb:c5:91:6e:c7:7b:9c:b3:94:a2:
+                    24:7d:09:25:74:52:22:6d:4a:34:f8:92:71:b1:e9:
+                    74:9b:8e:87:d4:2a:46:f8:fa:8f:86:5c:b5:6b:20:
+                    24:d1:37:ea:8a:87:07:e3:ad
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                0C:08:1A:2C:FA:77:26:CE:37:0F:A5:85:98:85:0F:4D:48:BA:83:B3
+            X509v3 Authority Key Identifier: 
+                keyid:0C:08:1A:2C:FA:77:26:CE:37:0F:A5:85:98:85:0F:4D:48:BA:83:B3
+                DirName:/C=US/ST=California/L=Menlo Park/O=pkg5/OU=ta6/CN=localhost/emailAddress=ta6
+                serial:93:AE:7E:2D:C9:61:8F:4B
+
+            X509v3 Basic Constraints: 
+                CA:TRUE
+    Signature Algorithm: sha256WithRSAEncryption
+        10:2c:ed:b9:a4:aa:bd:9e:4d:47:dd:02:64:52:a9:7a:73:a7:
+        f3:58:45:cf:da:5c:1e:80:30:d9:10:a7:e4:79:d2:eb:85:8b:
+        70:4c:39:df:b6:40:fb:7f:11:cd:a8:85:d6:5c:d1:2f:29:9f:
+        8d:fa:53:bc:20:f3:c8:97:9b:11:f4:7d:39:9a:2c:a6:6e:1e:
+        a4:0d:81:e0:65:59:89:f6:a9:66:65:38:05:44:e7:47:a2:9e:
+        a2:e3:82:07:2c:cb:8e:dc:47:a2:e9:cb:01:6a:54:c1:26:14:
+        03:e9:c3:ac:fe:98:0e:76:52:f3:5b:67:ea:26:0d:98:6d:e4:
+        23:ac
+-----BEGIN CERTIFICATE-----
+MIIDWTCCAsKgAwIBAgIJAJOufi3JYY9LMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNV
+BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRMwEQYDVQQHEwpNZW5sbyBQYXJr
+MQ0wCwYDVQQKEwRwa2c1MQwwCgYDVQQLEwN0YTYxEjAQBgNVBAMTCWxvY2FsaG9z
+dDESMBAGCSqGSIb3DQEJARYDdGE2MB4XDTExMDQxMTIyMzc1MloXDTE0MDEwNTIy
+Mzc1MlowfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEzARBgNV
+BAcTCk1lbmxvIFBhcmsxDTALBgNVBAoTBHBrZzUxDDAKBgNVBAsTA3RhNjESMBAG
+A1UEAxMJbG9jYWxob3N0MRIwEAYJKoZIhvcNAQkBFgN0YTYwgZ8wDQYJKoZIhvcN
+AQEBBQADgY0AMIGJAoGBAMVBoj0Ar+JxKeYYwnNl/Eqd4/cabnr1CYGHzc+pdKnk
+R9ri+r0OCq66BugbZuOKXruHkF7ROH0Sk3KgS4h33c4CZ5/FvknLt+gOvfB4N1W7
+xZFux3ucs5SiJH0JJXRSIm1KNPiScbHpdJuOh9QqRvj6j4ZctWsgJNE36oqHB+Ot
+AgMBAAGjgeIwgd8wHQYDVR0OBBYEFAwIGiz6dybONw+lhZiFD01IuoOzMIGvBgNV
+HSMEgacwgaSAFAwIGiz6dybONw+lhZiFD01IuoOzoYGApH4wfDELMAkGA1UEBhMC
+VVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEzARBgNVBAcTCk1lbmxvIFBhcmsxDTAL
+BgNVBAoTBHBrZzUxDDAKBgNVBAsTA3RhNjESMBAGA1UEAxMJbG9jYWxob3N0MRIw
+EAYJKoZIhvcNAQkBFgN0YTaCCQCTrn4tyWGPSzAMBgNVHRMEBTADAQH/MA0GCSqG
+SIb3DQEBCwUAA4GBABAs7bmkqr2eTUfdAmRSqXpzp/NYRc/aXB6AMNkQp+R50uuF
+i3BMOd+2QPt/Ec2ohdZc0S8pn436U7wg88iXmxH0fTmaLKZuHqQNgeBlWYn2qWZl
+OAVE50einqLjggcsy47cR6LpywFqVMEmFAPpw6z+mA52UvNbZ+omDZht5COs
+-----END CERTIFICATE-----
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            b8:9a:b1:4d:fa:a9:68:23
+        Signature Algorithm: sha256WithRSAEncryption
+        Issuer: C=US, ST=California, L=Menlo Park, O=pkg5, OU=ta8, CN=localhost/emailAddress=ta8
+        Validity
+            Not Before: Apr 11 22:37:54 2011 GMT
+            Not After : Jan  5 22:37:54 2014 GMT
+        Subject: C=US, ST=California, L=Menlo Park, O=pkg5, OU=ta8, CN=localhost/emailAddress=ta8
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (1024 bit)
+                Modulus (1024 bit):
+                    00:da:5e:85:e0:17:14:35:c1:e8:f4:b6:97:15:d1:
+                    f5:c3:36:26:57:85:5c:0c:e8:8e:d7:2b:10:66:b2:
+                    61:92:a3:df:a4:4f:61:52:41:9c:3b:2f:0e:bc:bd:
+                    92:9b:e2:4c:ec:68:34:76:2c:86:54:e5:8b:9e:ac:
+                    2f:7e:4f:07:52:ec:7f:51:31:ed:9e:94:ed:7e:15:
+                    da:4f:fb:65:d0:07:85:c2:60:69:ce:ac:74:72:8a:
+                    45:31:e4:6c:3e:5e:05:bc:d3:2f:37:56:14:c2:2e:
+                    78:78:6b:93:14:e5:61:08:22:ef:4d:f9:bb:1b:1f:
+                    31:09:12:7a:ad:e5:cf:18:5b
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                BB:CA:54:46:B9:0F:22:DB:69:82:15:BB:66:36:9D:50:1D:0B:1B:F5
+            X509v3 Authority Key Identifier: 
+                keyid:BB:CA:54:46:B9:0F:22:DB:69:82:15:BB:66:36:9D:50:1D:0B:1B:F5
+                DirName:/C=US/ST=California/L=Menlo Park/O=pkg5/OU=ta8/CN=localhost/emailAddress=ta8
+                serial:B8:9A:B1:4D:FA:A9:68:23
+
+            X509v3 Basic Constraints: 
+                CA:TRUE
+    Signature Algorithm: sha256WithRSAEncryption
+        7a:13:83:75:43:35:e1:4d:07:93:8d:1c:fd:4d:8f:5c:24:78:
+        f5:01:35:4c:a5:ad:5f:92:f3:23:21:0c:2d:dc:64:a5:7f:c2:
+        3c:c9:e3:b0:4e:d8:17:4e:76:4c:4d:71:fb:b9:3d:d9:51:b8:
+        fc:e0:91:a6:5c:18:c8:06:55:cc:a9:ba:9e:59:92:c4:5c:04:
+        11:e2:d9:99:1d:cb:bd:9d:6c:c2:0e:9e:f0:4c:20:69:6b:b1:
+        76:b6:d4:c0:e6:6c:4b:1e:18:cb:71:4a:9b:13:ca:db:c8:a4:
+        0e:35:c0:91:70:04:9c:32:bd:15:a2:36:72:97:d0:7b:d0:6c:
+        dc:03
+-----BEGIN CERTIFICATE-----
+MIIDWTCCAsKgAwIBAgIJALiasU36qWgjMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNV
+BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRMwEQYDVQQHEwpNZW5sbyBQYXJr
+MQ0wCwYDVQQKEwRwa2c1MQwwCgYDVQQLEwN0YTgxEjAQBgNVBAMTCWxvY2FsaG9z
+dDESMBAGCSqGSIb3DQEJARYDdGE4MB4XDTExMDQxMTIyMzc1NFoXDTE0MDEwNTIy
+Mzc1NFowfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEzARBgNV
+BAcTCk1lbmxvIFBhcmsxDTALBgNVBAoTBHBrZzUxDDAKBgNVBAsTA3RhODESMBAG
+A1UEAxMJbG9jYWxob3N0MRIwEAYJKoZIhvcNAQkBFgN0YTgwgZ8wDQYJKoZIhvcN
+AQEBBQADgY0AMIGJAoGBANpeheAXFDXB6PS2lxXR9cM2JleFXAzojtcrEGayYZKj
+36RPYVJBnDsvDry9kpviTOxoNHYshlTli56sL35PB1Lsf1Ex7Z6U7X4V2k/7ZdAH
+hcJgac6sdHKKRTHkbD5eBbzTLzdWFMIueHhrkxTlYQgi7035uxsfMQkSeq3lzxhb
+AgMBAAGjgeIwgd8wHQYDVR0OBBYEFLvKVEa5DyLbaYIVu2Y2nVAdCxv1MIGvBgNV
+HSMEgacwgaSAFLvKVEa5DyLbaYIVu2Y2nVAdCxv1oYGApH4wfDELMAkGA1UEBhMC
+VVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEzARBgNVBAcTCk1lbmxvIFBhcmsxDTAL
+BgNVBAoTBHBrZzUxDDAKBgNVBAsTA3RhODESMBAGA1UEAxMJbG9jYWxob3N0MRIw
+EAYJKoZIhvcNAQkBFgN0YTiCCQC4mrFN+qloIzAMBgNVHRMEBTADAQH/MA0GCSqG
+SIb3DQEBCwUAA4GBAHoTg3VDNeFNB5ONHP1Nj1wkePUBNUylrV+S8yMhDC3cZKV/
+wjzJ47BO2BdOdkxNcfu5PdlRuPzgkaZcGMgGVcypup5ZksRcBBHi2Zkdy72dbMIO
+nvBMIGlrsXa21MDmbEseGMtxSpsTytvIpA41wJFwBJwyvRWiNnKX0HvQbNwD
+-----END CERTIFICATE-----
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            a1:62:e1:e5:c0:a2:38:0d
+        Signature Algorithm: sha256WithRSAEncryption
+        Issuer: C=US, ST=California, L=Menlo Park, O=pkg5, OU=ta9, CN=localhost/emailAddress=ta9
+        Validity
+            Not Before: Apr 11 22:37:54 2011 GMT
+            Not After : Jan  5 22:37:54 2014 GMT
+        Subject: C=US, ST=California, L=Menlo Park, O=pkg5, OU=ta9, CN=localhost/emailAddress=ta9
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (1024 bit)
+                Modulus (1024 bit):
+                    00:e8:ab:ef:91:ca:05:4a:18:a2:98:c4:d8:93:d0:
+                    ce:99:a9:5e:02:8d:5d:5c:e3:f3:84:49:6b:a7:6d:
+                    ef:38:77:2e:32:c2:9c:09:1d:f6:be:6c:c6:c4:b1:
+                    c8:c3:32:72:2b:84:87:f6:ba:bf:fc:cf:5c:05:c2:
+                    4f:62:23:7e:02:3f:ce:6c:c6:b6:95:86:84:d7:97:
+                    9f:1c:87:70:29:62:6a:29:7c:06:a3:b7:18:12:67:
+                    07:3a:89:aa:f0:99:fe:df:46:00:b1:2f:aa:30:1e:
+                    a2:1e:f8:2b:37:99:21:b8:85:53:42:98:4a:bd:c5:
+                    f9:b4:61:60:0a:73:bc:0e:d1
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                A6:CF:35:00:96:15:AD:B4:24:DE:1D:5A:B9:56:A2:6E:B4:2D:46:C5
+            X509v3 Authority Key Identifier: 
+                keyid:A6:CF:35:00:96:15:AD:B4:24:DE:1D:5A:B9:56:A2:6E:B4:2D:46:C5
+                DirName:/C=US/ST=California/L=Menlo Park/O=pkg5/OU=ta9/CN=localhost/emailAddress=ta9
+                serial:A1:62:E1:E5:C0:A2:38:0D
+
+            X509v3 Basic Constraints: 
+                CA:TRUE
+    Signature Algorithm: sha256WithRSAEncryption
+        44:02:da:cf:c3:07:27:84:e4:06:22:ff:fc:7e:c9:47:7a:79:
+        e1:9f:6a:84:68:a8:fb:48:18:80:58:0f:b0:5e:ef:43:bf:3a:
+        69:23:b2:18:3e:78:3a:8e:ff:c5:d8:76:4c:99:d5:9f:be:8a:
+        fd:0e:79:b9:7e:62:c4:c2:4b:6f:78:01:e7:52:19:ff:08:86:
+        a7:b2:17:0c:11:03:ef:42:1f:b5:5b:40:0a:3a:9f:2a:4f:57:
+        31:3d:b1:dd:a8:51:e1:2f:b2:e4:5b:2e:1b:9f:a7:d6:b7:6b:
+        76:68:f9:2e:b1:38:6f:11:21:0e:81:a2:32:01:7b:bc:c3:1f:
+        82:4e
+-----BEGIN CERTIFICATE-----
+MIIDWTCCAsKgAwIBAgIJAKFi4eXAojgNMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNV
+BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRMwEQYDVQQHEwpNZW5sbyBQYXJr
+MQ0wCwYDVQQKEwRwa2c1MQwwCgYDVQQLEwN0YTkxEjAQBgNVBAMTCWxvY2FsaG9z
+dDESMBAGCSqGSIb3DQEJARYDdGE5MB4XDTExMDQxMTIyMzc1NFoXDTE0MDEwNTIy
+Mzc1NFowfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEzARBgNV
+BAcTCk1lbmxvIFBhcmsxDTALBgNVBAoTBHBrZzUxDDAKBgNVBAsTA3RhOTESMBAG
+A1UEAxMJbG9jYWxob3N0MRIwEAYJKoZIhvcNAQkBFgN0YTkwgZ8wDQYJKoZIhvcN
+AQEBBQADgY0AMIGJAoGBAOir75HKBUoYopjE2JPQzpmpXgKNXVzj84RJa6dt7zh3
+LjLCnAkd9r5sxsSxyMMyciuEh/a6v/zPXAXCT2IjfgI/zmzGtpWGhNeXnxyHcCli
+ail8BqO3GBJnBzqJqvCZ/t9GALEvqjAeoh74KzeZIbiFU0KYSr3F+bRhYApzvA7R
+AgMBAAGjgeIwgd8wHQYDVR0OBBYEFKbPNQCWFa20JN4dWrlWom60LUbFMIGvBgNV
+HSMEgacwgaSAFKbPNQCWFa20JN4dWrlWom60LUbFoYGApH4wfDELMAkGA1UEBhMC
+VVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEzARBgNVBAcTCk1lbmxvIFBhcmsxDTAL
+BgNVBAoTBHBrZzUxDDAKBgNVBAsTA3RhOTESMBAGA1UEAxMJbG9jYWxob3N0MRIw
+EAYJKoZIhvcNAQkBFgN0YTmCCQChYuHlwKI4DTAMBgNVHRMEBTADAQH/MA0GCSqG
+SIb3DQEBCwUAA4GBAEQC2s/DByeE5AYi//x+yUd6eeGfaoRoqPtIGIBYD7Be70O/
+Omkjshg+eDqO/8XYdkyZ1Z++iv0Oebl+YsTCS294AedSGf8IhqeyFwwRA+9CH7Vb
+QAo6nypPVzE9sd2oUeEvsuRbLhufp9a3a3Zo+S6xOG8RIQ6BojIBe7zDH4JO
+-----END CERTIFICATE-----
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            86:f1:45:12:31:c7:2b:2a
+        Signature Algorithm: sha256WithRSAEncryption
+        Issuer: C=US, ST=California, L=Menlo Park, O=pkg5, OU=ta10, CN=localhost/emailAddress=ta10
+        Validity
+            Not Before: Apr 11 22:37:55 2011 GMT
+            Not After : Jan  5 22:37:55 2014 GMT
+        Subject: C=US, ST=California, L=Menlo Park, O=pkg5, OU=ta10, CN=localhost/emailAddress=ta10
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (1024 bit)
+                Modulus (1024 bit):
+                    00:b6:50:43:73:64:12:40:26:54:0c:f9:67:e4:6a:
+                    ed:1f:18:e5:73:89:13:0f:c9:5f:6e:6e:c6:05:ad:
+                    2c:be:e4:6b:fd:c6:4f:ea:f3:6f:0d:f4:1a:34:7f:
+                    03:97:b0:a4:d1:6e:98:d2:36:fa:33:5d:51:37:de:
+                    8f:5b:3d:a0:07:52:c8:b7:71:30:71:fb:c3:a7:fa:
+                    61:f6:b4:28:be:9e:da:8b:8b:70:dd:8e:d0:a5:1a:
+                    00:70:1c:39:e1:cf:64:f8:ec:b4:83:b9:2b:67:fa:
+                    4d:ae:30:84:2f:2c:9d:6c:77:7e:09:95:43:77:6b:
+                    e1:9d:2b:c9:89:d9:a9:e5:8f
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                B7:F0:DB:5F:BA:CC:10:6D:A6:64:62:10:84:A5:C9:39:4C:3C:27:86
+            X509v3 Authority Key Identifier: 
+                keyid:B7:F0:DB:5F:BA:CC:10:6D:A6:64:62:10:84:A5:C9:39:4C:3C:27:86
+                DirName:/C=US/ST=California/L=Menlo Park/O=pkg5/OU=ta10/CN=localhost/emailAddress=ta10
+                serial:86:F1:45:12:31:C7:2B:2A
+
+            X509v3 Basic Constraints: 
+                CA:TRUE
+    Signature Algorithm: sha256WithRSAEncryption
+        5b:6d:71:b8:4e:e3:27:06:d9:2a:47:ab:21:a3:df:94:a9:d8:
+        62:f1:6a:97:33:cc:1c:52:55:9a:f8:ec:6d:b4:91:17:4d:2a:
+        0e:03:b4:4b:00:83:10:8e:12:c1:05:67:56:9a:30:90:91:ad:
+        8b:dc:0a:eb:3f:28:5d:f9:d4:87:0d:f7:3a:5a:f6:47:52:9e:
+        af:4e:21:d4:2f:b8:40:4f:7f:81:1f:93:ca:bc:e6:04:c5:18:
+        65:5e:b1:dd:0b:3c:5e:3a:6f:48:e3:fc:b2:c8:37:8d:9f:14:
+        1b:a7:12:79:bb:2d:b9:fc:7a:01:ef:66:c6:d4:c2:44:01:49:
+        23:a9
+-----BEGIN CERTIFICATE-----
+MIIDYDCCAsmgAwIBAgIJAIbxRRIxxysqMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNV
+BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRMwEQYDVQQHEwpNZW5sbyBQYXJr
+MQ0wCwYDVQQKEwRwa2c1MQ0wCwYDVQQLEwR0YTEwMRIwEAYDVQQDEwlsb2NhbGhv
+c3QxEzARBgkqhkiG9w0BCQEWBHRhMTAwHhcNMTEwNDExMjIzNzU1WhcNMTQwMTA1
+MjIzNzU1WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTETMBEG
+A1UEBxMKTWVubG8gUGFyazENMAsGA1UEChMEcGtnNTENMAsGA1UECxMEdGExMDES
+MBAGA1UEAxMJbG9jYWxob3N0MRMwEQYJKoZIhvcNAQkBFgR0YTEwMIGfMA0GCSqG
+SIb3DQEBAQUAA4GNADCBiQKBgQC2UENzZBJAJlQM+Wfkau0fGOVziRMPyV9ubsYF
+rSy+5Gv9xk/q828N9Bo0fwOXsKTRbpjSNvozXVE33o9bPaAHUsi3cTBx+8On+mH2
+tCi+ntqLi3DdjtClGgBwHDnhz2T47LSDuStn+k2uMIQvLJ1sd34JlUN3a+GdK8mJ
+2anljwIDAQABo4HlMIHiMB0GA1UdDgQWBBS38NtfuswQbaZkYhCEpck5TDwnhjCB
+sgYDVR0jBIGqMIGngBS38NtfuswQbaZkYhCEpck5TDwnhqGBg6SBgDB+MQswCQYD
+VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTETMBEGA1UEBxMKTWVubG8gUGFy
+azENMAsGA1UEChMEcGtnNTENMAsGA1UECxMEdGExMDESMBAGA1UEAxMJbG9jYWxo
+b3N0MRMwEQYJKoZIhvcNAQkBFgR0YTEwggkAhvFFEjHHKyowDAYDVR0TBAUwAwEB
+/zANBgkqhkiG9w0BAQsFAAOBgQBbbXG4TuMnBtkqR6sho9+Uqdhi8WqXM8wcUlWa
++OxttJEXTSoOA7RLAIMQjhLBBWdWmjCQka2L3ArrPyhd+dSHDfc6WvZHUp6vTiHU
+L7hAT3+BH5PKvOYExRhlXrHdCzxeOm9I4/yyyDeNnxQbpxJ5uy25/HoB72bG1MJE
+AUkjqQ==
+-----END CERTIFICATE-----
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            d7:f1:84:58:4b:42:ce:33
+        Signature Algorithm: sha256WithRSAEncryption
+        Issuer: C=US, ST=California, L=Menlo Park, O=pkg5, OU=ta11, CN=localhost/emailAddress=ta11
+        Validity
+            Not Before: Apr 11 22:37:55 2011 GMT
+            Not After : Jan  5 22:37:55 2014 GMT
+        Subject: C=US, ST=California, L=Menlo Park, O=pkg5, OU=ta11, CN=localhost/emailAddress=ta11
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (1024 bit)
+                Modulus (1024 bit):
+                    00:a3:c5:d4:23:f8:e8:a4:02:1f:38:cd:53:dc:7c:
+                    e8:3c:49:bd:14:c1:c7:a2:b7:00:7a:d2:d1:c8:01:
+                    7c:9b:f7:78:50:95:07:69:90:a0:7a:25:0f:55:55:
+                    f7:b2:33:ae:ae:66:64:5c:4c:86:66:e0:28:e2:63:
+                    8c:11:5f:ee:a4:af:77:86:c2:c0:18:0d:24:18:5f:
+                    26:ff:67:cc:f4:f9:7d:0c:e7:d7:0c:01:e8:85:57:
+                    f4:a8:d8:2c:f1:ec:2f:c7:8c:34:d4:3d:d3:1b:5c:
+                    2d:44:bd:d1:a6:35:d2:21:36:f9:31:ac:24:cb:ec:
+                    7b:70:c8:10:97:c8:8e:37:19
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                CE:A0:CF:69:A4:17:A0:54:BE:C3:CB:28:70:86:6A:BD:3B:DE:E4:CC
+            X509v3 Authority Key Identifier: 
+                keyid:CE:A0:CF:69:A4:17:A0:54:BE:C3:CB:28:70:86:6A:BD:3B:DE:E4:CC
+                DirName:/C=US/ST=California/L=Menlo Park/O=pkg5/OU=ta11/CN=localhost/emailAddress=ta11
+                serial:D7:F1:84:58:4B:42:CE:33
+
+            X509v3 Basic Constraints: 
+                CA:TRUE
+    Signature Algorithm: sha256WithRSAEncryption
+        89:34:9b:f9:55:53:63:83:82:0e:d0:f1:e5:0c:e3:4e:4b:2f:
+        54:20:2b:70:00:56:08:b4:18:88:59:e2:66:3e:5c:b6:0a:74:
+        16:bc:43:61:35:1e:df:e5:f6:f6:7e:de:87:18:61:b7:70:b0:
+        93:e8:5a:19:1d:01:a7:43:ca:38:ea:d2:e2:75:0e:3e:d2:b5:
+        91:57:1e:30:29:aa:2a:26:53:1b:9e:56:ad:61:41:3c:04:bb:
+        a5:af:da:75:63:5e:bb:31:21:f9:4c:dc:d0:c2:4c:90:07:45:
+        ed:32:0d:c0:c8:e9:6f:72:b5:ae:19:f2:88:9e:50:5c:5a:34:
+        47:a9
+-----BEGIN CERTIFICATE-----
+MIIDYDCCAsmgAwIBAgIJANfxhFhLQs4zMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNV
+BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRMwEQYDVQQHEwpNZW5sbyBQYXJr
+MQ0wCwYDVQQKEwRwa2c1MQ0wCwYDVQQLEwR0YTExMRIwEAYDVQQDEwlsb2NhbGhv
+c3QxEzARBgkqhkiG9w0BCQEWBHRhMTEwHhcNMTEwNDExMjIzNzU1WhcNMTQwMTA1
+MjIzNzU1WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTETMBEG
+A1UEBxMKTWVubG8gUGFyazENMAsGA1UEChMEcGtnNTENMAsGA1UECxMEdGExMTES
+MBAGA1UEAxMJbG9jYWxob3N0MRMwEQYJKoZIhvcNAQkBFgR0YTExMIGfMA0GCSqG
+SIb3DQEBAQUAA4GNADCBiQKBgQCjxdQj+OikAh84zVPcfOg8Sb0UwceitwB60tHI
+AXyb93hQlQdpkKB6JQ9VVfeyM66uZmRcTIZm4CjiY4wRX+6kr3eGwsAYDSQYXyb/
+Z8z0+X0M59cMAeiFV/So2Czx7C/HjDTUPdMbXC1EvdGmNdIhNvkxrCTL7HtwyBCX
+yI43GQIDAQABo4HlMIHiMB0GA1UdDgQWBBTOoM9ppBegVL7Dyyhwhmq9O97kzDCB
+sgYDVR0jBIGqMIGngBTOoM9ppBegVL7Dyyhwhmq9O97kzKGBg6SBgDB+MQswCQYD
+VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTETMBEGA1UEBxMKTWVubG8gUGFy
+azENMAsGA1UEChMEcGtnNTENMAsGA1UECxMEdGExMTESMBAGA1UEAxMJbG9jYWxo
+b3N0MRMwEQYJKoZIhvcNAQkBFgR0YTExggkA1/GEWEtCzjMwDAYDVR0TBAUwAwEB
+/zANBgkqhkiG9w0BAQsFAAOBgQCJNJv5VVNjg4IO0PHlDONOSy9UICtwAFYItBiI
+WeJmPly2CnQWvENhNR7f5fb2ft6HGGG3cLCT6FoZHQGnQ8o46tLidQ4+0rWRVx4w
+KaoqJlMbnlatYUE8BLulr9p1Y167MSH5TNzQwkyQB0XtMg3AyOlvcrWuGfKInlBc
+WjRHqQ==
+-----END CERTIFICATE-----