summaryrefslogtreecommitdiffstats
path: root/pki/base/java-tools
diff options
context:
space:
mode:
Diffstat (limited to 'pki/base/java-tools')
-rw-r--r--pki/base/java-tools/CMakeLists.txt4
-rw-r--r--pki/base/java-tools/LICENSE291
-rw-r--r--pki/base/java-tools/build.xml585
-rw-r--r--pki/base/java-tools/doc/README133
-rw-r--r--pki/base/java-tools/src/CMakeLists.txt81
-rw-r--r--pki/base/java-tools/src/com/netscape/cmstools/AtoB.java140
-rw-r--r--pki/base/java-tools/src/com/netscape/cmstools/AuditVerify.java322
-rw-r--r--pki/base/java-tools/src/com/netscape/cmstools/BtoA.java116
-rw-r--r--pki/base/java-tools/src/com/netscape/cmstools/CMCEnroll.java456
-rw-r--r--pki/base/java-tools/src/com/netscape/cmstools/CMCRequest.java1100
-rw-r--r--pki/base/java-tools/src/com/netscape/cmstools/CMCResponse.java244
-rw-r--r--pki/base/java-tools/src/com/netscape/cmstools/CMCRevoke.java410
-rw-r--r--pki/base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java646
-rw-r--r--pki/base/java-tools/src/com/netscape/cmstools/ExtJoiner.java98
-rw-r--r--pki/base/java-tools/src/com/netscape/cmstools/GenExtKeyUsage.java98
-rw-r--r--pki/base/java-tools/src/com/netscape/cmstools/GenIssuerAltNameExt.java130
-rw-r--r--pki/base/java-tools/src/com/netscape/cmstools/GenSubjectAltNameExt.java130
-rw-r--r--pki/base/java-tools/src/com/netscape/cmstools/HttpClient.java410
-rw-r--r--pki/base/java-tools/src/com/netscape/cmstools/OCSPClient.java270
-rw-r--r--pki/base/java-tools/src/com/netscape/cmstools/PKCS10Client.java269
-rw-r--r--pki/base/java-tools/src/com/netscape/cmstools/PKCS12Export.java301
-rw-r--r--pki/base/java-tools/src/com/netscape/cmstools/PasswordCache.java879
-rw-r--r--pki/base/java-tools/src/com/netscape/cmstools/PrettyPrintCert.java233
-rw-r--r--pki/base/java-tools/src/com/netscape/cmstools/PrettyPrintCrl.java199
-rw-r--r--pki/base/java-tools/src/com/netscape/cmstools/TestCRLSigning.java135
-rw-r--r--pki/base/java-tools/src/com/netscape/cmstools/TokenInfo.java99
-rw-r--r--pki/base/java-tools/templates/CMakeLists.txt39
-rw-r--r--pki/base/java-tools/templates/pki_java_command_wrapper149
-rw-r--r--pki/base/java-tools/templates/pki_java_command_wrapper.in149
-rw-r--r--pki/base/java-tools/templates/pretty_print_cert_command_wrapper177
-rw-r--r--pki/base/java-tools/templates/pretty_print_crl_command_wrapper163
31 files changed, 8456 insertions, 0 deletions
diff --git a/pki/base/java-tools/CMakeLists.txt b/pki/base/java-tools/CMakeLists.txt
new file mode 100644
index 000000000..427ded555
--- /dev/null
+++ b/pki/base/java-tools/CMakeLists.txt
@@ -0,0 +1,4 @@
+project(java-tools Java)
+
+add_subdirectory(src)
+add_subdirectory(templates)
diff --git a/pki/base/java-tools/LICENSE b/pki/base/java-tools/LICENSE
new file mode 100644
index 000000000..e281f4362
--- /dev/null
+++ b/pki/base/java-tools/LICENSE
@@ -0,0 +1,291 @@
+This Program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published
+by the Free Software Foundation; version 2 of the License.
+
+This Program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with this Program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
diff --git a/pki/base/java-tools/build.xml b/pki/base/java-tools/build.xml
new file mode 100644
index 000000000..68e732ef4
--- /dev/null
+++ b/pki/base/java-tools/build.xml
@@ -0,0 +1,585 @@
+<!-- ### BEGIN COPYRIGHT BLOCK ###
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Copyright (C) 2007 Red Hat, Inc.
+ All rights reserved.
+ ### END COPYRIGHT BLOCK ### -->
+<project name="java-tools" default="main" basedir=".">
+
+ <import file="config/product.xml"/>
+ <import file="config/product-ext.xml" optional="true"/>
+
+ <property name="jss.home" value="${jni-jar.home}${dirsec}"/>
+ <property name="jss.jar" value="${jss.home}/jss4.jar"/>
+ <property name="osutil.jar" value="${jni-jar.home}/osutil.jar"/>
+ <property name="ldapjdk.jar" value="${jar.home}/ldapjdk.jar"/>
+ <property name="pki-certsrv.jar" value="${pki-jar.home}/pki-certsrv.jar"/>
+ <property name="pki-cms.jar" value="${pki-jar.home}/pki-cms.jar"/>
+ <property name="pki-cmsutil.jar" value="${pki-jar.home}/pki-cmsutil.jar"/>
+ <property name="pki-nsutil.jar" value="${pki-jar.home}/pki-nsutil.jar"/>
+
+ <path id="classpath">
+ <pathelement location="${jss.jar}"/>
+ <pathelement location="${ldapjdk.jar}"/>
+ <pathelement location="${pki-nsutil.jar}"/>
+ <pathelement location="${osutil.jar}"/>
+ <pathelement location="${pki-cmsutil.jar}"/>
+ <pathelement location="${pki-cms.jar}"/>
+ <pathelement location="${pki-certsrv.jar}"/>
+ </path>
+ <path id="javadoc_classpath">
+ <path refid="classpath"/>
+ <pathelement location="./build/classes"/>
+ </path>
+
+
+ <target name="clean"
+ depends=""
+ description="--> remove component directories">
+ <echo message="${begin.clean.log.message}"/>
+ <delete dir="${dist.base}"/>
+ <delete dir="${build.dir}"/>
+ <echo message="${end.clean.log.message}"/>
+ </target>
+
+
+ <target name="download"
+ depends=""
+ description="--> download dependent components">
+ <echo message="${begin.download.log.message}"/>
+ <echo message="${empty.download.log.message}"/>
+ <echo message="${end.download.log.message}"/>
+ </target>
+
+
+ <target name="compile_java"
+ depends=""
+ description="--> compile java source code into classes">
+ <echo message="${begin.compile.java.log.message}"/>
+ <mkdir dir="${build.classes}"/>
+ <javac debug="on"
+ srcdir="${src.dir}/com/netscape"
+ destdir="${build.classes}">
+ <classpath refid="classpath"/>
+ </javac>
+ <echo message="${end.compile.java.log.message}"/>
+ </target>
+
+
+ <target name="build_jars"
+ depends="compile_java"
+ description="--> generate jar files">
+ <echo message="${begin.build.jars.log.message}"/>
+ <mkdir dir="${build.jars}"/>
+ <jar jarfile="${build.jars}/pki-tools.jar">
+ <fileset dir="${build.classes}">
+ <include name="com/netscape/**"/>
+ </fileset>
+ </jar>
+ <echo message="${end.build.jars.log.message}"/>
+ </target>
+
+
+ <target name="build_jni_headers"
+ depends="compile_java"
+ description="--> generate jni header files">
+ <echo message="${begin.build.jni.headers.log.message}"/>
+ <echo message="${empty.build.jni.headers.log.message}"/>
+ <echo message="${end.build.jni.headers.log.message}"/>
+ </target>
+
+
+ <target name="build"
+ depends="build_jars,build_jni_headers"
+ description="--> build classes, jars, and jni headers">
+ <echo message="${notify.build.log.message}"/>
+ </target>
+
+
+ <target name="compile_junit_tests"
+ depends="build"
+ description="--> compile junit test source code">
+ <echo message="${begin.compile.junit.tests.log.message}"/>
+ <echo message="${empty.compile.junit.tests.log.message}"/>
+ <echo message="${end.compile.junit.tests.log.message}"/>
+ </target>
+
+
+ <target name="run_junit_tests"
+ depends="compile_junit_tests"
+ description="--> execute junit tests">
+ <echo message="${begin.run.junit.tests.log.message}"/>
+ <echo message="${empty.run.junit.tests.log.message}"/>
+ <echo message="${end.run.junit.tests.log.message}"/>
+ </target>
+
+
+ <target name="verify"
+ depends="run_junit_tests"
+ description="--> build and execute junit tests">
+ <echo message="${notify.verify.log.message}"/>
+ </target>
+
+
+ <target name="clean_javadocs"
+ depends=""
+ description="--> remove javadocs directory">
+ <echo message="${begin.clean.javadocs.log.message}"/>
+ <delete dir="${docs.dir}"/>
+ <echo message="${end.clean.javadocs.log.message}"/>
+ </target>
+
+
+ <target name="compose_javadocs"
+ depends="build"
+ description="--> generate javadocs">
+ <echo message="${begin.compose.javadocs.log.message}"/>
+ <mkdir dir="${docs.dir}"/>
+ <javadoc destdir="${docs.dir}"
+ maxmemory="512m"
+ author="true"
+ breakiterator="true"
+ version="true"
+ use="true"
+ windowtitle="${ant.project.name}"
+ classpathref="javadoc_classpath"
+ verbose="false">
+ <doctitle>
+ <![CDATA[<h1>${ant.project.name}</h1>]]>
+ </doctitle>
+ <fileset dir="src"
+ defaultexcludes="yes">
+ <include name="com/netscape/cmstools/**"/>
+ </fileset>
+ </javadoc>
+ <echo message="${end.compose.javadocs.log.message}"/>
+ </target>
+
+
+ <target name="document"
+ depends="clean_javadocs,compose_javadocs"
+ description="--> remove old javadocs and compose new javadocs">
+ <echo message="${notify.document.log.message}"/>
+ </target>
+
+
+ <target name="distribute_binaries"
+ depends="document"
+ description="--> create the zip and gzipped tar binary distributions">
+ <echo message="${begin.distribute.binaries.log.message}"/>
+ <mkdir dir="${dist.base.binaries}"/>
+ <mkdir dir="./build/cmds"/>
+
+ <echo message="${begin.binary.wrappers.log.message}"/>
+ <copy file="./templates/pki_java_command_wrapper"
+ tofile="./build/cmds/AtoB.tmp"/>
+ <exec executable="sed"
+ output="./build/cmds/AtoB">
+ <arg value="-e"/>
+ <arg value="s/\[PKI_PRODUCT\]/${product.prefix}/g"/>
+ <arg value="-e"/>
+ <arg value="s/\[PKI_COMMAND\]/AtoB/g"/>
+ <arg value="./build/cmds/AtoB.tmp"/>
+ </exec>
+ <delete file="./build/cmds/AtoB.tmp"/>
+
+ <copy file="./templates/pki_java_command_wrapper"
+ tofile="./build/cmds/AuditVerify.tmp"/>
+ <exec executable="sed"
+ output="./build/cmds/AuditVerify">
+ <arg value="-e"/>
+ <arg value="s/\[PKI_PRODUCT\]/${product.prefix}/g"/>
+ <arg value="-e"/>
+ <arg value="s/\[PKI_COMMAND\]/AuditVerify/g"/>
+ <arg value="./build/cmds/AuditVerify.tmp"/>
+ </exec>
+ <delete file="./build/cmds/AuditVerify.tmp"/>
+
+ <copy file="./templates/pki_java_command_wrapper"
+ tofile="./build/cmds/BtoA.tmp"/>
+ <exec executable="sed"
+ output="./build/cmds/BtoA">
+ <arg value="-e"/>
+ <arg value="s/\[PKI_PRODUCT\]/${product.prefix}/g"/>
+ <arg value="-e"/>
+ <arg value="s/\[PKI_COMMAND\]/BtoA/g"/>
+ <arg value="./build/cmds/BtoA.tmp"/>
+ </exec>
+ <delete file="./build/cmds/BtoA.tmp"/>
+
+ <copy file="./templates/pki_java_command_wrapper"
+ tofile="./build/cmds/CMCEnroll.tmp"/>
+ <exec executable="sed"
+ output="./build/cmds/CMCEnroll">
+ <arg value="-e"/>
+ <arg value="s/\[PKI_PRODUCT\]/${product.prefix}/g"/>
+ <arg value="-e"/>
+ <arg value="s/\[PKI_COMMAND\]/CMCEnroll/g"/>
+ <arg value="./build/cmds/CMCEnroll.tmp"/>
+ </exec>
+ <delete file="./build/cmds/CMCEnroll.tmp"/>
+
+ <copy file="./templates/pki_java_command_wrapper"
+ tofile="./build/cmds/CMCRequest.tmp"/>
+ <exec executable="sed"
+ output="./build/cmds/CMCRequest">
+ <arg value="-e"/>
+ <arg value="s/\[PKI_PRODUCT\]/${product.prefix}/g"/>
+ <arg value="-e"/>
+ <arg value="s/\[PKI_COMMAND\]/CMCRequest/g"/>
+ <arg value="./build/cmds/CMCRequest.tmp"/>
+ </exec>
+ <delete file="./build/cmds/CMCRequest.tmp"/>
+
+ <copy file="./templates/pki_java_command_wrapper"
+ tofile="./build/cmds/CMCResponse.tmp"/>
+ <exec executable="sed"
+ output="./build/cmds/CMCResponse">
+ <arg value="-e"/>
+ <arg value="s/\[PKI_PRODUCT\]/${product.prefix}/g"/>
+ <arg value="-e"/>
+ <arg value="s/\[PKI_COMMAND\]/CMCResponse/g"/>
+ <arg value="./build/cmds/CMCResponse.tmp"/>
+ </exec>
+ <delete file="./build/cmds/CMCResponse.tmp"/>
+
+ <copy file="./templates/pki_java_command_wrapper"
+ tofile="./build/cmds/CMCRevoke.tmp"/>
+ <exec executable="sed"
+ output="./build/cmds/CMCRevoke">
+ <arg value="-e"/>
+ <arg value="s/\[PKI_PRODUCT\]/${product.prefix}/g"/>
+ <arg value="-e"/>
+ <arg value="s/\[PKI_COMMAND\]/CMCRevoke/g"/>
+ <arg value="./build/cmds/CMCRevoke.tmp"/>
+ </exec>
+ <delete file="./build/cmds/CMCRevoke.tmp"/>
+
+ <copy file="./templates/pki_java_command_wrapper"
+ tofile="./build/cmds/CRMFPopClient.tmp"/>
+ <exec executable="sed"
+ output="./build/cmds/CRMFPopClient">
+ <arg value="-e"/>
+ <arg value="s/\[PKI_PRODUCT\]/${product.prefix}/g"/>
+ <arg value="-e"/>
+ <arg value="s/\[PKI_COMMAND\]/CRMFPopClient/g"/>
+ <arg value="./build/cmds/CRMFPopClient.tmp"/>
+ </exec>
+ <delete file="./build/cmds/CRMFPopClient.tmp"/>
+
+ <copy file="./templates/pki_java_command_wrapper"
+ tofile="./build/cmds/ExtJoiner.tmp"/>
+ <exec executable="sed"
+ output="./build/cmds/ExtJoiner">
+ <arg value="-e"/>
+ <arg value="s/\[PKI_PRODUCT\]/${product.prefix}/g"/>
+ <arg value="-e"/>
+ <arg value="s/\[PKI_COMMAND\]/ExtJoiner/g"/>
+ <arg value="./build/cmds/ExtJoiner.tmp"/>
+ </exec>
+ <delete file="./build/cmds/ExtJoiner.tmp"/>
+
+ <copy file="./templates/pki_java_command_wrapper"
+ tofile="./build/cmds/GenExtKeyUsage.tmp"/>
+ <exec executable="sed"
+ output="./build/cmds/GenExtKeyUsage">
+ <arg value="-e"/>
+ <arg value="s/\[PKI_PRODUCT\]/${product.prefix}/g"/>
+ <arg value="-e"/>
+ <arg value="s/\[PKI_COMMAND\]/GenExtKeyUsage/g"/>
+ <arg value="./build/cmds/GenExtKeyUsage.tmp"/>
+ </exec>
+ <delete file="./build/cmds/GenExtKeyUsage.tmp"/>
+
+ <copy file="./templates/pki_java_command_wrapper"
+ tofile="./build/cmds/GenIssuerAltNameExt.tmp"/>
+ <exec executable="sed"
+ output="./build/cmds/GenIssuerAltNameExt">
+ <arg value="-e"/>
+ <arg value="s/\[PKI_PRODUCT\]/${product.prefix}/g"/>
+ <arg value="-e"/>
+ <arg value="s/\[PKI_COMMAND\]/GenIssuerAltNameExt/g"/>
+ <arg value="./build/cmds/GenIssuerAltNameExt.tmp"/>
+ </exec>
+ <delete file="./build/cmds/GenIssuerAltNameExt.tmp"/>
+
+ <copy file="./templates/pki_java_command_wrapper"
+ tofile="./build/cmds/GenSubjectAltNameExt.tmp"/>
+ <exec executable="sed"
+ output="./build/cmds/GenSubjectAltNameExt">
+ <arg value="-e"/>
+ <arg value="s/\[PKI_PRODUCT\]/${product.prefix}/g"/>
+ <arg value="-e"/>
+ <arg value="s/\[PKI_COMMAND\]/GenSubjectAltNameExt/g"/>
+ <arg value="./build/cmds/GenSubjectAltNameExt.tmp"/>
+ </exec>
+ <delete file="./build/cmds/GenSubjectAltNameExt.tmp"/>
+
+ <copy file="./templates/pki_java_command_wrapper"
+ tofile="./build/cmds/HttpClient.tmp"/>
+ <exec executable="sed"
+ output="./build/cmds/HttpClient">
+ <arg value="-e"/>
+ <arg value="s/\[PKI_PRODUCT\]/${product.prefix}/g"/>
+ <arg value="-e"/>
+ <arg value="s/\[PKI_COMMAND\]/HttpClient/g"/>
+ <arg value="./build/cmds/HttpClient.tmp"/>
+ </exec>
+ <delete file="./build/cmds/HttpClient.tmp"/>
+
+ <copy file="./templates/pki_java_command_wrapper"
+ tofile="./build/cmds/OCSPClient.tmp"/>
+ <exec executable="sed" output="./build/cmds/OCSPClient">
+ <arg value="-e"/>
+ <arg value="s/\[PKI_PRODUCT\]/${product.prefix}/g"/>
+ <arg value="-e"/>
+ <arg value="s/\[PKI_COMMAND\]/OCSPClient/g"/>
+ <arg value="./build/cmds/OCSPClient.tmp"/>
+ </exec>
+ <delete file="./build/cmds/OCSPClient.tmp"/>
+
+ <copy file="./templates/pki_java_command_wrapper"
+ tofile="./build/cmds/PKCS10Client.tmp"/>
+ <exec executable="sed"
+ output="./build/cmds/PKCS10Client">
+ <arg value="-e"/>
+ <arg value="s/\[PKI_PRODUCT\]/${product.prefix}/g"/>
+ <arg value="-e"/>
+ <arg value="s/\[PKI_COMMAND\]/PKCS10Client/g"/>
+ <arg value="./build/cmds/PKCS10Client.tmp"/>
+ </exec>
+ <delete file="./build/cmds/PKCS10Client.tmp"/>
+
+ <copy file="./templates/pki_java_command_wrapper"
+ tofile="./build/cmds/PKCS12Export.tmp"/>
+ <exec executable="sed"
+ output="./build/cmds/PKCS12Export">
+ <arg value="-e"/>
+ <arg value="s/\[PKI_PRODUCT\]/${product.prefix}/g"/>
+ <arg value="-e"/>
+ <arg value="s/\[PKI_COMMAND\]/PKCS12Export/g"/>
+ <arg value="./build/cmds/PKCS12Export.tmp"/>
+ </exec>
+ <delete file="./build/cmds/PKCS12Export.tmp"/>
+
+ <copy file="./templates/pretty_print_cert_command_wrapper"
+ tofile="./build/cmds/PrettyPrintCert.tmp"/>
+ <exec executable="sed"
+ output="./build/cmds/PrettyPrintCert">
+ <arg value="-e"/>
+ <arg value="s/\[PKI_PRODUCT\]/${product.prefix}/g"/>
+ <arg value="-e"/>
+ <arg value="s/\[PKI_COMMAND\]/PrettyPrintCert/g"/>
+ <arg value="./build/cmds/PrettyPrintCert.tmp"/>
+ </exec>
+ <delete file="./build/cmds/PrettyPrintCert.tmp"/>
+
+ <copy file="./templates/pretty_print_crl_command_wrapper"
+ tofile="./build/cmds/PrettyPrintCrl.tmp"/>
+ <exec executable="sed"
+ output="./build/cmds/PrettyPrintCrl">
+ <arg value="-e"/>
+ <arg value="s/\[PKI_PRODUCT\]/${product.prefix}/g"/>
+ <arg value="-e"/>
+ <arg value="s/\[PKI_COMMAND\]/PrettyPrintCrl/g"/>
+ <arg value="./build/cmds/PrettyPrintCrl.tmp"/>
+ </exec>
+ <delete file="./build/cmds/PrettyPrintCrl.tmp"/>
+
+ <copy file="./templates/pki_java_command_wrapper"
+ tofile="./build/cmds/TokenInfo.tmp"/>
+ <exec executable="sed"
+ output="./build/cmds/TokenInfo">
+ <arg value="-e"/>
+ <arg value="s/\[PKI_PRODUCT\]/${product.prefix}/g"/>
+ <arg value="-e"/>
+ <arg value="s/\[PKI_COMMAND\]/TokenInfo/g"/>
+ <arg value="./build/cmds/TokenInfo.tmp"/>
+ </exec>
+ <delete file="./build/cmds/TokenInfo.tmp"/>
+ <echo message="${end.binary.wrappers.log.message}"/>
+
+ <echo message="${begin.binary.zip.log.message}"/>
+ <zip destfile="${dist.base.binaries}/${dist.name}.zip">
+ <zipfileset dir="./build/jars"
+ filemode="755"
+ prefix="usr/share/java/${product.prefix}">
+ <include name="**"/>
+ </zipfileset>
+ <zipfileset dir="./build/cmds"
+ filemode="755"
+ prefix="usr/bin">
+ <include name="**"/>
+ </zipfileset>
+ <zipfileset dir="./templates"
+ filemode="755"
+ prefix="usr/share/${product.prefix}">
+ <include name="**"/>
+ </zipfileset>
+ <zipfileset dir="."
+ filemode="644"
+ prefix="usr/share/doc/${dist.name}">
+ <include name="EULA"/>
+ <include name="LICENSE"/>
+ </zipfileset>
+ <zipfileset dir="./docs"
+ filemode="755"
+ prefix="usr/share/javadoc/${product.name}-${version}">
+ <include name="**"/>
+ </zipfileset>
+ </zip>
+ <echo message="${end.binary.zip.log.message}"/>
+
+ <echo message="${begin.binary.tar.log.message}"/>
+ <tar longfile="gnu"
+ destfile="${dist.base.binaries}/${dist.name}.tar">
+ <tarfileset dir="./build/jars"
+ mode="755"
+ prefix="${dist.name}/usr/share/java/${product.prefix}">
+ <include name="**"/>
+ </tarfileset>
+ <tarfileset dir="./build/cmds"
+ mode="755"
+ prefix="usr/bin">
+ <include name="**"/>
+ </tarfileset>
+ <tarfileset dir="./templates"
+ mode="755"
+ prefix="usr/share/${product.prefix}">
+ <include name="**"/>
+ </tarfileset>
+ <tarfileset dir="."
+ mode="644"
+ prefix="${dist.name}/usr/share/doc/${dist.name}">
+ <include name="EULA"/>
+ <include name="LICENSE"/>
+ </tarfileset>
+ <tarfileset dir="./docs"
+ mode="755"
+ prefix="${dist.name}/usr/share/javadoc/${product.name}-${version}">
+ <include name="**"/>
+ </tarfileset>
+ </tar>
+ <echo message="${end.binary.tar.log.message}"/>
+
+ <echo message="${begin.binary.gtar.log.message}"/>
+ <gzip destfile="${dist.base.binaries}/${dist.name}.tar.gz"
+ src="${dist.base.binaries}/${dist.name}.tar"/>
+ <delete file="${dist.base.binaries}/${dist.name}.tar"/>
+ <delete dir="${dist.name}"/>
+ <checksum fileext=".md5">
+ <fileset dir="${dist.base.binaries}/">
+ <include name="**/*"/>
+ <exclude name="**/*.asc"/>
+ <exclude name="**/*.md5"/>
+ </fileset>
+ </checksum>
+ <checksum fileext=".sha1"
+ algorithm="SHA">
+ <fileset dir="${dist.base.binaries}/">
+ <include name="**/*"/>
+ <exclude name="**/*.asc"/>
+ <exclude name="**/*.md5"/>
+ </fileset>
+ </checksum>
+ <echo message="${end.binary.gtar.log.message}"/>
+
+ <echo message="${end.distribute.binaries.log.message}"/>
+ </target>
+
+
+ <target name="distribute_source"
+ depends=""
+ description="--> create the zip and gzipped tar source distributions">
+ <echo message="${begin.distribute.source.log.message}"/>
+ <mkdir dir="${dist.base.source}"/>
+
+ <echo message="${begin.source.zip.log.message}"/>
+ <zip destfile="${dist.base.source}/${src.dist.name}.zip">
+ <zipfileset dir="."
+ filemode="644"
+ prefix="${src.dist.name}">
+ <include name="${specfile}"/>
+ <include name="EULA"/>
+ <include name="LICENSE"/>
+ <include name="build.xml"/>
+ <include name="config/product*.xml"/>
+ <include name="config/release*.xml"/>
+ <include name="release"/>
+ <include name="src/**"/>
+ <include name="templates/**"/>
+ </zipfileset>
+ </zip>
+ <echo message="${end.source.zip.log.message}"/>
+
+ <echo message="${begin.source.tar.log.message}"/>
+ <tar longfile="gnu"
+ destfile="${dist.base.source}/${src.dist.name}.tar">
+ <tarfileset dir="."
+ mode="644"
+ prefix="${src.dist.name}">
+ <include name="${specfile}"/>
+ <include name="EULA"/>
+ <include name="LICENSE"/>
+ <include name="build.xml"/>
+ <include name="config/product*.xml"/>
+ <include name="config/release*.xml"/>
+ <include name="release"/>
+ <include name="src/**"/>
+ <include name="templates/**"/>
+ </tarfileset>
+ </tar>
+ <echo message="${end.source.tar.log.message}"/>
+
+ <echo message="${begin.source.gtar.log.message}"/>
+ <gzip destfile="${dist.base.source}/${src.dist.name}.tar.gz"
+ src="${dist.base.source}/${src.dist.name}.tar"/>
+ <delete file="${dist.base.source}/${src.dist.name}.tar"/>
+ <delete dir="${dist.name}"/>
+ <checksum fileext=".md5">
+ <fileset dir="${dist.base.source}/">
+ <include name="**/*"/>
+ <exclude name="**/*.asc"/>
+ <exclude name="**/*.md5"/>
+ </fileset>
+ </checksum>
+ <checksum fileext=".sha1"
+ algorithm="SHA">
+ <fileset dir="${dist.base.source}/">
+ <include name="**/*"/>
+ <exclude name="**/*.asc"/>
+ <exclude name="**/*.md5"/>
+ </fileset>
+ </checksum>
+ <echo message="${end.source.gtar.log.message}"/>
+
+ <echo message="${end.distribute.source.log.message}"/>
+ </target>
+
+
+ <target name="distribute"
+ depends="distribute_binaries,distribute_source"
+ description="--> create binary and source component distributions">
+ <echo message="${notify.distribute.log.message}"/>
+ </target>
+
+
+ <target name="main"
+ depends="clean,distribute"
+ description="--> clean, build, verify, document, distribute [default]">
+ <echo message="${notify.main.log.message}"/>
+ </target>
+
+</project>
+
diff --git a/pki/base/java-tools/doc/README b/pki/base/java-tools/doc/README
new file mode 100644
index 000000000..93d3734fb
--- /dev/null
+++ b/pki/base/java-tools/doc/README
@@ -0,0 +1,133 @@
+ Certificate System
+ Java Command Line Utilities
+
+
+Command Line Utility Purpose
+==============================================================================
+AtoB <input file> <output file> A command line utility utilized
+ to convert an ASCII BASE 64
+ blob into a BINARY BASE 64 blob.
+
+AuditVerify A command line utility utilized
+ to verify signatures in signed
+ audit log files.
+
+BtoA <input file> <output file> A command line utility utilized
+ to convert a BINARY BASE 64
+ blob into an ASCII BASE 64 blob.
+
+CMCEnroll A command line utility used to
+ sign a certificate enrollment
+ request with an agent's
+ certificate.
+
+CMCRequest A command line utility used to
+ construct a Certificate
+ Management Messages over
+ CMS (CMC) request.
+
+CMCResponse A command line utility used to
+ parse a CMC response.
+
+CMCRevoke A command line utility used to
+ sign a revocation request with
+ an agent's certificate.
+
+CRMFPopClient A command line utility used to
+ generate CRMF requests with
+ proof of possession (POP).
+
+ExtJoiner <ext_file0> . . . <ext_file9> A command line utility utilized
+ to join a sequence of extensions
+ together so that the final
+ output can be used in the
+ configuration wizard for
+ specifying extra extensions
+ in default certificates
+ (i. e. - CA certificate,
+ SSL certificate).
+
+GenExtKeyUsage [true|false] A command line utility utilized
+ <OID_1> . . . <OID_9> to generate a DER-encoded
+ Extended Key Usage extension.
+ The first parameter is the
+ criticality of the extension,
+ true or false. The OIDs to be
+ included in the extension are
+ passed as command-line
+ arguments. The OIDs are
+ described in RFC 2459. For
+ example, the OID for code
+ signing is 1.3.6.1.5.5.7.3.3.
+
+GenIssuerAltNameExt <general_type0> A command line utility utilized
+ <general_name0> to generate an issuer
+ . . . alternative name extension in
+ <general_type3> base-64 encoding. The encoding
+ <general_name3> output can be used with the
+ configuration wizard, where:
+ <general_type#> can be one
+ of the following strings:
+ DNSName
+ EDIPartyName
+ IPAddressName
+ URIName
+ RFC822Name
+ OIDName
+ X500Name
+ <general_name#> is a string
+
+GenSubjectAltNameExt <general_type0> A command line utility utilized
+ <general_name0> to generate a subject
+ . . . alternative name extension in
+ <general_type3> base-64 encoding. The encoding
+ <general_name3> output can be used with the
+ configuration wizard, where:
+ <general_type#> can be one
+ of the following strings:
+ DNSName
+ EDIPartyName
+ IPAddressName
+ URIName
+ RFC822Name
+ OIDName
+ X500Name
+ <general_name#> is a string
+
+HttpClient A command line utility used
+ to communicate with any
+ http/https server.
+
+OCSPClient A command line utility that
+ verifies certificate status by
+ submitting Online Certificate
+ Status Protocol (OCSP) requests
+ to an instance of an OCSP
+ subsystem.
+
+PKCS10Client A command line utility that
+ generates a Public Key
+ Cryptography Standards
+ (PKCS) #10 enrollment
+ request.
+
+PKCS12Export A command line utility utilized
+ to create PKCS12 file.
+
+PrettyPrintCert <input file> [output file] A command line utility utilized
+ to print the contents of a
+ certificate stored as an ASCII
+ BASE 64 encoded blob in a
+ user-friendly manner.
+
+PrettyPrintCrl <input file> [output file] A command line utility utilized
+ to print the contents of a
+ Certificate Revocation List
+ (CRL) stored as an ASCII
+ BASE 64 encoded blob in a
+ user-friendly manner.
+
+TokenInfo A command line utility utilized
+ to display all external HSMs
+ visible to JSS.
+
diff --git a/pki/base/java-tools/src/CMakeLists.txt b/pki/base/java-tools/src/CMakeLists.txt
new file mode 100644
index 000000000..6d40bf39b
--- /dev/null
+++ b/pki/base/java-tools/src/CMakeLists.txt
@@ -0,0 +1,81 @@
+project(pki-tools_java Java)
+
+find_file(JSS_JAR
+ NAMES
+ jss4.jar
+ PATHS
+ /usr/lib/java
+ /usr/share/java
+)
+
+find_file(OSUTIL_JAR
+ NAMES
+ osutil.jar
+ PATHS
+ /usr/lib/java
+ /usr/share/java
+)
+
+find_file(XALAN_JAR
+ NAMES
+ xalan-j2.jar
+ PATHS
+ /usr/lib/java
+ /usr/share/java
+)
+
+find_file(XERCES_JAR
+ NAMES
+ xerces-j2.jar
+ PATHS
+ /usr/lib/java
+ /usr/share/java
+)
+
+set(pki-tools_java_SRCS
+ com/netscape/cmstools/PrettyPrintCrl.java
+ com/netscape/cmstools/BtoA.java
+ com/netscape/cmstools/PasswordCache.java
+ com/netscape/cmstools/OCSPClient.java
+ com/netscape/cmstools/PKCS12Export.java
+ com/netscape/cmstools/TestCRLSigning.java
+ com/netscape/cmstools/CRMFPopClient.java
+ com/netscape/cmstools/AuditVerify.java
+ com/netscape/cmstools/PrettyPrintCert.java
+ com/netscape/cmstools/HttpClient.java
+ com/netscape/cmstools/GenExtKeyUsage.java
+ com/netscape/cmstools/CMCRevoke.java
+ com/netscape/cmstools/TokenInfo.java
+ com/netscape/cmstools/CMCEnroll.java
+ com/netscape/cmstools/ExtJoiner.java
+ com/netscape/cmstools/CMCRequest.java
+ com/netscape/cmstools/AtoB.java
+ com/netscape/cmstools/GenIssuerAltNameExt.java
+ com/netscape/cmstools/GenSubjectAltNameExt.java
+ com/netscape/cmstools/CMCResponse.java
+ com/netscape/cmstools/PKCS10Client.java
+)
+
+set(CMAKE_JAVA_INCLUDE_PATH
+ ${PKI_NSUTIL_JAR} ${PKI_CMSUTIL_JAR}
+ ${XALAN_JAR} ${XERCES_JAR}
+ ${JSS_JAR} ${OSUTIL_JAR})
+
+set(CMAKE_JAVA_TARGET_VERSION ${APPLICATION_VERSION})
+
+# build pki-tools
+add_jar(pki-tools ${pki-tools_java_SRCS})
+add_dependencies(pki-tools osutil pki-nsutil pki-cmsutil)
+install_jar(pki-tools ${JAVA_JAR_INSTALL_DIR}/pki)
+set(PKI_TOOLS_JAR ${pki-tools_JAR_FILE} CACHE INTERNAL "pki-tools jar file")
+
+create_javadoc(pki-java-tools-${APPLICATION_VERSION}
+ FILES ${pki-tools_java_SRCS}
+ CLASSPATH ${CMAKE_JAVA_INCLUDE_PATH}
+ WINDOWTITLE "pki-java-tools"
+ DOCTITLE "<h1>pki-java-tools</h1>"
+ AUTHOR TRUE
+ USE TRUE
+ VERSION TRUE
+)
+add_dependencies(pki-java-tools-${APPLICATION_VERSION}_javadoc pki-tools)
diff --git a/pki/base/java-tools/src/com/netscape/cmstools/AtoB.java b/pki/base/java-tools/src/com/netscape/cmstools/AtoB.java
new file mode 100644
index 000000000..bdeaee273
--- /dev/null
+++ b/pki/base/java-tools/src/com/netscape/cmstools/AtoB.java
@@ -0,0 +1,140 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmstools;
+
+
+import java.io.*;
+
+
+/**
+ * The AtoB class is a utility program designed to "translate" an ASCII
+ * BASE 64 encoded blob into a BINARY BASE 64 encoded blob. It assumes
+ * that the name of a data file is passed to the program via the command line,
+ * and that the contents contain a blob encoded in an ASCII BASE 64
+ * format. Note that the data file may contain an optional "-----BEGIN" header
+ * and/or an optional "-----END" trailer.
+ *
+ * <P>
+ * The program may be invoked as follows:
+ * <PRE>
+ *
+ * AtoB &lt;input filename&gt; &lt;output filename&gt;
+ *
+ * NOTE: &lt;input filename&gt; must contain an ASCII
+ * BASE 64 encoded blob
+ *
+ * &lt;output filename&gt; contains a BINARY
+ * BASE 64 encoded blob
+ * </PRE>
+ *
+ * @version $Revision$, $Date$
+ */
+public class AtoB {
+ // Define constants
+ public static final int ARGC = 2;
+ public static final String HEADER = "-----BEGIN";
+ public static final String TRAILER = "-----END";
+
+ public static void main(String argv[]) {
+
+ BufferedReader inputBlob = null;
+ String asciiBASE64BlobChunk = new String();
+ String asciiBASE64Blob = new String();
+ byte binaryBASE64Blob[] = null;
+ FileOutputStream outputBlob = null;
+
+ // (1) Check that two arguments were submitted to the program
+ if (argv.length != ARGC) {
+ System.out.println("Usage: AtoB " +
+ "<input filename> " +
+ "<output filename>");
+ return;
+ }
+
+ // (2) Create a DataInputStream() object to the BASE 64
+ // encoded blob contained within the file
+ // specified on the command line
+ try {
+ inputBlob = new BufferedReader(new InputStreamReader(
+ new BufferedInputStream(
+ new FileInputStream(
+ argv[0]))));
+ } catch (FileNotFoundException e) {
+ System.out.println("AtoB(): can''t find file " +
+ argv[0] + ":\n" + e);
+ return;
+ }
+
+ // (3) Read the entire contents of the specified BASE 64 encoded
+ // blob into a String() object throwing away any
+ // headers beginning with HEADER and any trailers beginning
+ // with TRAILER
+ try {
+ while ((asciiBASE64BlobChunk = inputBlob.readLine()) != null) {
+ if (!(asciiBASE64BlobChunk.startsWith(HEADER)) &&
+ !(asciiBASE64BlobChunk.startsWith(TRAILER))) {
+ asciiBASE64Blob += asciiBASE64BlobChunk.trim();
+ }
+ }
+ } catch (IOException e) {
+ System.out.println("AtoB(): Unexpected BASE64 " +
+ "encoded error encountered in readLine():\n" +
+ e);
+ }
+
+ // (4) Close the DataInputStream() object
+ try {
+ inputBlob.close();
+ } catch (IOException e) {
+ System.out.println("AtoB(): Unexpected BASE64 " +
+ "encoded error encountered in close():\n" + e);
+ }
+
+ // (5) Decode the ASCII BASE 64 blob enclosed in the
+ // String() object into a BINARY BASE 64 byte[] object
+
+ binaryBASE64Blob = com.netscape.osutil.OSUtil.AtoB(asciiBASE64Blob);
+
+ // (6) Finally, print the actual AtoB blob to the
+ // specified output file
+ try {
+ outputBlob = new FileOutputStream(argv[1]);
+ } catch (IOException e) {
+ System.out.println("AtoB(): unable to open file " +
+ argv[1] + " for writing:\n" + e);
+ return;
+ }
+
+ try {
+ outputBlob.write(binaryBASE64Blob);
+ } catch (IOException e) {
+ System.out.println("AtoB(): I/O error " +
+ "encountered during write():\n" +
+ e);
+ }
+
+ try {
+ outputBlob.close();
+ } catch (IOException e) {
+ System.out.println("AtoB(): Unexpected error " +
+ "encountered while attempting to close() " +
+ argv[1] + ":\n" + e);
+ }
+ }
+}
+
diff --git a/pki/base/java-tools/src/com/netscape/cmstools/AuditVerify.java b/pki/base/java-tools/src/com/netscape/cmstools/AuditVerify.java
new file mode 100644
index 000000000..66a6a6cd8
--- /dev/null
+++ b/pki/base/java-tools/src/com/netscape/cmstools/AuditVerify.java
@@ -0,0 +1,322 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmstools;
+
+
+import java.io.*;
+import java.util.*;
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.crypto.X509Certificate;
+import org.mozilla.jss.crypto.ObjectNotFoundException;
+import org.mozilla.jss.util.Base64InputStream;
+import java.security.*;
+import java.security.interfaces.*;
+import netscape.security.x509.X509CertImpl;
+
+/**
+ * Tool for verifying signed audit logs
+ *
+ * @version $Revision$, $Date$
+ */
+public class AuditVerify {
+
+ private static void usage() {
+ System.out.println("Usage: AuditVerify -d <dbdir> -n <signing certificate nickname> -a <log list file> [-P <cert/key db prefix>] [-v]");
+ System.exit(1);
+ }
+
+ public static final String CRYPTO_PROVIDER = "Mozilla-JSS";
+
+ public static byte[] base64decode(String input) throws Exception {
+ return com.netscape.osutil.OSUtil.AtoB(input);
+ }
+
+ // We always sign 0x0a as the line separator, regardless of what
+ // line separator characters are used in the log file. This helps
+ // signature verification be platform-independent.
+ private static final byte LINE_SEP_BYTE = 0x0a;
+
+ private static void output(int linenum, String mesg) throws IOException {
+ System.out.println("Line " + linenum + ": " + mesg);
+ }
+
+ private static void writeFile(String curfileName) {
+ System.out.println("======\nFile: " + curfileName + "\n======");
+ }
+
+ private static void writeSigStatus(int linenum, String sigStartFile,
+ int sigStartLine, String sigStopFile, int sigStopLine, String mesg)
+ throws IOException
+ {
+ output(linenum, mesg + ": signature of " + sigStartFile + ":" +
+ sigStartLine + " to " + sigStopFile + ":" + sigStopLine);
+ }
+
+ private static class PrefixFilter implements FilenameFilter {
+ private String prefix;
+ public PrefixFilter(String prefix) {
+ this.prefix = prefix;
+ }
+ public boolean accept(File dir, String name) {
+ // look for <prefix>cert* in this directory
+ return( name.indexOf(prefix + "cert") != -1 );
+ }
+ }
+
+ public static boolean validPrefix(String configDir, String prefix)
+ throws IOException
+ {
+ File dir = new File(configDir);
+ if( ! dir.isDirectory() ) {
+ System.out.println("ERROR: \"" + dir + "\" is not a directory");
+ usage();
+ }
+
+ String matchingFiles[] = dir.list( new PrefixFilter(prefix) );
+
+ // prefix may be valid if at least one file matched the pattern
+ return (matchingFiles.length > 0);
+ }
+
+ public static boolean isSigningCert(X509CertImpl cert) {
+ boolean[] keyUsage = null;
+
+ try {
+ keyUsage = cert.getKeyUsage();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return (keyUsage == null) ? false : keyUsage[0];
+ }
+
+
+ public static void main(String args[]) {
+ try {
+
+ String dbdir = null;
+ String logListFile = null;
+ String signerNick = null;
+ String prefix = null;
+ boolean verbose = false;
+
+ for(int i = 0; i < args.length; ++i) {
+ if( args[i].equals("-d") ) {
+ if( ++i >= args.length ) usage();
+ dbdir = args[i];
+ } else if( args[i].equals("-a") ) {
+ if( ++i >= args.length ) usage();
+ logListFile = args[i];
+ } else if( args[i].equals("-n") ) {
+ if( ++i >= args.length ) usage();
+ signerNick = args[i];
+ } else if( args[i].equals("-P") ) {
+ if( ++i >= args.length ) usage();
+ prefix = args[i];
+ } else if( args[i].equals("-v") ) {
+ verbose = true;
+ } else {
+ System.out.println("Unrecognized argument(" + i + "): "
+ + args[i]);
+ usage();
+ }
+ }
+ if( dbdir == null || logListFile == null || signerNick == null) {
+ System.out.println("Argument omitted");
+ usage();
+ }
+
+ // get list of log files
+ Vector logFiles = new Vector();
+ BufferedReader r = new BufferedReader(new FileReader(logListFile));
+ String listLine;
+ while( (listLine = r.readLine()) != null ) {
+ StringTokenizer tok = new StringTokenizer(listLine, ",");
+ while( tok.hasMoreElements() ) {
+ logFiles.addElement( ((String)tok.nextElement()).trim());
+ }
+ }
+ if( logFiles.size() == 0 ) {
+ System.out.println("Error: no log files listed in " + logListFile);
+ System.exit(1);
+ }
+
+ // initialize crypto stuff
+ if( prefix == null ) {
+ if( ! validPrefix(dbdir, "")) {
+ System.out.println("ERROR: \"" + dbdir +
+ "\" does not contain any security databases");
+ usage();
+ }
+ CryptoManager.initialize(dbdir);
+ } else {
+ if( ! validPrefix(dbdir, prefix) ) {
+ System.out.println("ERROR: \"" + prefix +
+ "\" is not a valid prefix");
+ usage();
+ }
+ CryptoManager.initialize(
+ new CryptoManager.InitializationValues(dbdir, prefix, prefix,
+ "secmod.db")
+ );
+ }
+ CryptoManager cm = CryptoManager.getInstance();
+ X509Certificate signerCert = cm.findCertByNickname(signerNick);
+
+ X509CertImpl cert_i = null;
+ if (signerCert != null) {
+ byte[] signerCert_b = signerCert.getEncoded();
+ cert_i = new X509CertImpl(signerCert_b);
+ } else {
+ System.out.println("ERROR: signing certificate not found");
+ System.exit(1);
+ }
+
+ // verify signer's certificate
+ // not checking validity because we want to allow verifying old logs
+ //
+ if (!isSigningCert(cert_i)) {
+ System.out.println("info: signing certificate is not a signing certificate");
+ System.exit(1);
+ }
+
+ PublicKey pubk = signerCert.getPublicKey();
+ String sigAlgorithm=null;
+ if( pubk instanceof RSAPublicKey ) {
+ sigAlgorithm = "SHA-256/RSA";
+ } else if( pubk instanceof DSAPublicKey ) {
+ sigAlgorithm = "SHA-256/DSA";
+ } else {
+ System.out.println("Error: unknown key type: " +
+ pubk.getAlgorithm());
+ System.exit(1);
+ }
+ Signature sig = Signature.getInstance(sigAlgorithm, CRYPTO_PROVIDER);
+ sig.initVerify(pubk);
+
+ int goodSigCount = 0;
+ int badSigCount = 0;
+
+ int lastFileWritten = -1;
+
+ int sigStartLine = 1;
+ int sigStopLine = 1;
+ String sigStartFile = (String) logFiles.elementAt(0);
+ String sigStopFile = null;
+ int signedLines = 1;
+
+ boolean lastLineWasSig = false;
+
+ for( int curfile = 0; curfile < logFiles.size(); ++curfile) {
+ String curfileName = (String) logFiles.elementAt(curfile);
+ BufferedReader br = new BufferedReader(new FileReader(curfileName));
+
+ if( verbose ) {
+ writeFile(curfileName);
+ lastFileWritten = curfile;
+ }
+
+ String curLine;
+ int linenum = 0;
+ while( (curLine = br.readLine()) != null ) {
+ ++linenum;
+ if( curLine.indexOf("AUDIT_LOG_SIGNING") != -1 ) {
+ if( curfile == 0 && linenum == 1 ) {
+ // Ignore the first signature of the first file,
+ // since it signs data we don't have access to.
+ if( verbose ) {
+ output(linenum,
+ "Ignoring first signature of log series");
+ }
+ } else {
+ int sigStart = curLine.indexOf("sig: ") + 5;
+ if( sigStart < 5 ) {
+ output(linenum, "INVALID SIGNATURE");
+ ++badSigCount;
+ } else {
+ byte[] logSig =
+ base64decode(curLine.substring(sigStart));
+
+ // verify the signature
+ if( sig.verify(logSig) ) {
+ // signature verifies correctly
+ if( verbose ) {
+ writeSigStatus(linenum, sigStartFile,
+ sigStartLine, sigStopFile, sigStopLine,
+ "verification succeeded");
+ }
+ ++goodSigCount;
+ } else {
+ if( lastFileWritten < curfile ) {
+ writeFile(curfileName);
+ lastFileWritten = curfile;
+ }
+ writeSigStatus(linenum, sigStartFile,
+ sigStartLine, sigStopFile, sigStopLine,
+ "VERIFICATION FAILED");
+ ++badSigCount;
+ }
+ }
+ sig.initVerify(pubk);
+ signedLines = 0;
+ sigStartLine = linenum;
+ sigStartFile = curfileName;
+ }
+ }
+
+ byte[] lineBytes = curLine.getBytes("UTF-8");
+ sig.update(lineBytes);
+ sig.update(LINE_SEP_BYTE);
+ ++signedLines;
+ sigStopLine = linenum;
+ sigStopFile = curfileName;
+ }
+
+ }
+
+ // Make sure there were no unsigned log entries at the end.
+ // The first signed line is the previous signature, but anything
+ // more than that is data.
+ if( signedLines > 1 ) {
+ System.out.println(
+ "ERROR: log entries after " + sigStartFile
+ + ":" + sigStartLine + " are UNSIGNED");
+ badSigCount++;
+ }
+
+ System.out.println("\nVerification process complete.");
+ System.out.println("Valid signatures: " + goodSigCount);
+ System.out.println("Invalid signatures: " + badSigCount);
+
+ if( badSigCount > 0 ) {
+ System.exit(2);
+ } else {
+ System.exit(0);
+ }
+
+ } catch(FileNotFoundException fnfe) {
+ System.out.println(fnfe);
+ } catch(ObjectNotFoundException onfe) {
+ System.out.println("ERROR: certificate not found");
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+
+ System.out.println("Verification process FAILED.");
+ System.exit(1);
+ }
+}
diff --git a/pki/base/java-tools/src/com/netscape/cmstools/BtoA.java b/pki/base/java-tools/src/com/netscape/cmstools/BtoA.java
new file mode 100644
index 000000000..d00fb6122
--- /dev/null
+++ b/pki/base/java-tools/src/com/netscape/cmstools/BtoA.java
@@ -0,0 +1,116 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmstools;
+
+
+import java.io.*;
+
+
+/**
+ * The BtoA class is a utility program designed to "translate" a BINARY
+ * BASE 64 encoded blob into an ASCII BASE 64 encoded blob. It assumes
+ * that the name of a data file is passed to the program via the command line,
+ * and that the contents contain a blob encoded in a BINARY BASE 64
+ * format.
+ *
+ * <P>
+ * The program may be invoked as follows:
+ * <PRE>
+ *
+ * BtoA &lt;input filename&gt; &lt;output filename&gt;
+ *
+ * NOTE: &lt;input filename&gt; must contain a BINARY
+ * BASE 64 encoded blob
+ *
+ * &lt;output filename&gt; contains an ASCII
+ * BASE 64 encoded blob
+ * </PRE>
+ *
+ * @version $Revision$, $Date$
+ */
+public class BtoA {
+ // Define constants
+ public static final int ARGC = 2;
+
+ public static void main(String argv[]) {
+
+ FileInputStream inputBlob = null;
+ FileOutputStream outputBlob = null;
+
+ // (1) Check that two arguments were submitted to the program
+ if (argv.length != ARGC) {
+ System.out.println("Usage: BtoA " +
+ "<input filename> " +
+ "<output filename>");
+ return;
+ }
+
+ // (2) Create a DataInputStream() object to the BASE 64
+ // encoded blob contained within the file
+ // specified on the command line
+ try {
+ inputBlob = new FileInputStream(argv[0]);
+ } catch (FileNotFoundException e) {
+ System.out.println("BtoA(): can''t find file " +
+ argv[0] + ":\n" + e);
+ return;
+ }
+
+ // (3) Create a FileOutputStream() object to the BASE 64
+ // specified output file
+ try {
+ outputBlob = new FileOutputStream(argv[1]);
+ } catch (IOException e) {
+ System.out.println("BtoA(): unable to open file " +
+ argv[1] + " for writing:\n" + e);
+ return;
+ }
+
+ // (4) Convert the BINARY BASE 64 blob into an ASCII BASE 64 blob
+
+ try {
+ byte data[] = new byte[inputBlob.available()];
+ inputBlob.read(data);
+ String out = com.netscape.osutil.OSUtil.BtoA(data);
+ outputBlob.write(out.getBytes());
+ } catch (IOException e) {
+ System.out.println("BtoA(): Unexpected BASE64 " +
+ "encoded error encountered:\n" +
+ e);
+ }
+
+ // (5) Close the DataInputStream() object
+ try {
+ inputBlob.close();
+ } catch (IOException e) {
+ System.out.println("BtoA(): Unexpected input error " +
+ "encountered while attempting to close() " +
+ argv[0] + ":\n" + e);
+ }
+
+ // (6) Close the FileOutputStream() object
+ try {
+ outputBlob.close();
+ } catch (IOException e) {
+ System.out.println("BtoA(): Unexpected output error " +
+ "encountered while attempting to close() " +
+ argv[1] + ":\n" + e);
+ }
+ }
+}
+
diff --git a/pki/base/java-tools/src/com/netscape/cmstools/CMCEnroll.java b/pki/base/java-tools/src/com/netscape/cmstools/CMCEnroll.java
new file mode 100644
index 000000000..23c6547b4
--- /dev/null
+++ b/pki/base/java-tools/src/com/netscape/cmstools/CMCEnroll.java
@@ -0,0 +1,456 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmstools;
+
+
+import org.mozilla.jss.pkix.cmc.*;
+import org.mozilla.jss.pkix.cms.*;
+import org.mozilla.jss.pkix.cert.*;
+import org.mozilla.jss.pkix.primitive.*;
+import org.mozilla.jss.asn1.*;
+import org.mozilla.jss.pkcs10.*;
+import org.mozilla.jss.crypto.*;
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.crypto.CryptoToken;
+import org.mozilla.jss.crypto.SignatureAlgorithm;
+import org.mozilla.jss.crypto.DigestAlgorithm;
+import org.mozilla.jss.crypto.X509Certificate;
+import org.mozilla.jss.util.*;
+
+import org.mozilla.jss.*;
+
+import netscape.security.util.*;
+import netscape.security.x509.*;
+import netscape.security.pkcs.PKCS10;
+
+import java.security.*;
+import java.security.cert.CertificateException;
+import java.math.*;
+import java.security.Principal;
+import java.lang.*;
+import java.lang.reflect.*;
+import java.io.*;
+import java.util.*;
+
+
+
+/**
+ * Tool for signing PKCS #10 , return CMC enrollment request
+ *
+ * <P>
+ * @version $Revision$, $Date$
+
+ */
+public class CMCEnroll {
+
+ public static final String PR_REQUEST_CMC = "CMC";
+ public static final String PR_REQUEST_PKCS10 = "PKCS10";
+
+ public static final int ARGC = 4;
+ private static final String CERTDB = "cert8.db";
+ private static final String KEYDB = "key3.db";
+ public static final String HEADER = "-----BEGIN NEW CERTIFICATE REQUEST-----";
+ public static final String TRAILER = "-----END NEW CERTIFICATE REQUEST-----";
+
+ void cleanArgs(String[] s) {
+
+ }
+
+ public static X509Certificate getCertificate(String tokenname,
+ String nickname) throws Exception {
+ CryptoManager manager = CryptoManager.getInstance();
+ CryptoToken token = null;
+
+ if (tokenname.equals("internal")) {
+ token = manager.getInternalKeyStorageToken();
+ } else {
+ token = manager.getTokenByName(tokenname);
+ }
+ StringBuffer certname = new StringBuffer();
+
+ if (!token.equals(manager.getInternalKeyStorageToken())) {
+ certname.append(tokenname);
+ certname.append(":");
+ }
+ certname.append(nickname);
+ try {
+ return manager.findCertByNickname(certname.toString());
+ } catch (ObjectNotFoundException e) {
+ throw new IOException("Signing Certificate not found");
+ }
+ }
+
+ public static java.security.PrivateKey getPrivateKey(String tokenname, String nickname)
+ throws Exception {
+
+ X509Certificate cert = getCertificate(tokenname, nickname);
+
+ return CryptoManager.getInstance().findPrivKeyByCert(cert);
+ }
+
+
+ /**
+ * getCMCBlob create and return the enrollent request.
+ * <P>
+ * @param signerCert the certificate of the authorized signer of the CMC revocation request.
+ * @param manager the crypto manger.
+ * @param nValue the nickname of the certificate inside the token.
+ * @param rValue request PKCS#10 file name.
+ * @return the CMC revocation request encoded in base64
+ */
+ static String getCMCBlob(X509Certificate signerCert,CryptoManager manager, String nValue, String rValue) {
+
+ String asciiBASE64Blob = rValue; // input pkcs10 blob
+ String tokenname = "internal";
+
+ try {
+
+ java.security.PrivateKey privKey = null;
+ PKCS10 pkcs = null;
+ SignerIdentifier si = null;
+ ContentInfo fullEnrollmentReq = null;
+
+ try {
+ byte[] decodedBytes = com.netscape.osutil.OSUtil.AtoB(asciiBASE64Blob);
+
+ pkcs = new PKCS10(decodedBytes);
+ } catch (IOException e) {
+ throw new IOException("Internal Error - " + e.toString());
+ } catch (SignatureException e) {
+ throw new IOException("Internal Error - " + e.toString());
+ } catch (NoSuchAlgorithmException e) {
+ throw new IOException("Internal Error - " + e.toString());
+ }
+
+ String hasSki = "true";
+
+ BigInteger serialno = signerCert.getSerialNumber();
+ byte[] certB = signerCert.getEncoded();
+ X509CertImpl impl = new X509CertImpl(certB);
+ X500Name issuerName = (X500Name) impl.getIssuerDN();
+ byte[] issuerByte = issuerName.getEncoded();
+ ByteArrayInputStream istream = new ByteArrayInputStream(issuerByte);
+
+ Name issuer = (Name) Name.getTemplate().decode(istream);
+ IssuerAndSerialNumber ias = new IssuerAndSerialNumber(issuer, new INTEGER(serialno.toString()));
+
+ si = new SignerIdentifier(SignerIdentifier.ISSUER_AND_SERIALNUMBER, ias, null);
+ privKey = getPrivateKey(tokenname, nValue);
+
+ // create CMC req
+ // transfer pkcs10 to jss class
+ int bpid = 1;
+ ByteArrayInputStream crInputStream = new ByteArrayInputStream(pkcs.toByteArray());
+ CertificationRequest cr = (CertificationRequest) CertificationRequest.getTemplate().decode(crInputStream);
+
+ TaggedCertificationRequest tcr = new
+ TaggedCertificationRequest(new
+ INTEGER(bpid++), cr);
+ TaggedRequest trq = new
+ TaggedRequest(TaggedRequest.PKCS10, tcr,
+ null);
+
+ SEQUENCE reqSequence = new SEQUENCE();
+
+ reqSequence.addElement(trq);
+
+ // Add some control sequence
+ // Verisign has transactionID,senderNonce
+ SEQUENCE controlSeq = new SEQUENCE();
+
+ Date date = new Date();
+ String salt = "lala123" + date.toString();
+ byte[] dig;
+
+ try {
+ MessageDigest SHA1Digest = MessageDigest.getInstance("SHA1");
+
+ dig = SHA1Digest.digest(salt.getBytes());
+ } catch (NoSuchAlgorithmException ex) {
+ dig = salt.getBytes();
+ }
+
+ String sn = com.netscape.osutil.OSUtil.BtoA(dig);
+
+ TaggedAttribute senderNonce = new TaggedAttribute(new
+ INTEGER(bpid++),
+ OBJECT_IDENTIFIER.id_cmc_senderNonce,
+ new OCTET_STRING(sn.getBytes()));
+
+ controlSeq.addElement(senderNonce);
+
+ // Verisign recommend transactionId be MD5 hash of publicKey
+ byte[] transId;
+
+ try {
+ MessageDigest MD5Digest = MessageDigest.getInstance("MD5");
+
+ transId = MD5Digest.digest(pkcs.getSubjectPublicKeyInfo().getKey());
+ } catch (Exception ex) {
+ transId = salt.getBytes();
+ }
+
+ TaggedAttribute transactionId = new TaggedAttribute(new
+ INTEGER(bpid++),
+ OBJECT_IDENTIFIER.id_cmc_transactionId,
+ new INTEGER(1, transId));
+
+ controlSeq.addElement(transactionId);
+
+ PKIData pkidata = new PKIData(controlSeq, reqSequence, new SEQUENCE(), new SEQUENCE());
+
+ EncapsulatedContentInfo ci = new
+ EncapsulatedContentInfo(OBJECT_IDENTIFIER.id_cct_PKIData,
+ pkidata);
+ // SHA1 is the default digest Alg for now.
+ DigestAlgorithm digestAlg = null;
+ SignatureAlgorithm signAlg = SignatureAlgorithm.RSASignatureWithSHA1Digest;
+ org.mozilla.jss.crypto.PrivateKey.Type signingKeyType = ((org.mozilla.jss.crypto.PrivateKey) privKey).getType();
+
+ if (signingKeyType.equals(org.mozilla.jss.crypto.PrivateKey.Type.DSA))
+ signAlg = SignatureAlgorithm.DSASignatureWithSHA1Digest;
+ MessageDigest SHADigest = null;
+ byte[] digest = null;
+
+ try {
+ SHADigest = MessageDigest.getInstance("SHA1");
+ digestAlg = DigestAlgorithm.SHA1;
+
+ ByteArrayOutputStream ostream = new ByteArrayOutputStream();
+
+ pkidata.encode((OutputStream) ostream);
+ digest = SHADigest.digest(ostream.toByteArray());
+ } catch (NoSuchAlgorithmException e) {
+ }
+ SignerInfo signInfo = new
+ SignerInfo(si, null, null, OBJECT_IDENTIFIER.id_cct_PKIData, digest, signAlg,
+ (org.mozilla.jss.crypto.PrivateKey) privKey);
+ SET signInfos = new SET();
+
+ signInfos.addElement(signInfo);
+
+ SET digestAlgs = new SET();
+
+ if (digestAlg != null) {
+ AlgorithmIdentifier ai = new AlgorithmIdentifier(digestAlg.toOID(), null);
+
+ digestAlgs.addElement(ai);
+ }
+
+ org.mozilla.jss.crypto.X509Certificate[] agentChain = manager.buildCertificateChain(signerCert);
+ SET certs = new SET();
+
+ for (int i = 0; i < agentChain.length; i++) {
+ ANY cert = new ANY(agentChain[i].getEncoded());
+
+ certs.addElement(cert);
+ }
+ SignedData req = new SignedData(digestAlgs, ci, certs, null, signInfos);
+
+ fullEnrollmentReq = new
+ ContentInfo(req);
+
+ ByteArrayOutputStream bs = new ByteArrayOutputStream();
+ PrintStream ps = new PrintStream(bs);
+
+ if (fullEnrollmentReq != null) {
+ // format is PR_REQUEST_CMC
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+
+ fullEnrollmentReq.encode(os);
+ ps.print(com.netscape.osutil.OSUtil.BtoA(os.toByteArray()));
+ //fullEnrollmentReq.print(ps); // no header/trailer
+ } else {
+ // format is PR_REQUEST_PKCS10
+ pkcs.print(ps);
+ }
+ asciiBASE64Blob = bs.toString();
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.exit(1);
+ }
+ return asciiBASE64Blob;
+ }
+
+ /** Creates a new instance of CMCEnroll */
+ public static void main(String[]s) {
+
+ String dValue = null, nValue = null, rValue = null, pValue = null;
+ FileOutputStream outputBlob = null;
+
+ // default path is "."
+ String mPath = ".";
+ // default prefix is ""
+ String mPrefix = "";
+
+ boolean bWrongParam = false;
+
+ // (1) Check that two arguments were submitted to the program
+ if (s.length != (ARGC * 2)) {
+ System.out.println("Wrong number of parameters:" + s.length);
+ System.out.println("Usage: CMCEnroll " +
+ "-d <dir to cert8.db, key3.db> " +
+ "-n <nickname> " +
+ "-r <request PKCS#10 file name> " +
+ "-p <password>"
+ );
+ bWrongParam = true;
+ }else {
+ int length;
+ int i;
+
+ length = s.length;
+ for (i = 0; i < length; i++) {
+ if (s[i].equals("-d")) {
+ dValue = s[i + 1];
+ } else if (s[i].equals("-n")) {
+ nValue = s[i + 1];
+ } else if (s[i].equals("-r")) {
+ rValue = s[i + 1];
+ } else if (s[i].equals("-p")) {
+ pValue = s[i + 1];
+ }
+ if (s[i].equals(""))
+ bWrongParam = true;
+
+ }
+
+ if (dValue == null || nValue == null || rValue == null || pValue == null )
+ bWrongParam = true;
+ else if (dValue.length() == 0 || nValue.length() == 0 || rValue.length() == 0 ||
+ pValue.length() == 0 )
+ bWrongParam = true;
+ if (bWrongParam == true) {
+ System.out.println("Usage: CMCEnroll " +
+ "-d <dir to cert8.db, key3.db> " +
+ "-n <nickname> " +
+ "-r <request PKCS#10 file name> " +
+ "-p <password>"
+ );
+ System.exit(0);
+ }
+
+ try {
+ // initialize CryptoManager
+ mPath = dValue;
+ System.out.println("cert/key prefix = " + mPrefix);
+ System.out.println("path = " + mPath);
+ CryptoManager.InitializationValues vals =
+ new CryptoManager.InitializationValues(mPath, mPrefix,
+ mPrefix, "secmod.db");
+
+ CryptoManager.initialize(vals);
+
+ CryptoManager cm = CryptoManager.getInstance();
+ CryptoToken token = cm.getInternalKeyStorageToken();
+ Password pass = new Password(pValue.toCharArray());
+
+ token.login(pass);
+ CryptoStore store = token.getCryptoStore();
+ X509Certificate[] list = store.getCertificates();
+ X509Certificate signerCert = null;
+
+ signerCert = cm.findCertByNickname(nValue);
+
+ BufferedReader inputBlob = null;
+
+ try {
+ inputBlob = new BufferedReader(new InputStreamReader(
+ new BufferedInputStream(
+ new FileInputStream(
+ rValue))));
+ } catch (FileNotFoundException e) {
+ System.out.println("CMCEnroll: can''t find file " +
+ rValue + ":\n" + e);
+ return;
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.exit(1);
+ }
+ // (3) Read the entire contents of the specified BASE 64 encoded
+ // blob into a String() object throwing away any
+ // headers beginning with HEADER and any trailers beginning
+ // with TRAILER
+ String asciiBASE64BlobChunk = new String();
+ String asciiBASE64Blob = new String();
+
+ try {
+ while ((asciiBASE64BlobChunk = inputBlob.readLine()) != null) {
+ if (!(asciiBASE64BlobChunk.startsWith(HEADER)) &&
+ !(asciiBASE64BlobChunk.startsWith(TRAILER))) {
+ asciiBASE64Blob += asciiBASE64BlobChunk.trim();
+ }
+ }
+ } catch (IOException e) {
+ System.out.println("CMCEnroll: Unexpected BASE64 " +
+ "encoded error encountered in readLine():\n" +
+ e);
+ }
+ // (4) Close the DataInputStream() object
+ try {
+ inputBlob.close();
+ } catch (IOException e) {
+ System.out.println("CMCEnroll(): Unexpected BASE64 " +
+ "encoded error encountered in close():\n" + e);
+ }
+
+ asciiBASE64Blob = getCMCBlob(signerCert,cm, nValue, asciiBASE64Blob );
+ // (5) Decode the ASCII BASE 64 blob enclosed in the
+ // String() object into a BINARY BASE 64 byte[] object
+ byte binaryBASE64Blob[] = null;
+
+ binaryBASE64Blob = com.netscape.osutil.OSUtil.AtoB(asciiBASE64Blob);
+
+ // (6) Finally, print the actual CMCEnroll blob to the
+ // specified output file
+ try {
+ outputBlob = new FileOutputStream(rValue + ".out");
+ } catch (IOException e) {
+ System.out.println("CMCEnroll: unable to open file " +
+ rValue + ".out" + " for writing:\n" + e);
+ return;
+ }
+
+ System.out.println(HEADER);
+ System.out.println(asciiBASE64Blob + TRAILER);
+ try {
+ asciiBASE64Blob = HEADER + "\n" + asciiBASE64Blob + TRAILER;
+ outputBlob.write(asciiBASE64Blob.getBytes());
+ } catch (IOException e) {
+ System.out.println("CMCEnroll: I/O error " +
+ "encountered during write():\n" +
+ e);
+ }
+
+ try {
+ outputBlob.close();
+ } catch (IOException e) {
+ System.out.println("CMCEnroll: Unexpected error " +
+ "encountered while attempting to close() " +
+ "\n" + e);
+ }
+
+ }catch (Exception e) {
+ e.printStackTrace();
+ System.exit(1);
+ }
+
+ return;
+ }
+ }
+}
diff --git a/pki/base/java-tools/src/com/netscape/cmstools/CMCRequest.java b/pki/base/java-tools/src/com/netscape/cmstools/CMCRequest.java
new file mode 100644
index 000000000..9c5b74c05
--- /dev/null
+++ b/pki/base/java-tools/src/com/netscape/cmstools/CMCRequest.java
@@ -0,0 +1,1100 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmstools;
+
+
+import org.mozilla.jss.pkix.cmc.*;
+import org.mozilla.jss.pkix.cms.*;
+import org.mozilla.jss.pkix.cert.*;
+import org.mozilla.jss.pkix.primitive.*;
+import org.mozilla.jss.asn1.*;
+import org.mozilla.jss.pkcs10.*;
+import org.mozilla.jss.pkcs11.*;
+import org.mozilla.jss.crypto.*;
+import org.mozilla.jss.pkix.crmf.*;
+import org.mozilla.jss.pkix.cmmf.*;
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.crypto.CryptoToken;
+import org.mozilla.jss.crypto.SignatureAlgorithm;
+import org.mozilla.jss.crypto.DigestAlgorithm;
+import org.mozilla.jss.crypto.X509Certificate;
+import org.mozilla.jss.util.*;
+
+import org.mozilla.jss.*;
+
+import netscape.security.util.*;
+import netscape.security.x509.*;
+import netscape.security.pkcs.PKCS10;
+
+import java.security.*;
+import java.security.cert.CertificateException;
+import java.math.*;
+import java.security.Principal;
+import java.lang.*;
+import java.lang.reflect.*;
+import java.io.*;
+import java.util.*;
+
+import com.netscape.cmsutil.util.*;
+
+
+/**
+ * Tool for creating CMC full request
+ *
+ * <P>
+ * @version $Revision$, $Date$
+ *
+ */
+public class CMCRequest {
+
+ public static final String PR_REQUEST_CMC = "CMC";
+ public static final String PR_REQUEST_CRMF = "CRMF";
+
+ public static final int ARGC = 1;
+ private static final String CERTDB = "cert8.db";
+ private static final String KEYDB = "key3.db";
+ public static final String HEADER = "-----BEGIN NEW CERTIFICATE REQUEST-----";
+ public static final String TRAILER = "-----END NEW CERTIFICATE REQUEST-----";
+
+ void cleanArgs(String[] s) {
+
+ }
+
+ public static X509Certificate getCertificate(String tokenname,
+ String nickname) throws Exception {
+ CryptoManager manager = CryptoManager.getInstance();
+ CryptoToken token = null;
+
+ if (tokenname.equals("internal")) {
+ token = manager.getInternalKeyStorageToken();
+ } else {
+ token = manager.getTokenByName(tokenname);
+ }
+ StringBuffer certname = new StringBuffer();
+
+ if (!token.equals(manager.getInternalKeyStorageToken())) {
+ certname.append(tokenname);
+ certname.append(":");
+ }
+ certname.append(nickname);
+ try {
+ return manager.findCertByNickname(certname.toString());
+ } catch (ObjectNotFoundException e) {
+ throw new IOException("Signing Certificate not found");
+ }
+ }
+
+ public static java.security.PrivateKey getPrivateKey(String tokenname, String nickname)
+ throws Exception {
+
+ X509Certificate cert = getCertificate(tokenname, nickname);
+
+ return CryptoManager.getInstance().findPrivKeyByCert(cert);
+ }
+
+
+ /**
+ * getCMCBlob create and return the enrollent request.
+ * <P>
+ * @param signerCert the certificate of the authorized signer of the CMC revocation request.
+ * @param nickname the nickname of the certificate inside the token.
+ * @param rValue CRMF/PKCS10 request.
+ * @param format either crmf or pkcs10
+ * @return the CMC enrollment request encoded in base64
+ */
+ static ContentInfo getCMCBlob(X509Certificate signerCert, String nickname,
+ String[] rValue, String format, CryptoManager manager, String transactionMgtEnable,
+ String transactionMgtId, String identityProofEnable, String identityProofSharedSecret,
+ SEQUENCE controlSeq, SEQUENCE otherMsgSeq, int bpid) {
+
+ String tokenname = "internal";
+
+ ContentInfo fullEnrollmentReq = null;
+ try {
+ java.security.PrivateKey privKey = null;
+ SignerIdentifier si = null;
+
+ BigInteger serialno = signerCert.getSerialNumber();
+ byte[] certB = signerCert.getEncoded();
+ X509CertImpl impl = new X509CertImpl(certB);
+ X500Name issuerName = (X500Name) impl.getIssuerDN();
+ byte[] issuerByte = issuerName.getEncoded();
+ ByteArrayInputStream istream = new ByteArrayInputStream(issuerByte);
+
+ Name issuer = (Name) Name.getTemplate().decode(istream);
+ IssuerAndSerialNumber ias = new IssuerAndSerialNumber(
+ issuer, new INTEGER(serialno.toString()));
+
+ si = new SignerIdentifier(
+ SignerIdentifier.ISSUER_AND_SERIALNUMBER, ias, null);
+ privKey = getPrivateKey(tokenname, nickname);
+
+ TaggedRequest trq = null;
+ PKCS10 pkcs = null;
+ CertReqMsg certReqMsg = null;
+
+ // create CMC req
+ SEQUENCE reqSequence = new SEQUENCE();
+ try {
+ for (int k=0; k<rValue.length; k++) {
+ String asciiBASE64Blob = rValue[k];
+ byte[] decodedBytes = com.netscape.osutil.OSUtil.AtoB(asciiBASE64Blob);
+
+ if (format.equals("crmf")) {
+ ByteArrayInputStream reqBlob =
+ new ByteArrayInputStream(decodedBytes);
+ SEQUENCE crmfMsgs = null;
+ try {
+ crmfMsgs = (SEQUENCE)new SEQUENCE.OF_Template(new
+ CertReqMsg.Template()).decode(reqBlob);
+ } catch (InvalidBERException ee) {
+ System.out.println("This is not a crmf request. Or this request has an error.");
+ System.exit(1);
+ }
+ int nummsgs = crmfMsgs.size();
+ certReqMsg = (CertReqMsg)crmfMsgs.elementAt(0);
+ trq = new TaggedRequest(TaggedRequest.CRMF, null,
+ certReqMsg);
+ } else if (format.equals("pkcs10")) {
+ try {
+ pkcs = new PKCS10(decodedBytes);
+ } catch (IllegalArgumentException e) {
+ System.out.println("This is not a PKCS10 request.");
+ System.exit(1);
+ }
+ ByteArrayInputStream crInputStream = new ByteArrayInputStream(
+ pkcs.toByteArray());
+ CertificationRequest cr = (CertificationRequest)
+ CertificationRequest.getTemplate().decode(crInputStream);
+ TaggedCertificationRequest tcr = new TaggedCertificationRequest(
+ new INTEGER(bpid++), cr);
+ trq = new
+ TaggedRequest(TaggedRequest.PKCS10, tcr, null);
+ } else {
+ System.out.println("Unrecognized request format: "+format);
+ System.exit(1);
+ }
+ reqSequence.addElement(trq);
+ }
+ } catch (IOException e) {
+ throw new IOException("Internal Error - " + e.toString());
+ } catch (SignatureException e) {
+ throw new IOException("Internal Error - " + e.toString());
+ } catch (NoSuchAlgorithmException e) {
+ throw new IOException("Internal Error - " + e.toString());
+ }
+
+ if (transactionMgtEnable.equals("true"))
+ bpid = addTransactionAttr(bpid, controlSeq, transactionMgtId, format,
+ pkcs, certReqMsg);
+
+ if (identityProofEnable.equals("true"))
+ bpid = addIdentityProofAttr(bpid, controlSeq, reqSequence,
+ identityProofSharedSecret);
+
+ PKIData pkidata = new PKIData(controlSeq, reqSequence, new SEQUENCE(), otherMsgSeq);
+
+ EncapsulatedContentInfo ci = new
+ EncapsulatedContentInfo(OBJECT_IDENTIFIER.id_cct_PKIData, pkidata);
+ // SHA1 is the default digest Alg for now.
+ DigestAlgorithm digestAlg = null;
+ SignatureAlgorithm signAlg = SignatureAlgorithm.RSASignatureWithSHA1Digest;
+ org.mozilla.jss.crypto.PrivateKey.Type signingKeyType = ((org.mozilla.jss.crypto.PrivateKey) privKey).getType();
+
+ if (signingKeyType.equals(org.mozilla.jss.crypto.PrivateKey.Type.DSA))
+ signAlg = SignatureAlgorithm.DSASignatureWithSHA1Digest;
+ MessageDigest SHADigest = null;
+
+ byte[] digest = null;
+ try {
+ SHADigest = MessageDigest.getInstance("SHA1");
+ digestAlg = DigestAlgorithm.SHA1;
+
+ ByteArrayOutputStream ostream = new ByteArrayOutputStream();
+
+ pkidata.encode((OutputStream) ostream);
+ digest = SHADigest.digest(ostream.toByteArray());
+ } catch (NoSuchAlgorithmException e) {
+ }
+ SignerInfo signInfo = new
+ SignerInfo(si, null, null, OBJECT_IDENTIFIER.id_cct_PKIData, digest, signAlg,
+ (org.mozilla.jss.crypto.PrivateKey) privKey);
+ SET signInfos = new SET();
+ signInfos.addElement(signInfo);
+
+ SET digestAlgs = new SET();
+
+ if (digestAlg != null) {
+ AlgorithmIdentifier ai = new AlgorithmIdentifier(digestAlg.toOID(), null);
+ digestAlgs.addElement(ai);
+ }
+
+ org.mozilla.jss.crypto.X509Certificate[] agentChain = manager.buildCertificateChain(signerCert);
+ SET certs = new SET();
+
+ for (int i = 0; i < agentChain.length; i++) {
+ ANY cert = new ANY(agentChain[i].getEncoded());
+ certs.addElement(cert);
+ }
+ SignedData req = new SignedData(digestAlgs, ci, certs, null, signInfos);
+ fullEnrollmentReq = new ContentInfo(req);
+ ByteArrayOutputStream bs = new ByteArrayOutputStream();
+ PrintStream ps = new PrintStream(bs);
+
+ if (fullEnrollmentReq != null) {
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+
+ fullEnrollmentReq.encode(os);
+ ps.print(com.netscape.osutil.OSUtil.BtoA(os.toByteArray()));
+ }
+ String asciiBASE64Blob = bs.toString();
+
+ System.out.println("");
+ System.out.println("The CMC enrollment request in base-64 encoded format:");
+ System.out.println("");
+ System.out.println(asciiBASE64Blob);
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.exit(1);
+ }
+ return fullEnrollmentReq;
+ }
+
+ static void printUsage() {
+ System.out.println("");
+ System.out.println("Usage: CMCRequest <configuration file>");
+ System.out.println("For example, CMCRequest CMCRequest.cfg");
+ System.out.println("");
+ System.out.println("The configuration file should look like as follows:");
+ System.out.println("");
+ System.out.println("#numRequests: Total number of PKCS10 requests or CRMF requests.");
+ System.out.println("numRequests=1");
+ System.out.println("");
+ System.out.println("#input: full path for the PKCS10 request or CRMF request,");
+ System.out.println("#the content must be in Base-64 encoded format");
+ System.out.println("#Multiple files are supported. They must be separated by space.");
+ System.out.println("input=crmf1");
+ System.out.println("");
+ System.out.println("#output: full path for the CMC request in binary format");
+ System.out.println("output=/u/doc/cmcReq");
+ System.out.println("");
+ System.out.println("#nickname: nickname for agent certificate which will be used");
+ System.out.println("#to sign the CMC full request.");
+ System.out.println("nickname=CMS Agent Certificate");
+ System.out.println("");
+ System.out.println("#dbdir: directory for cert8.db, key3.db and secmod.db");
+ System.out.println("dbdir=/u/smith/.netscape");
+ System.out.println("");
+ System.out.println("#password: password for cert8.db which stores the agent");
+ System.out.println("#certificate");
+ System.out.println("password=pass");
+ System.out.println("");
+ System.out.println("#format: request format, either pkcs10 or crmf");
+ System.out.println("format=crmf");
+ System.out.println("");
+ System.out.println("#confirmCertAcceptance.enable: if true, then the request will");
+ System.out.println("#contain this control. Otherwise, false.");
+ System.out.println("confirmCertAcceptance.enable=true");
+ System.out.println("");
+ System.out.println("#confirmCertAcceptance.serial: The serial number for");
+ System.out.println("#confirmCertAcceptance control");
+ System.out.println("confirmCertAcceptance.serial=3");
+ System.out.println("");
+ System.out.println("#confirmCertAcceptance.issuer: The issuer name for");
+ System.out.println("#confirmCertAcceptance control");
+ System.out.println("confirmCertAcceptance.issuer=cn=Certificate Manager,c=us");
+ System.out.println("");
+ System.out.println("#getCert.enable: if true, then the request will contain this");
+ System.out.println("#control. Otherwise, false.");
+ System.out.println("getCert.enable=true");
+ System.out.println("");
+ System.out.println("#getCert.serial: The serial number for getCert control");
+ System.out.println("getCert.serial=3");
+ System.out.println("");
+ System.out.println("#getCert.issuer: The issuer name for getCert control");
+ System.out.println("getCert.issuer=cn=Certificate Manager,c=us");
+ System.out.println("");
+ System.out.println("#dataReturn.enable: if true, then the request will contain");
+ System.out.println("#this control. Otherwise, false.");
+ System.out.println("dataReturn.enable=true");
+ System.out.println("");
+ System.out.println("#dataReturn.data: data contained in the control.");
+ System.out.println("dataReturn.data=test");
+ System.out.println("");
+ System.out.println("#transactionMgt.enable: if true, then the request will contain");
+ System.out.println("#this control. Otherwise, false.");
+ System.out.println("transactionMgt.enable=true");
+ System.out.println("");
+ System.out.println("#transactionMgt.id: transaction identifier. Verisign recommend");
+ System.out.println("#transactionId to be MD5 hash of publicKey.");
+ System.out.println("transactionMgt.id=");
+ System.out.println("");
+ System.out.println("#senderNonce.enable: if true, then the request will contain this");
+ System.out.println("#control. Otherwise, false.");
+ System.out.println("senderNonce.enable=true");
+ System.out.println("");
+ System.out.println("#senderNonce.id: sender nonce");
+ System.out.println("senderNonce.id=");
+ System.out.println("");
+ System.out.println("#revRequest.enable: if true, then the request will contain this");
+ System.out.println("#control. Otherwise, false.");
+ System.out.println("revRequest.enable=true");
+ System.out.println("");
+ System.out.println("#revRequest.nickname: The nickname for the revoke certificate");
+ System.out.println("revRequest.nickname=newuser's 102504a ID");
+ System.out.println("");
+ System.out.println("#revRequest.issuer: The issuer name for the certificate being");
+ System.out.println("#revoked.");
+ System.out.println("revRequest.issuer=cn=Certificate Manager,c=us");
+ System.out.println("");
+ System.out.println("#revRequest.serial: The serial number for the certificate being");
+ System.out.println("#revoked.");
+ System.out.println("revRequest.serial=61");
+ System.out.println("");
+ System.out.println("#revRequest.reason: The reason for revoking this certificate: ");
+ System.out.println("# unspecified, keyCompromise, caCompromise,");
+ System.out.println("# affiliationChanged, superseded, cessationOfOperation,");
+ System.out.println("# certificateHold, removeFromCRL");
+ System.out.println("revRequest.reason=unspecified");
+ System.out.println("");
+ System.out.println("#revRequest.sharedSecret: The sharedSecret");
+ System.out.println("revRequest.sharedSecret=");
+ System.out.println("");
+ System.out.println("#revRequest.comment: The human readable comment");
+ System.out.println("revRequest.comment=");
+ System.out.println("");
+ System.out.println("#revRequest.invalidityDatePresent: if true, the current time will be the");
+ System.out.println("# invalidityDate. If false, no invalidityDate");
+ System.out.println("# is present.");
+ System.out.println("revRequest.invalidityDatePresent=false");
+ System.out.println("");
+ System.out.println("#identityProof.enable: if true, then the request will contain");
+ System.out.println("#this control. Otherwise, false.");
+ System.out.println("identityProof.enable=true");
+ System.out.println("");
+ System.out.println("#identityProof.sharedSecret: Shared Secret");
+ System.out.println("identityProof.sharedSecret=testing");
+ System.out.println("");
+ System.out.println("#popLinkWitness.enable: if true, then the request will contain");
+ System.out.println("#this control. Otherwise, false.");
+ System.out.println("#If you want to test this control, make sure to use CRMFPopClient ");
+ System.out.println("# to generate the CRMF request which will include the ");
+ System.out.println("#idPOPLinkWitness attribute in the controls section of the ");
+ System.out.println("#CertRequest structure.");
+ System.out.println("popLinkWitness.enable=false");
+ System.out.println("");
+ System.out.println("#LraPopWitness.enable: if true, then the request will contain this");
+ System.out.println("#control. Otherwise, false.");
+ System.out.println("LraPopWitness.enable=true");
+ System.out.println("");
+ System.out.println("#LraPopWitness.bodyPartIDs: List of body part IDs");
+ System.out.println("#Each id is separated by space.");
+ System.out.println("LraPopWitness.bodyPartIDs=1");
+ System.exit(1);
+ }
+
+ private static int addLraPopWitnessAttr(int bpid, SEQUENCE seq, String bodyPartIDs) {
+ StringTokenizer tokenizer = new StringTokenizer(bodyPartIDs, " ");
+ SEQUENCE bodyList = new SEQUENCE();
+ while (tokenizer.hasMoreTokens()) {
+ String s = (String)tokenizer.nextToken();
+ bodyList.addElement(new INTEGER(s));
+ }
+ LraPopWitness lra = new LraPopWitness(new INTEGER(0), bodyList);
+ TaggedAttribute cont = new TaggedAttribute(new
+ INTEGER(bpid++), OBJECT_IDENTIFIER.id_cmc_lraPOPWitness, lra);
+ System.out.println("Successfully create LRA POP witness control. bpid = "+(bpid-1));
+ System.out.println("");
+ seq.addElement(cont);
+ return bpid;
+ }
+
+ private static int addConfirmCertAttr(int bpid, SEQUENCE seq, String confirmCertIssuer,
+ String confirmCertSerial) {
+ try {
+ INTEGER serial = new INTEGER(confirmCertSerial);
+ X500Name issuername = new X500Name(confirmCertIssuer);
+ byte[] issuerbyte = issuername.getEncoded();
+ ANY issuern = new ANY(issuerbyte);
+ CMCCertId cmcCertId = new CMCCertId(issuern, serial, null);
+ TaggedAttribute cmcCertIdControl = new TaggedAttribute(new
+ INTEGER(bpid++),
+ OBJECT_IDENTIFIER.id_cmc_idConfirmCertAcceptance, cmcCertId);
+ System.out.println("Successfully create confirm certificate acceptance control. bpid = "+(bpid-1));
+ System.out.println("");
+ seq.addElement(cmcCertIdControl);
+ } catch (Exception e) {
+ System.out.println("Error in creating confirm certificate acceptance control. Check the parameters.");
+ System.exit(1);
+ }
+ return bpid;
+ }
+
+ private static ENUMERATED toCRLReason(String str) {
+ if (str.equalsIgnoreCase("unspecified")) {
+ return RevRequest.unspecified;
+ } else if (str.equalsIgnoreCase("keyCompromise")) {
+ return RevRequest.keyCompromise;
+ } else if (str.equalsIgnoreCase("caCompromise")) {
+ return RevRequest.cACompromise;
+ } else if (str.equalsIgnoreCase("affiliationChanged")) {
+ return RevRequest.affiliationChanged;
+ } else if (str.equalsIgnoreCase("superseded")) {
+ return RevRequest.superseded;
+ } else if (str.equalsIgnoreCase("cessationOfOperation")) {
+ return RevRequest.cessationOfOperation;
+ } else if (str.equalsIgnoreCase("certificateHold")) {
+ return RevRequest.certificateHold;
+ } else if (str.equalsIgnoreCase("removeFromCRL")) {
+ return RevRequest.removeFromCRL;
+ }
+
+ System.out.println("Unrecognized CRL reason");
+ System.exit(1);
+
+ return RevRequest.unspecified;
+ }
+
+ private static int addIdentityProofAttr(int bpid, SEQUENCE seq, SEQUENCE reqSequence,
+ String sharedSecret) {
+ byte[] b = ASN1Util.encode(reqSequence);
+ byte[] key = null;
+ byte[] finalDigest = null;
+ try {
+ MessageDigest SHA1Digest = MessageDigest.getInstance("SHA1");
+ key = SHA1Digest.digest(sharedSecret.getBytes());
+ } catch (NoSuchAlgorithmException ex) {
+ System.out.println( "CMCRequest::addIdentityProofAttr() - "
+ + "No such algorithm!" );
+ return -1;
+ }
+
+ try {
+ MessageDigest SHA1Digest = MessageDigest.getInstance("SHA1");
+ HMACDigest hmacDigest = new HMACDigest(SHA1Digest, key);
+ hmacDigest.update(b);
+ finalDigest = hmacDigest.digest();
+ } catch (NoSuchAlgorithmException ex) {
+ }
+
+ TaggedAttribute identityProof = new TaggedAttribute(new
+ INTEGER(bpid++), OBJECT_IDENTIFIER.id_cmc_identityProof,
+ new OCTET_STRING(finalDigest));
+ seq.addElement(identityProof);
+ System.out.println("Identity Proof control: ");
+ System.out.print(" Value: ");
+ for (int i=0; i<finalDigest.length; i++) {
+ System.out.print(finalDigest[i]+" ");
+ }
+ System.out.println("");
+ System.out.println("Successfully create identityProof control. bpid = "+(bpid-1));
+ System.out.println("");
+ return bpid;
+ }
+
+ private static int addRevRequestAttr(int bpid, SEQUENCE seq, SEQUENCE otherMsgSeq, String nickname,
+ String revRequestIssuer, String revRequestSerial, String revRequestReason,
+ String revRequestSharedSecret, String revRequestComment, String invalidityDatePresent,
+ CryptoManager manager) {
+ try {
+ if (nickname.length() <= 0) {
+ System.out.println("The nickname for the certificate being revoked is null");
+ System.exit(1);
+ }
+ String nickname1 = nickname;
+ UTF8String comment = null;
+ OCTET_STRING sharedSecret = null;
+ GeneralizedTime d = null;
+ X500Name subjectname = new X500Name(revRequestIssuer);
+ INTEGER snumber = new INTEGER(revRequestSerial);
+ ENUMERATED reason = toCRLReason(revRequestReason);
+ if (revRequestSharedSecret.length() > 0)
+ sharedSecret = new OCTET_STRING(revRequestSharedSecret.getBytes());
+ if (revRequestComment.length() > 0)
+ comment = new UTF8String(revRequestComment);
+ if (invalidityDatePresent.equals("true"))
+ d = new GeneralizedTime(new Date());
+ RevRequest revRequest =
+ new RevRequest(new ANY(subjectname.getEncoded()), snumber,
+ reason, d, sharedSecret, comment);
+ int revokeBpid = bpid;
+ TaggedAttribute revRequestControl = new TaggedAttribute(
+ new INTEGER(bpid++),
+ OBJECT_IDENTIFIER.id_cmc_revokeRequest, revRequest);
+ seq.addElement(revRequestControl);
+
+ if (sharedSecret != null) {
+ System.out.println("Successfully create revRequest control. bpid = "+(bpid-1));
+ System.out.println("");
+ return bpid;
+ }
+
+ EncapsulatedContentInfo revokeContent = new EncapsulatedContentInfo(
+ OBJECT_IDENTIFIER.id_cct_PKIData, revRequestControl);
+ DigestAlgorithm digestAlg1 = null;
+ SignatureAlgorithm signAlg1 = SignatureAlgorithm.RSASignatureWithSHA1Digest;
+ java.security.PrivateKey revokePrivKey = null;
+ X509Certificate revokeCert = null;
+ try {
+ revokeCert = manager.findCertByNickname(nickname1);
+ } catch (ObjectNotFoundException e) {
+ System.out.println("Certificate not found: "+nickname1);
+ System.exit(1);
+ }
+ revokePrivKey = manager.findPrivKeyByCert(revokeCert);
+ org.mozilla.jss.crypto.PrivateKey.Type signingKeyType1 =
+ ((org.mozilla.jss.crypto.PrivateKey) revokePrivKey).getType();
+ if (signingKeyType1.equals(org.mozilla.jss.crypto.PrivateKey.Type.DSA))
+ signAlg1 = SignatureAlgorithm.DSASignatureWithSHA1Digest;
+
+ MessageDigest rSHADigest = null;
+ byte[] rdigest = null;
+ try {
+ rSHADigest = MessageDigest.getInstance("SHA1");
+ digestAlg1 = DigestAlgorithm.SHA1;
+
+ ByteArrayOutputStream ostream = new ByteArrayOutputStream();
+
+ revRequestControl.encode((OutputStream) ostream);
+ rdigest = rSHADigest.digest(ostream.toByteArray());
+ } catch (NoSuchAlgorithmException e) {
+ }
+
+ ByteArrayInputStream bistream =
+ new ByteArrayInputStream(subjectname.getEncoded());
+ Name iname = (Name)Name.getTemplate().decode(bistream);
+ IssuerAndSerialNumber ias1 = new IssuerAndSerialNumber(iname, snumber);
+
+ SignerIdentifier rsi = new SignerIdentifier(
+ SignerIdentifier.ISSUER_AND_SERIALNUMBER, ias1, null);
+
+ SignerInfo signInfo1 = new SignerInfo(rsi, null, null,
+ OBJECT_IDENTIFIER.id_cct_PKIData, rdigest, signAlg1,
+ (org.mozilla.jss.crypto.PrivateKey) revokePrivKey);
+
+ SET signInfos1 = new SET();
+ signInfos1.addElement(signInfo1);
+ SET digestAlgs1 = new SET();
+ if (digestAlg1 != null) {
+ AlgorithmIdentifier ai1 = new AlgorithmIdentifier(digestAlg1.toOID(), null);
+ digestAlgs1.addElement(ai1);
+ }
+
+ org.mozilla.jss.crypto.X509Certificate[] revokeCertChain =
+ manager.buildCertificateChain(revokeCert);
+ SET certs1 = new SET();
+ for (int i=0; i<revokeCertChain.length; i++) {
+ ANY cert1 = new ANY(revokeCertChain[i].getEncoded());
+ certs1.addElement(cert1);
+ }
+
+ SignedData sData = new SignedData(digestAlgs1, revokeContent, certs1, null, signInfos1);
+ OBJECT_IDENTIFIER signedDataOID = new OBJECT_IDENTIFIER("1.2.840.113549.1.7.2");
+ ByteArrayOutputStream bos1 = new ByteArrayOutputStream();
+ sData.encode(bos1);
+ OtherMsg otherMsg = new OtherMsg(new INTEGER(revokeBpid), signedDataOID, new ANY(bos1.toByteArray()));
+ otherMsgSeq.addElement(otherMsg);
+ System.out.println("Successfully create revRequest control. bpid = "+(bpid-1));
+ System.out.println("");
+ } catch (Exception e) {
+ System.out.println("Error in creating revRequest control. Check the parameters.");
+ System.exit(1);
+ }
+
+ return bpid;
+ }
+
+ private static int addGetCertAttr(int bpid, SEQUENCE seq, String issuer, String serial) {
+ try {
+ INTEGER serialno = new INTEGER(serial);
+ X500Name issuername = new X500Name(issuer);
+ byte[] issuerbyte = issuername.getEncoded();
+ ANY issuern = new ANY(issuerbyte);
+ GetCert getCert = new GetCert(issuern, serialno);
+ TaggedAttribute getCertControl = new TaggedAttribute(new
+ INTEGER(bpid++),
+ OBJECT_IDENTIFIER.id_cmc_getCert, getCert);
+ System.out.println("Successfully create get certificate control. bpid = "+(bpid-1));
+ System.out.println("");
+ seq.addElement(getCertControl);
+ } catch (Exception e) {
+ System.out.println("Error in creating get certificate control. Check the parameters.");
+ System.exit(1);
+ }
+
+ return bpid;
+ }
+
+ private static int addDataReturnAttr(int bpid, SEQUENCE seq, String str) {
+ try {
+ byte bvalue[] = str.getBytes();
+ System.out.println("Data Return Control: ");
+ String ss = " Value: ";
+ for (int m=0; m<bvalue.length; m++) {
+ ss = ss+bvalue[m]+" ";
+ }
+ System.out.println(ss);
+ OCTET_STRING s = new OCTET_STRING(bvalue);
+ TaggedAttribute dataReturnControl = new TaggedAttribute(new
+ INTEGER(bpid++), OBJECT_IDENTIFIER.id_cmc_dataReturn, s);
+ seq.addElement(dataReturnControl);
+ System.out.println("Successfully create data return control. bpid = "+(bpid-1));
+ System.out.println("");
+ } catch (Exception e) {
+ System.out.println("Error in creating data return control. Check the parameters.");
+ System.exit(1);
+ }
+
+ return bpid;
+ }
+
+ private static int addTransactionAttr(int bpid, SEQUENCE seq, String id, String format,
+ PKCS10 pkcs, CertReqMsg certReqMsg) {
+ byte[] transId = null;
+ Date date = new Date();
+ String salt = "lala123" + date.toString();
+ if (id == null || id.equals("")) {
+ try {
+ MessageDigest MD5Digest = MessageDigest.getInstance("MD5");
+ if (format.equals("crmf")) {
+ CertRequest certreq = certReqMsg.getCertReq();
+ CertTemplate certTemplate = certreq.getCertTemplate();
+ SubjectPublicKeyInfo pkinfo = certTemplate.getPublicKey();
+ BIT_STRING bitString = pkinfo.getSubjectPublicKey();
+ byte[] b = bitString.getBits();
+ transId = MD5Digest.digest(b);
+ } else if (format.equals("pkcs10")) {
+ transId = MD5Digest.digest(pkcs.getSubjectPublicKeyInfo().getKey());
+ }
+ } catch (Exception ex) {
+ transId = salt.getBytes();
+ }
+ } else {
+ transId = id.getBytes();
+ }
+
+ if( transId == null ) {
+ System.out.println( "CMCRequest::addTransactionAttr() - "
+ + "transId is null!" );
+ return -1;
+ }
+
+ INTEGER ii = new INTEGER(1, transId);
+ TaggedAttribute transactionId = new TaggedAttribute(new
+ INTEGER(bpid++), OBJECT_IDENTIFIER.id_cmc_transactionId, ii);
+ System.out.println("Transaction ID control: ");
+ System.out.println(" Value: "+ii.toString());
+ System.out.println("Successfully create transaction management control. bpid = "+(bpid-1));
+ System.out.println("");
+
+ seq.addElement(transactionId);
+
+ return bpid;
+ }
+
+ private static int addSenderNonceAttr(int bpid, SEQUENCE seq, String nonce) {
+ byte[] dig;
+ String sn = nonce;
+ if (nonce == null || nonce.equals("")) {
+ // Verisign has transactionID,senderNonce
+ Date date = new Date();
+ String salt = "lala123" + date.toString();
+
+ try {
+ MessageDigest SHA1Digest = MessageDigest.getInstance("SHA1");
+
+ dig = SHA1Digest.digest(salt.getBytes());
+ } catch (NoSuchAlgorithmException ex) {
+ dig = salt.getBytes();
+ }
+
+ sn = com.netscape.osutil.OSUtil.BtoA(dig);
+ }
+ byte bb[] = sn.getBytes();
+ System.out.println("SenderNonce control: ");
+ String ss = " Value: ";
+ for (int m=0; m<bb.length; m++) {
+ ss = ss+bb[m]+" ";
+ }
+ System.out.println(ss);
+ TaggedAttribute senderNonce = new TaggedAttribute(new
+ INTEGER(bpid++), OBJECT_IDENTIFIER.id_cmc_senderNonce,
+ new OCTET_STRING(sn.getBytes()));
+ System.out.println("Successfully create sender nonce control. bpid = "+(bpid-1));
+ System.out.println("");
+ seq.addElement(senderNonce);
+ return bpid;
+ }
+
+ private static int addPopLinkWitnessAttr(int bpid, SEQUENCE controlSeq) {
+byte[] seed =
+{0x10, 0x53, 0x42, 0x24, 0x1a, 0x2a, 0x35, 0x3c,
+ 0x7a, 0x52, 0x54, 0x56, 0x71, 0x65, 0x66, 0x4c,
+ 0x51, 0x34, 0x35, 0x23, 0x3c, 0x42, 0x43, 0x45,
+ 0x61, 0x4f, 0x6e, 0x43, 0x1e, 0x2a, 0x2b, 0x31,
+ 0x32, 0x34, 0x35, 0x36, 0x55, 0x51, 0x48, 0x14,
+ 0x16, 0x29, 0x41, 0x42, 0x43, 0x7b, 0x63, 0x44,
+ 0x6a, 0x12, 0x6b, 0x3c, 0x4c, 0x3f, 0x00, 0x14,
+ 0x51, 0x61, 0x15, 0x22, 0x23, 0x5f, 0x5e, 0x69};
+
+ TaggedAttribute idPOPLinkRandom = new TaggedAttribute(new
+ INTEGER(bpid++), OBJECT_IDENTIFIER.id_cmc_idPOPLinkRandom,
+ new OCTET_STRING(seed));
+ controlSeq.addElement(idPOPLinkRandom);
+ System.out.println("Successfully create PopLinkWitness control. bpid = "+(bpid-1));
+ System.out.println("");
+ return bpid;
+ }
+
+ public static void main(String[]s) {
+ String numRequests=null;
+ String dbdir=null, nickname=null;
+ String ifilename=null, ofilename=null, password=null, format=null;
+ FileOutputStream outputBlob = null;
+ String confirmCertEnable = "false", confirmCertIssuer = null, confirmCertSerial = null;
+ String getCertEnable = "false", getCertIssuer = null, getCertSerial = null;
+ String dataReturnEnable = "false", dataReturnData = null;
+ String transactionMgtEnable = "false", transactionMgtId = null;
+ String senderNonceEnable = "false", senderNonce = null;
+ String revCertNickname = "";
+ String revRequestEnable = "false", revRequestIssuer = null, revRequestSerial= null;
+ String revRequestReason = null, revRequestSharedSecret = null, revRequestComment = null;
+ String revRequestInvalidityDatePresent = "false";
+ String identityProofEnable = "false", identityProofSharedSecret = null;
+ String popLinkWitnessEnable = "false";
+ String bodyPartIDs = null, lraPopWitnessEnable = "false";
+
+ System.out.println("");
+
+ // Check that the correct # of arguments were submitted to the program
+ if( s.length != ( ARGC ) ) {
+ System.out.println("Wrong number of parameters:" + s.length);
+ printUsage();
+ }
+
+ String configFile = s[0];
+ BufferedReader reader = null;
+ try {
+ reader = new BufferedReader(new InputStreamReader(
+ new BufferedInputStream(
+ new FileInputStream(
+ configFile))));
+ } catch (FileNotFoundException e) {
+ System.out.println("CMCRequest: can't find configuration file: "+configFile);
+ printUsage();
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.exit(1);
+ }
+
+ try {
+ String str = "";
+ while ((str = reader.readLine()) != null) {
+ str = str.trim();
+ if (!str.startsWith("#") && str.length() > 0) {
+ int index = str.indexOf("=");
+ String name = "";
+ String val = "";
+ if (index == -1) {
+ System.out.println("Error in configuration file: "+str);
+ System.exit(1);
+ }
+ name = str.substring(0, index);
+ if (index != str.length()-1)
+ val = str.substring(index+1);
+
+ if (name.equals("format")) {
+ format = val;
+ } else if (name.equals("dbdir")) {
+ dbdir = val;
+ } else if (name.equals("nickname")) {
+ nickname = val;
+ } else if (name.equals("password")) {
+ password = val;
+ } else if (name.equals("output")) {
+ ofilename = val;
+ } else if (name.equals("input")) {
+ ifilename = val;
+ } else if (name.equals("confirmCertAcceptance.serial")) {
+ confirmCertSerial = val;
+ } else if (name.equals("confirmCertAcceptance.issuer")) {
+ confirmCertIssuer = val;
+ } else if (name.equals("confirmCertAcceptance.enable")) {
+ confirmCertEnable = val;
+ } else if (name.equals("getCert.enable")) {
+ getCertEnable = val;
+ } else if (name.equals("getCert.issuer")) {
+ getCertIssuer = val;
+ } else if (name.equals("getCert.serial")) {
+ getCertSerial = val;
+ } else if (name.equals("dataReturn.enable")) {
+ dataReturnEnable = val;
+ } else if (name.equals("dataReturn.data")) {
+ dataReturnData = val;
+ } else if (name.equals("transactionMgt.enable")) {
+ transactionMgtEnable = val;
+ } else if (name.equals("transactionMgt.id")) {
+ transactionMgtId = val;
+ } else if (name.equals("senderNonce.enable")) {
+ senderNonceEnable = val;
+ } else if (name.equals("senderNonce")) {
+ senderNonce = val;
+ } else if (name.equals("revRequest.enable")) {
+ revRequestEnable = val;
+ } else if (name.equals("revRequest.issuer")) {
+ revRequestIssuer = val;
+ } else if (name.equals("revRequest.serial")) {
+ revRequestSerial = val;
+ } else if (name.equals("revRequest.reason")) {
+ revRequestReason = val;
+ } else if (name.equals("revRequest.sharedSecret")) {
+ revRequestSharedSecret = val;
+ } else if (name.equals("revRequest.comment")) {
+ revRequestComment = val;
+ } else if (name.equals("revRequest.invalidityDatePresent")) {
+ revRequestInvalidityDatePresent = val;
+ } else if (name.equals("revRequest.nickname")) {
+ revCertNickname = val;
+ } else if (name.equals("identityProof.enable")) {
+ identityProofEnable = val;
+ } else if (name.equals("identityProof.sharedSecret")) {
+ identityProofSharedSecret = val;
+ } else if (name.equals("popLinkWitness.enable")) {
+ popLinkWitnessEnable = val;
+ } else if (name.equals("LraPopWitness.enable")) {
+ lraPopWitnessEnable = val;
+ } else if (name.equals("LraPopWitness.bodyPartIDs")) {
+ bodyPartIDs = val;
+ } else if (name.equals("numRequests")) {
+ numRequests = val;
+ }
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ printUsage();
+ }
+
+ if (ifilename == null) {
+ System.out.println("Missing input filename for PKCS10 or CRMF.");
+ printUsage();
+ }
+
+ int num = 0;
+ if (numRequests == null) {
+ System.out.println("Missing numRequests.");
+ printUsage();
+ } else {
+ try {
+ num = Integer.parseInt(numRequests);
+ } catch (Exception ee) {
+ System.out.println("numRequests must be integer");
+ System.exit(1);
+ }
+ }
+
+ StringTokenizer tokenizer = new StringTokenizer(ifilename, " ");
+ String[] ifiles = new String[num];
+ for (int i=0; i<num; i++) {
+ String ss = (String)tokenizer.nextToken();
+ ifiles[i] = ss;
+ if (ss == null) {
+ System.out.println("Missing input file for the request.");
+ System.exit(1);
+ }
+ }
+
+ if (ofilename == null) {
+ System.out.println("Missing output filename for the CMC request.");
+ printUsage();
+ }
+
+ if (format == null) {
+ System.out.println("Missing format.");
+ printUsage();
+ }
+
+ if (password == null) {
+ System.out.println("Missing password.");
+ printUsage();
+ }
+
+ if (nickname == null) {
+ System.out.println("Missing nickname.");
+ printUsage();
+ }
+
+ try {
+ // initialize CryptoManager
+ if (dbdir == null)
+ dbdir = ".";
+ String mPrefix = "";
+ System.out.println("cert/key prefix = " + mPrefix);
+ System.out.println("path = " + dbdir);
+ CryptoManager.InitializationValues vals =
+ new CryptoManager.InitializationValues(dbdir, mPrefix,
+ mPrefix, "secmod.db");
+
+ CryptoManager.initialize(vals);
+ CryptoManager cm = CryptoManager.getInstance();
+ CryptoToken token = cm.getInternalKeyStorageToken();
+ Password pass = new Password(password.toCharArray());
+
+ token.login(pass);
+ CryptoStore store = token.getCryptoStore();
+ X509Certificate[] list = store.getCertificates();
+ X509Certificate signerCert = null;
+
+ signerCert = cm.findCertByNickname(nickname);
+
+ String[] requests = new String[num];
+ for (int i=0; i<num; i++) {
+ BufferedReader inputBlob = null;
+ try {
+ inputBlob = new BufferedReader(new InputStreamReader(
+ new BufferedInputStream(new FileInputStream(ifiles[i]))));
+ } catch (FileNotFoundException e) {
+ System.out.println("CMCRequest: can't find file " +
+ ifiles[i] + ":\n" + e);
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.exit(1);
+ }
+ // (3) Read the entire contents of the specified BASE 64 encoded
+ // blob into a String() object throwing away any
+ // headers beginning with HEADER and any trailers beginning
+ // with TRAILER
+ String asciiBASE64BlobChunk = new String();
+ String asciiBASE64Blob = new String();
+
+ try {
+ while ((asciiBASE64BlobChunk = inputBlob.readLine()) != null) {
+ if (!(asciiBASE64BlobChunk.startsWith(HEADER)) &&
+ !(asciiBASE64BlobChunk.startsWith(TRAILER))) {
+ asciiBASE64Blob += asciiBASE64BlobChunk.trim();
+ }
+ }
+ requests[i] = asciiBASE64Blob;
+ } catch (IOException e) {
+ System.out.println("CMCRequest: Unexpected BASE64 " +
+ "encoded error encountered in readLine():\n" +
+ e);
+ }
+ // (4) Close the DataInputStream() object
+ try {
+ inputBlob.close();
+ } catch (IOException e) {
+ System.out.println("CMCRequest(): Unexpected BASE64 " +
+ "encoded error encountered in close():\n" + e);
+ }
+ }
+
+ SEQUENCE controlSeq = new SEQUENCE();
+ int bpid = 1;
+ if (confirmCertEnable.equalsIgnoreCase("true")) {
+ if (confirmCertIssuer.length() == 0 || confirmCertSerial.length() == 0) {
+ System.out.println("Illegal parameters for confirm certificate acceptance control");
+ printUsage();
+ System.exit(1);
+ }
+ bpid = addConfirmCertAttr(bpid, controlSeq, confirmCertIssuer, confirmCertSerial);
+ }
+
+ if (lraPopWitnessEnable.equalsIgnoreCase("true")) {
+ if (bodyPartIDs.length() == 0) {
+ System.out.println("Illegal parameters for Lra Pop Witness control");
+ printUsage();
+ System.exit(1);
+ }
+
+ bpid = addLraPopWitnessAttr(bpid, controlSeq, bodyPartIDs);
+ }
+
+ if (getCertEnable.equalsIgnoreCase("true")) {
+ if (getCertIssuer.length() == 0 || getCertSerial.length() == 0) {
+ System.out.println("Illegal parameters for get certificate control");
+ printUsage();
+ System.exit(1);
+ }
+
+ bpid = addGetCertAttr(bpid, controlSeq, getCertIssuer, getCertSerial);
+ }
+
+ if (dataReturnEnable.equalsIgnoreCase("true")) {
+ if (dataReturnData.length() == 0) {
+ System.out.println("Illegal parameters for data return control");
+ printUsage();
+ System.exit(1);
+ }
+
+ bpid = addDataReturnAttr(bpid, controlSeq, dataReturnData);
+ }
+
+ if (senderNonceEnable.equalsIgnoreCase("true"))
+ bpid = addSenderNonceAttr(bpid, controlSeq, senderNonce);
+
+ if (popLinkWitnessEnable.equalsIgnoreCase("true"))
+ bpid = addPopLinkWitnessAttr(bpid, controlSeq);
+
+ SEQUENCE otherMsgSeq = new SEQUENCE();
+ if (revRequestEnable.equalsIgnoreCase("true")) {
+ if (revRequestIssuer.length() == 0 || revRequestSerial.length() == 0 ||
+ revRequestReason.length() == 0) {
+ System.out.println("Illegal parameters for revRequest control");
+ printUsage();
+ System.exit(1);
+ }
+
+ bpid = addRevRequestAttr(bpid, controlSeq, otherMsgSeq, revCertNickname,
+ revRequestIssuer, revRequestSerial, revRequestReason, revRequestSharedSecret,
+ revRequestComment, revRequestInvalidityDatePresent, cm);
+ }
+
+ ContentInfo cmcblob = getCMCBlob(signerCert, nickname, requests, format,
+ cm, transactionMgtEnable, transactionMgtId, identityProofEnable,
+ identityProofSharedSecret, controlSeq, otherMsgSeq, bpid);
+
+ // (6) Finally, print the actual CMC blob to the
+ // specified output file
+ FileOutputStream os = null;
+ try {
+ os = new FileOutputStream(ofilename);
+ cmcblob.encode(os);
+ System.out.println("");
+ System.out.println("");
+ System.out.println("The CMC enrollment request in binary format is stored in "+
+ ofilename+".");
+ } catch (IOException e) {
+ System.out.println("CMCRequest: unable to open file " +ofilename+
+ " for writing:\n" + e);
+ }
+
+ try {
+ os.close();
+ } catch (IOException e) {
+ System.out.println("CMCRequest: Unexpected error " +
+ "encountered while attempting to close() " +
+ "\n" + e);
+ }
+
+ }catch (Exception e) {
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+}
diff --git a/pki/base/java-tools/src/com/netscape/cmstools/CMCResponse.java b/pki/base/java-tools/src/com/netscape/cmstools/CMCResponse.java
new file mode 100644
index 000000000..04d3b4ddc
--- /dev/null
+++ b/pki/base/java-tools/src/com/netscape/cmstools/CMCResponse.java
@@ -0,0 +1,244 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmstools;
+
+import org.mozilla.jss.pkix.cmc.*;
+import org.mozilla.jss.pkix.cms.*;
+import org.mozilla.jss.pkix.cert.*;
+import org.mozilla.jss.pkix.primitive.*;
+import org.mozilla.jss.asn1.*;
+import org.mozilla.jss.pkcs10.*;
+import org.mozilla.jss.pkcs11.*;
+import org.mozilla.jss.crypto.*;
+import org.mozilla.jss.pkix.crmf.*;
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.crypto.CryptoToken;
+import org.mozilla.jss.crypto.SignatureAlgorithm;
+import org.mozilla.jss.crypto.DigestAlgorithm;
+import org.mozilla.jss.crypto.X509Certificate;
+import org.mozilla.jss.util.*;
+import org.mozilla.jss.*;
+
+import netscape.security.util.*;
+import netscape.security.x509.*;
+import netscape.security.pkcs.PKCS10;
+
+import java.security.cert.CertificateException;
+import java.math.*;
+import java.security.Principal;
+import java.lang.*;
+import java.lang.reflect.*;
+import java.io.*;
+import java.util.*;
+import java.text.*;
+
+/**
+ * Tool for parsing a CMC response
+ *
+ * <P>
+ * @version $Revision$, $Date$
+ *
+ */
+public class CMCResponse
+{
+
+ public CMCResponse() {
+ }
+
+ public static void printOutput(String path, String filename) {
+ byte[] bb = new byte[10000];
+ FileInputStream fis = null;
+ try {
+ fis = new FileInputStream(filename);
+ while (fis.available() > 0)
+ fis.read(bb, 0, 10000);
+ } catch (Exception e) {
+ System.out.println("Error reading the response. Exception: "+e.toString());
+ System.exit(1);
+ }
+
+ try {
+ ByteArrayInputStream bis = new ByteArrayInputStream(bb);
+ org.mozilla.jss.pkix.cms.ContentInfo cii = (org.mozilla.jss.pkix.cms.ContentInfo)
+ org.mozilla.jss.pkix.cms.ContentInfo.getTemplate().decode(bis);
+
+ org.mozilla.jss.pkix.cms.SignedData cmcFullResp =
+ (org.mozilla.jss.pkix.cms.SignedData)cii.getInterpretedContent();
+
+ String content = "";
+ if (cmcFullResp.hasCertificates()) {
+ SET certs = cmcFullResp.getCertificates();
+ int numCerts = certs.size();
+
+ for (int i = 0; i < numCerts; i++) {
+ Certificate cert = (Certificate) certs.elementAt(i);
+ X509CertImpl certImpl = new X509CertImpl(ASN1Util.encode(cert));
+ CertPrettyPrint print = new CertPrettyPrint(certImpl);
+ content += print.toString(Locale.getDefault());
+ }
+ }
+
+ System.out.println("Certificates: ");
+ System.out.println(content);
+ System.out.println("");
+ EncapsulatedContentInfo ci = cmcFullResp.getContentInfo();
+ OBJECT_IDENTIFIER id = ci.getContentType();
+ OBJECT_IDENTIFIER dataid = new OBJECT_IDENTIFIER("1.2.840.113549.1.7.1");
+ if (!id.equals(OBJECT_IDENTIFIER.id_cct_PKIResponse) && !id.equals(dataid)) {
+ System.out.println("Invalid CMC Response Format");
+ }
+
+ if (!ci.hasContent())
+ return;
+
+ OCTET_STRING content1 = ci.getContent();
+ ByteArrayInputStream bbis = new ByteArrayInputStream(content1.toByteArray());
+ ResponseBody responseBody = (ResponseBody) (new ResponseBody.Template()).decode(bbis);
+ SEQUENCE controlSequence = responseBody.getControlSequence();
+
+ int numControls = controlSequence.size();
+ System.out.println("Number of controls is "+numControls);
+ INTEGER bodyPartId = null;
+ String error = "";
+
+ for (int i=0; i<numControls; i++) {
+ TaggedAttribute taggedAttr = (TaggedAttribute) controlSequence.elementAt(i);
+ OBJECT_IDENTIFIER type = taggedAttr.getType();
+
+ if (type.equals(OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo)) {
+ System.out.println("Control #"+i+": CMCStatusInfo");
+ System.out.println(" OID: "+type.toString());
+ SET sts = taggedAttr.getValues();
+ int numSts = sts.size();
+ for (int j = 0; j < numSts; j++) {
+ CMCStatusInfo cst = (CMCStatusInfo)ASN1Util.decode(CMCStatusInfo.getTemplate(),
+ ASN1Util.encode(sts.elementAt(j)));
+ SEQUENCE seq = cst.getBodyList();
+
+ String s = " BodyList: ";
+ for (int k=0; k < seq.size(); k++) {
+ INTEGER n = (INTEGER)seq.elementAt(k);
+ s = s+n.toString()+" ";
+ }
+ System.out.println(s);
+ int st = cst.getStatus();
+ if (st != CMCStatusInfo.SUCCESS && st != CMCStatusInfo.CONFIRM_REQUIRED) {
+ String stString = cst.getStatusString();
+ if (stString != null)
+ System.out.println(" Status String: "+stString);
+ OtherInfo oi = cst.getOtherInfo();
+ OtherInfo.Type t = oi.getType();
+ if (t == OtherInfo.FAIL)
+ System.out.println(" OtherInfo type: FAIL");
+ else if (t == OtherInfo.PEND) {
+ System.out.println(" OtherInfo type: PEND");
+ PendInfo pi = oi.getPendInfo();
+ if (pi.getPendTime() != null) {
+ byte[] bp = pi.getPendToken().toByteArray();
+ String pt = new String(bp);
+ String datePattern = "dd/MMM/yyyy:HH:mm:ss z";
+ SimpleDateFormat dateFormat = new SimpleDateFormat(datePattern);
+ Date d = pi.getPendTime().toDate();
+ System.out.println(" Date: "+dateFormat.format(d));
+ }
+ }
+ } else if (st == CMCStatusInfo.SUCCESS) {
+ System.out.println(" Status: SUCCESS");
+ }
+ }
+ } else if (type.equals(OBJECT_IDENTIFIER.id_cmc_transactionId)) {
+ System.out.println("Control #"+i+": CMC Transaction Id");
+ System.out.println(" OID: "+type.toString());
+ SET transIds = taggedAttr.getValues();
+ INTEGER num = (INTEGER)(ASN1Util.decode(INTEGER.getTemplate(),
+ ASN1Util.encode(transIds.elementAt(0))));
+ System.out.println(" INTEGER: "+num);
+ } else if (type.equals(OBJECT_IDENTIFIER.id_cmc_recipientNonce)) {
+ System.out.println("Control #"+i+": CMC Recipient Nonce");
+ System.out.println(" OID: "+type.toString());
+ SET recipientN = taggedAttr.getValues();
+ OCTET_STRING str =
+ (OCTET_STRING)(ASN1Util.decode(OCTET_STRING.getTemplate(),
+ ASN1Util.encode(recipientN.elementAt(0))));
+ byte b[] = str.toByteArray();
+ String s = " Value: ";
+ for (int m=0; m<b.length; m++) {
+ s = s+b[m]+" ";
+ }
+ System.out.println(s);
+ } else if (type.equals(OBJECT_IDENTIFIER.id_cmc_senderNonce)) {
+ System.out.println("Control #"+i+": CMC Sender Nonce");
+ System.out.println(" OID: "+type.toString());
+ SET senderN = taggedAttr.getValues();
+ OCTET_STRING str =
+ (OCTET_STRING)(ASN1Util.decode(OCTET_STRING.getTemplate(),
+ ASN1Util.encode(senderN.elementAt(0))));
+ byte b[] = str.toByteArray();
+ String s = " Value: ";
+ for (int m=0; m<b.length; m++) {
+ s = s+b[m]+" ";
+ }
+ System.out.println(s);
+ } else if (type.equals(OBJECT_IDENTIFIER.id_cmc_dataReturn)) {
+ System.out.println("Control #"+i+": CMC Data Return");
+ System.out.println(" OID: "+type.toString());
+ SET dataReturn = taggedAttr.getValues();
+ OCTET_STRING str =
+ (OCTET_STRING)(ASN1Util.decode(OCTET_STRING.getTemplate(),
+ ASN1Util.encode(dataReturn.elementAt(0))));
+ byte b[] = str.toByteArray();
+ String s = " Value: ";
+ for (int m=0; m<b.length; m++) {
+ s = s+b[m]+" ";
+ }
+ System.out.println(s);
+ }
+ }
+ } catch (Exception e) {
+ System.out.println("Error found in the response. Exception: "+e.toString());
+ System.exit(1);
+
+ }
+ }
+
+ private static void printUsage() {
+ System.out.println("");
+ System.out.println("Usage: CMCResponse -d <pathname for cert8.db> -i <pathname for CMC response in binary format> ");
+ }
+
+ public static void main(String args[]) {
+ String filename = null, path = null;
+ if (args.length != 4) {
+ printUsage();
+ System.exit(1);
+ }
+
+ for (int i=0; i<args.length; i++) {
+ if (args[i].equals("-d"))
+ path = args[i+1];
+ else if (args[i].equals("-i"))
+ filename = args[i+1];
+ }
+
+ if (filename == null || path == null) {
+ printUsage();
+ System.exit(1);
+ }
+ printOutput(path, filename);
+ }
+}
diff --git a/pki/base/java-tools/src/com/netscape/cmstools/CMCRevoke.java b/pki/base/java-tools/src/com/netscape/cmstools/CMCRevoke.java
new file mode 100644
index 000000000..97d4f3551
--- /dev/null
+++ b/pki/base/java-tools/src/com/netscape/cmstools/CMCRevoke.java
@@ -0,0 +1,410 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmstools;
+
+
+import org.mozilla.jss.pkix.cmc.*;
+import org.mozilla.jss.pkix.cms.*;
+import org.mozilla.jss.pkix.cert.*;
+import org.mozilla.jss.pkix.primitive.*;
+import org.mozilla.jss.asn1.*;
+import org.mozilla.jss.pkcs10.*;
+import org.mozilla.jss.crypto.*;
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.crypto.CryptoToken;
+import org.mozilla.jss.crypto.SignatureAlgorithm;
+import org.mozilla.jss.crypto.DigestAlgorithm;
+import org.mozilla.jss.crypto.X509Certificate;
+import org.mozilla.jss.util.*;
+
+import org.mozilla.jss.*;
+
+import netscape.security.util.*;
+import netscape.security.x509.*;
+import netscape.security.pkcs.PKCS10;
+
+import java.security.*;
+import java.security.cert.CertificateException;
+import java.math.*;
+import java.security.Principal;
+import java.lang.*;
+import java.lang.reflect.*;
+import java.io.*;
+import java.util.*;
+
+
+
+/**
+ * Tool for signing a CMC revocation request with an agent's certificate.
+ *
+ * <P>
+ * @version $Revision$, $Date$
+ */
+public class CMCRevoke {
+ public static final int ARGC = 7;
+ private static final String CERTDB = "cert8.db";
+ private static final String KEYDB = "key3.db";
+ public static final String HEADER = "-----BEGIN NEW CERTIFICATE REQUEST-----";
+ public static final String TRAILER = "-----END NEW CERTIFICATE REQUEST-----";
+ static String dValue = null, nValue = null, iValue = null, sValue = null, mValue = null, hValue = null, cValue = null;
+
+ public static final String CMS_BASE_CA_SIGNINGCERT_NOT_FOUND="CA signing certificate not found";
+ public static final String PR_INTERNAL_TOKEN_NAME = "internal";
+ public static final String PR_REQUEST_CMC = "CMC";
+
+ static String cleanArgs(String s) {
+ if (s.startsWith("\"") && s.endsWith("\""))
+ return s.substring(1, s.length() - 2);
+ else if (s.startsWith("\'") && s.endsWith("\'"))
+ return new String(s.substring(1, s.length() - 2));
+ else
+ return s;
+ }
+
+ /**
+ * Creates a new instance of CMCRevoke.
+ */
+ public static void main(String[]s) {
+
+ FileOutputStream outputBlob = null;
+
+ // default path is "."
+ String mPath = ".";
+ // default prefix is ""
+ String mPrefix = "";
+
+ boolean bWrongParam = false;
+
+ // (1) Check that two arguments were submitted to the program
+ if (s.length != (ARGC) && s.length != (ARGC - 1)) {
+
+ bWrongParam = true;
+ System.out.println("Wrong number of parameters:" + s.length);
+ System.out.println("Usage: CMCRevoke " +
+ "-d<dir to cert8.db, key3.db> " +
+ "-n<nickname> " +
+ "-i<issuerName> " +
+ "-s<serialName> " +
+ "-m<reason to revoke> " +
+ "-h<password to db> " +
+ "-c<comment> ");
+ for (int i = 0; i < s.length; i++) {
+ System.out.println(i + ":" + s[i]);
+ }
+ }else {
+ int length;
+ int i;
+
+ length = s.length;
+ for (i = 0; i < length; i++) {
+ if (s[i].startsWith("-d")) {
+ dValue = cleanArgs(s[i].substring(2));
+ } else if (s[i].startsWith("-n")) {
+ nValue = cleanArgs(s[i].substring(2));
+ } else if (s[i].startsWith("-i")) {
+ iValue = cleanArgs(s[i].substring(2));
+ } else if (s[i].startsWith("-s")) {
+ sValue = cleanArgs(s[i].substring(2));
+ } else if (s[i].startsWith("-m")) {
+ mValue = cleanArgs(s[i].substring(2));
+ } else if (s[i].startsWith("-h")) {
+ hValue = cleanArgs(s[i].substring(2));
+ } else if (s[i].startsWith("-c")) {
+ cValue = cleanArgs(s[i].substring(2));
+ }
+
+ }
+ // optional parameter
+ if (cValue == null)
+ cValue = new String();
+ if (dValue == null || nValue == null || iValue == null || sValue == null || mValue == null || hValue == null)
+ bWrongParam = true;
+ else if (dValue.length() == 0 || nValue.length() == 0 || iValue.length() == 0 ||
+ sValue.length() == 0 || mValue.length() == 0 || hValue.length() == 0)
+ bWrongParam = true;
+
+ if (bWrongParam == true) {
+ System.out.println("Usage: CMCRevoke " +
+ "-d<dir to cert8.db, key3.db> " +
+ "-n<nickname> " +
+ "-i<issuerName> " +
+ "-s<serialName> " +
+ "-m<reason to revoke> " +
+ "-h<password to db> " +
+ "-c<comment> ");
+ for (i = 0; i < s.length; i++) {
+ System.out.println(i + ":" + s[i]);
+ }
+ System.exit(0);
+ }
+
+ try {
+ // initialize CryptoManager
+ mPath = dValue;
+ System.out.println("cert/key prefix = " + mPrefix);
+ System.out.println("path = " + mPath);
+ CryptoManager.InitializationValues vals =
+ new CryptoManager.InitializationValues(mPath, mPrefix, mPrefix, "secmod.db");
+
+ CryptoManager.initialize(vals);
+
+ CryptoManager cm = CryptoManager.getInstance();
+ CryptoToken token = cm.getInternalKeyStorageToken();
+ Password pass = new Password(hValue.toCharArray());
+
+ token.login(pass);
+ CryptoStore store = token.getCryptoStore();
+ X509Certificate[] list = store.getCertificates();
+ X509Certificate signerCert = null;
+
+ signerCert = cm.findCertByNickname(nValue);
+ String outBlob = createRevokeReq(signerCert, cm, nValue);
+
+ printCMCRevokeRequest(outBlob);
+ }catch (Exception e) {
+ e.printStackTrace();
+ System.exit(1);
+ }
+
+ return;
+ }
+ }
+
+ /**
+ * printout CMC revoke request in Base64 encoding to a file CMCRevoke.out
+ * <P>
+ * @param asciiBASE64Blob the ascii string of the request
+ */
+ static void printCMCRevokeRequest(String asciiBASE64Blob) {
+
+ // (6) Finally, print the actual CMCSigning blob to the
+ // specified output file
+ FileOutputStream outputBlob = null;
+
+ try {
+ outputBlob = new FileOutputStream("CMCRevoke.out");
+ } catch (IOException e) {
+ System.out.println("CMCSigning: unable to open file CMCRevoke.out for writing:\n" + e);
+ return;
+ }
+
+ System.out.println(HEADER);
+ System.out.println(asciiBASE64Blob + TRAILER);
+ try {
+ asciiBASE64Blob = HEADER + "\n" + asciiBASE64Blob + TRAILER;
+ outputBlob.write(asciiBASE64Blob.getBytes());
+ } catch (IOException e) {
+ System.out.println("CMCSigning: I/O error " +
+ "encountered during write():\n" +
+ e);
+ }
+
+ try {
+ outputBlob.close();
+ } catch (IOException e) {
+ System.out.println("CMCSigning: Unexpected error " +
+ "encountered while attempting to close() " +
+ "\n" + e);
+ }
+ }
+
+ /**
+ * getCertificate find the certicate inside the token by its nickname.
+ * <P>
+ * @param manager the CrytoManager
+ * @param tokenname the name of the token. it's set to "internal".
+ * @param nickname the nickname of the certificate inside the token.
+ * @return the X509Certificate.
+ */
+ public static X509Certificate getCertificate(CryptoManager manager, String tokenname,
+ String nickname) throws NoSuchTokenException,
+ Exception, TokenException {
+ CryptoToken token = null;
+
+ if (tokenname.equals(PR_INTERNAL_TOKEN_NAME)) {
+ token = manager.getInternalKeyStorageToken();
+ } else {
+ token = manager.getTokenByName(tokenname);
+ }
+ StringBuffer certname = new StringBuffer();
+
+ if (!token.equals(manager.getInternalKeyStorageToken())) {
+ certname.append(tokenname);
+ certname.append(":");
+ }
+ certname.append(nickname);
+ try {
+ return manager.findCertByNickname(certname.toString());
+ } catch (ObjectNotFoundException e) {
+ throw new Exception(CMS_BASE_CA_SIGNINGCERT_NOT_FOUND);
+ }
+ }
+
+ /**
+ * createRevokeReq create and return the revocation request.
+ * <P>
+ * @param signerCert the certificate of the authorized signer of the CMC revocation request.
+ * @param manager the crypto manger.
+ * @param nValue the nickname of the certificate inside the token.
+ * @return the CMC revocation request encoded in base64
+ */
+ static String createRevokeReq(X509Certificate signerCert, CryptoManager manager, String nValue) {
+
+ java.security.PrivateKey privKey = null;
+ SignerIdentifier si = null;
+ ContentInfo fullEnrollmentReq = null;
+ String tokenname = "internal";
+ String asciiBASE64Blob = new String();
+
+ try {
+
+ String hasSki = "true";
+
+ BigInteger serialno = signerCert.getSerialNumber();
+ byte[] certB = signerCert.getEncoded();
+ X509CertImpl impl = new X509CertImpl(certB);
+ X500Name issuerName = (X500Name) impl.getIssuerDN();
+ byte[] issuerByte = issuerName.getEncoded();
+ ByteArrayInputStream istream = new ByteArrayInputStream(issuerByte);
+
+ Name issuer = (Name) Name.getTemplate().decode(istream);
+ IssuerAndSerialNumber ias = new IssuerAndSerialNumber(issuer, new INTEGER(serialno.toString()));
+
+ si = new SignerIdentifier(SignerIdentifier.ISSUER_AND_SERIALNUMBER, ias, null);
+ X509Certificate cert = getCertificate(manager, tokenname, nValue);
+
+ privKey = manager.findPrivKeyByCert(cert);
+
+ if( privKey == null ) {
+ System.out.println( "CMCRevoke::createRevokeReq() - " +
+ "privKey is null!" );
+ return "";
+ }
+
+ int bpid = 1;
+ // Add some control sequence
+ // Verisign has transactionID,senderNonce
+ SEQUENCE controlSeq = new SEQUENCE();
+
+ Date date = new Date();
+ String salt = "lala123" + date.toString();
+ byte[] dig;
+
+ try {
+ MessageDigest SHA1Digest = MessageDigest.getInstance("SHA1");
+
+ dig = SHA1Digest.digest(salt.getBytes());
+ } catch (NoSuchAlgorithmException ex) {
+ dig = salt.getBytes();
+ }
+ String sn = com.netscape.osutil.OSUtil.BtoA(dig);
+
+ TaggedAttribute senderNonce = new TaggedAttribute(new INTEGER(bpid++), OBJECT_IDENTIFIER.id_cmc_senderNonce,
+ new OCTET_STRING(sn.getBytes()));
+
+ controlSeq.addElement(senderNonce);
+
+ Name subjectName = new Name();
+
+ subjectName.addCommonName(iValue);
+ org.mozilla.jss.pkix.cmmf.RevRequest lRevokeRequest = new org.mozilla.jss.pkix.cmmf.RevRequest(new ANY((new X500Name(iValue)).getEncoded()),
+ new INTEGER(sValue),
+ //org.mozilla.jss.pkix.cmmf.RevRequest.unspecified,
+ new ENUMERATED((new Integer(mValue)). longValue()),
+ //new GeneralizedTime(new Date(lValue)),
+ new OCTET_STRING(hValue.getBytes()),
+ new UTF8String(cValue.toCharArray()));
+ //byte[] encoded = ASN1Util.encode(lRevokeRequest);
+ //org.mozilla.jss.asn1.ASN1Template template = new org.mozilla.jss.pkix.cmmf.RevRequest.Template();
+ //org.mozilla.jss.pkix.cmmf.RevRequest revRequest = (org.mozilla.jss.pkix.cmmf.RevRequest)
+ // template.decode(new java.io.ByteArrayInputStream(
+ // encoded));
+
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ //lRevokeRequest.encode(os); // khai
+ TaggedAttribute revokeRequestTag = new TaggedAttribute(new INTEGER(bpid++), OBJECT_IDENTIFIER.id_cmc_revokeRequest,
+ lRevokeRequest);
+
+ controlSeq.addElement(revokeRequestTag);
+ PKIData pkidata = new PKIData(controlSeq, new SEQUENCE(), new SEQUENCE(), new SEQUENCE());
+
+ EncapsulatedContentInfo ci = new EncapsulatedContentInfo(OBJECT_IDENTIFIER.id_cct_PKIData, pkidata);
+ // SHA1 is the default digest Alg for now.
+ DigestAlgorithm digestAlg = null;
+ SignatureAlgorithm signAlg = SignatureAlgorithm.RSASignatureWithSHA1Digest;
+ org.mozilla.jss.crypto.PrivateKey.Type signingKeyType = ((org.mozilla.jss.crypto.PrivateKey) privKey).getType();
+
+ if (signingKeyType.equals(org.mozilla.jss.crypto.PrivateKey.Type.DSA))
+ signAlg = SignatureAlgorithm.DSASignatureWithSHA1Digest;
+ MessageDigest SHADigest = null;
+ byte[] digest = null;
+
+ try {
+ SHADigest = MessageDigest.getInstance("SHA1");
+ digestAlg = DigestAlgorithm.SHA1;
+
+ ByteArrayOutputStream ostream = new ByteArrayOutputStream();
+
+ pkidata.encode((OutputStream) ostream);
+ digest = SHADigest.digest(ostream.toByteArray());
+ } catch (NoSuchAlgorithmException e) {
+ }
+ SignerInfo signInfo = new SignerInfo(si, null, null, OBJECT_IDENTIFIER.id_cct_PKIData, digest, signAlg,
+ (org.mozilla.jss.crypto.PrivateKey) privKey);
+ SET signInfos = new SET();
+
+ signInfos.addElement(signInfo);
+
+ SET digestAlgs = new SET();
+
+ if (digestAlg != null) {
+ AlgorithmIdentifier ai = new AlgorithmIdentifier(digestAlg.toOID(), null);
+
+ digestAlgs.addElement(ai);
+ }
+
+ org.mozilla.jss.crypto.X509Certificate[] agentChain = manager.buildCertificateChain(signerCert);
+ SET certs = new SET();
+
+ for (int i = 0; i < agentChain.length; i++) {
+ ANY certificate = new ANY(agentChain[i].getEncoded());
+
+ certs.addElement(certificate);
+ }
+ SignedData req = new SignedData(digestAlgs, ci, certs, null, signInfos);
+
+ fullEnrollmentReq = new ContentInfo(req);
+
+ ByteArrayOutputStream bs = new ByteArrayOutputStream();
+ PrintStream ps = new PrintStream(bs);
+
+ if (fullEnrollmentReq != null) {
+ // format is PR_REQUEST_CMC
+ fullEnrollmentReq.encode(os);
+ ps.print(com.netscape.osutil.OSUtil.BtoA(os.toByteArray()));
+ ////fullEnrollmentReq.print(ps); // no header/trailer
+ }
+
+ asciiBASE64Blob = bs.toString();
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.exit(1);
+ }
+ return asciiBASE64Blob;
+ }
+}
diff --git a/pki/base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java b/pki/base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java
new file mode 100644
index 000000000..dc9bcb0cb
--- /dev/null
+++ b/pki/base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java
@@ -0,0 +1,646 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmstools;
+
+import java.io.*;
+import java.util.Date;
+import java.util.StringTokenizer;
+import java.net.URL;
+import java.net.URLConnection;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.BufferedReader;
+
+import java.net.URLEncoder;
+import java.security.KeyPair;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import org.mozilla.jss.util.Password;
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.crypto.CryptoToken;
+import org.mozilla.jss.crypto.KeyPairGenerator;
+import org.mozilla.jss.crypto.KeyPairAlgorithm;
+//import netscape.security.provider.RSAPublicKey;
+import netscape.security.pkcs.PKCS10;
+//import java.security.Signature;
+import netscape.security.x509.X500Name;
+import netscape.security.util.BigInt;
+import netscape.security.x509.X500Signer;
+import java.io.ByteArrayOutputStream;
+
+import org.mozilla.jss.crypto.*;
+import org.mozilla.jss.asn1.*;
+import org.mozilla.jss.pkix.primitive.*;
+import org.mozilla.jss.pkix.crmf.*;
+import com.netscape.cmsutil.util.*;
+
+
+/**
+ * A command-line utility used to generate a Certificate Request Message
+ * Format (CRMF) request with proof of possesion (POP).
+ *
+ * Usage:
+ * <pre>
+ * CRMFPopClient TOKEN_PWD
+ * Authenticator HOST PORT USER_NAME PASSWORD
+ * POP_OPTION
+ * SUBJECT_DN [OUTPUT_CERT_REQ]
+ *
+ * --- or ---
+ *
+ * CRMFPopClient TOKEN_PWD
+ * POP_OPTION
+ * OUTPUT_CERT_REQ SUBJECT_DN
+ *
+ *
+ * where POP_OPTION can be [POP_SUCCESS or POP_FAIL or POP_NONE]
+ * </pre>
+ * <p>
+ * Examples:
+ * <pre>
+ * CRMFPopClient password123
+ * nullAuthMgr host.netscape.com 1026 admin netscape
+ * [POP_SUCCESS or POP_FAIL or POP_NONE]
+ * CN=MyTest,C=US,UID=MyUid
+ *
+ * --- or ---
+ *
+ * CRMFPopClient password123
+ * nullAuthMgr host.netscape.com 1026 admin netscape
+ * [POP_SUCCESS or POP_FAIL or POP_NONE]
+ * CN=MyTest,C=US,UID=MyUid OUTPUT_CERT_REQ
+ *
+ * --- or ---
+ *
+ * CRMFPopClient password123
+ * [POP_SUCCESS or POP_FAIL or POP_NONE]
+ * OUTPUT_CERT_REQ CN=MyTest,C=US,UID=MyUid
+ * </pre>
+ * <p>
+ * <pre>
+ * IMPORTANT: The file "transport.txt" needs to be created to contain the
+ * transport certificate in its base64 encoded format. This
+ * file should consist of one line containing a single certificate
+ * in base64 encoded format with the header and footer removed.
+ * </pre>
+ * <p>
+ * @version $Revision$, $Date$
+ */
+public class CRMFPopClient
+{
+
+ private static void usage()
+ {
+ System.out.println("");
+ System.out.println("Description: A command-line utility used to generate a");
+ System.out.println(" Certificate Request Message Format (CRMF)");
+ System.out.println(" request with proof of possesion (POP).\n\n");
+ System.out.println("Usage:");
+ System.out.println("");
+ System.out.println(" CRMFPopClient TOKEN_PWD");
+ System.out.println(" Authenticator HOST PORT USER_NAME PASSWORD");
+ System.out.println(" POP_OPTION");
+ System.out.println(" SUBJECT_DN [OUTPUT_CERT_REQ] \n");
+ System.out.println(" --- or ---\n");
+ System.out.println(" CRMFPopClient TOKEN_PWD");
+ System.out.println(" POP_OPTION");
+ System.out.println(" OUTPUT_CERT_REQ SUBJECT_DN\n\n");
+ System.out.println(" where POP_OPTION can be [POP_SUCCESS or POP_FAIL or POP_NONE]\n\n");
+ System.out.println("Examples:");
+ System.out.println("");
+ System.out.println(" CRMFPopClient password123");
+ System.out.println(" nullAuthMgr host.netscape.com 1026 admin netscape");
+ System.out.println(" [POP_SUCCESS or POP_FAIL or POP_NONE]");
+ System.out.println(" CN=MyTest,C=US,UID=MyUid\n");
+ System.out.println(" --- or ---\n");
+ System.out.println(" CRMFPopClient password123");
+ System.out.println(" nullAuthMgr host.netscape.com 1026 admin netscape");
+ System.out.println(" [POP_SUCCESS or POP_FAIL or POP_NONE]");
+ System.out.println(" CN=MyTest,C=US,UID=MyUid OUTPUT_CERT_REQ\n");
+ System.out.println(" --- or ---\n");
+ System.out.println(" CRMFPopClient password123");
+ System.out.println(" [POP_SUCCESS or POP_FAIL or POP_NONE]");
+ System.out.println(" OUTPUT_CERT_REQ CN=MyTest,C=US,UID=MyUid");
+ System.out.println("\n");
+ System.out.println("IMPORTANT: The file \"transport.txt\" needs to be created to contain the");
+ System.out.println(" transport certificate in its base64 encoded format. This");
+ System.out.println(" file should consist of one line containing a single certificate");
+ System.out.println(" in base64 encoded format with the header and footer removed.\n");
+ }
+ private static int getRealArgsLength(String args[])
+ {
+
+ int len = args.length;
+
+ String curArg = "";
+ int finalLen = len;
+
+ for(int i = 0; i < len; i++)
+ {
+
+ curArg = args[i];
+ // System.out.println("arg[" + i + "] " + curArg);
+
+
+ if(curArg == null || curArg.equalsIgnoreCase("")) {
+ finalLen --;
+ }
+
+ }
+
+ //System.out.println("getRealArgsLength: returning " + finalLen);
+
+ if(finalLen < 0)
+ finalLen = 0;
+
+
+ return finalLen;
+
+
+ }
+ public static void main(String args[])
+ {
+ String USER_PREFIX = "user";
+
+
+ int argsLen = getRealArgsLength(args);
+
+ // System.out.println("args length " + argsLen);
+
+
+ System.out.println("\n\nProof Of Possession Utility....");
+ System.out.println("");
+
+ if(argsLen == 0 || (argsLen != 8 && argsLen != 9 && argsLen != 4))
+ {
+ usage();
+ return;
+ }
+
+ String DB_DIR = "./";
+ String TOKEN_PWD = args[0];
+ int KEY_LEN = 1024;
+
+
+ int PORT = 0;
+ String USER_NAME = null;
+ String USER_PWORD = null;
+ String AUTHENTICATOR = null;
+
+ String HOST = null;
+ String SUBJ_DN = null;
+
+
+ if(argsLen >= 8)
+ {
+ AUTHENTICATOR = args[1];
+ HOST = args[2];
+
+ PORT = Integer.parseInt(args[3]);
+
+ USER_NAME = args[4];
+ USER_PWORD = args[5];
+
+ SUBJ_DN = args[7];
+
+ }
+
+ String POP_OPTION = null;
+ String OUTPUT_CERT_REQ = null;
+
+ if(argsLen == 4)
+ POP_OPTION = args[1];
+ else
+ POP_OPTION = args[6];
+
+
+ int doServerHit = 1;
+
+ if(argsLen == 9)
+ OUTPUT_CERT_REQ = args[8];
+
+
+
+
+ if(argsLen == 4)
+ {
+ doServerHit = 0;
+ OUTPUT_CERT_REQ = args[2];
+ SUBJ_DN = args[3];
+ }
+
+
+ int dont_do_pop = 0;
+
+ if(POP_OPTION.equals("POP_NONE"))
+ {
+ dont_do_pop = 1;
+ }
+
+ URL url = null;
+ URLConnection conn = null;
+ InputStream is = null;
+ BufferedReader reader = null;
+ boolean success = false;
+ int num = 1;
+ long total_time = 0;
+ KeyPair pair = null;
+
+
+ boolean foundTransport = false;
+ String transportCert = null;
+ try {
+ BufferedReader br = new BufferedReader(new FileReader("./transport.txt"));
+ transportCert = br.readLine();
+ foundTransport = true;
+ } catch (Exception e) {
+ System.out.println("ERROR: cannot find ./transport.txt, so no key archival");
+
+ return;
+ }
+
+
+
+ try {
+ CryptoManager.initialize( DB_DIR );
+ } catch (Exception e) {
+ // it is ok if it is already initialized
+ System.out.println("INITIALIZATION ERROR: " + e.toString());
+// return;
+ }
+
+
+ try {
+ CryptoManager manager = CryptoManager.getInstance();
+ String token_pwd = TOKEN_PWD;
+ CryptoToken token = manager.getInternalKeyStorageToken();
+ Password password = new Password(token_pwd.toCharArray());
+ try {
+ token.login(password);
+ } catch (Exception e) {
+ //System.out.println("login Exception: " + e.toString());
+ if (!token.isLoggedIn()) {
+ token.initPassword(password, password);
+ }
+ }
+
+ System.out.println("."); //"done with cryptomanager");
+
+ KeyPairGenerator kg = token.getKeyPairGenerator(
+ KeyPairAlgorithm.RSA);
+ kg.initialize(KEY_LEN);
+
+ String authenticator = AUTHENTICATOR;
+ pair = kg.genKeyPair();
+
+ System.out.println("."); //key pair generated");
+
+ // wrap private key
+ byte transport[] = com.netscape.osutil.OSUtil.AtoB(transportCert);
+
+ X509Certificate tcert = manager.importCACertPackage(transport);
+
+ byte iv[] = {0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1};
+
+ KeyGenerator kg1 = token.getKeyGenerator(KeyGenAlgorithm.DES3);
+ SymmetricKey sk = kg1.generate();
+
+ System.out.println("."); //before KeyWrapper");
+
+ // wrap private key using session
+ KeyWrapper wrapper1 =
+ token.getKeyWrapper(KeyWrapAlgorithm.DES3_CBC_PAD);
+
+ System.out.println("."); //key wrapper created");
+
+ wrapper1.initWrap(sk, new IVParameterSpec(iv));
+
+ System.out.println("."); //key wrapper inited");
+ byte key_data[] = wrapper1.wrap((org.mozilla.jss.crypto.PrivateKey)pair.getPrivate());
+
+ System.out.println("."); //key wrapper wrapped");
+
+ // wrap session using transport
+ KeyWrapper rsaWrap = token.getKeyWrapper(
+ KeyWrapAlgorithm.RSA);
+
+ System.out.println("."); //got rsaWrapper");
+
+ rsaWrap.initWrap(tcert.getPublicKey(), null);
+
+ System.out.println("."); //rsaWrap inited");
+
+ byte session_data[] = rsaWrap.wrap(sk);
+
+ System.out.println("."); //rsaWrapped");
+
+ try {
+ // create CRMF
+ CertTemplate certTemplate = new CertTemplate();
+ certTemplate.setVersion(new INTEGER(2));
+
+ Name n1 = getJssName(SUBJ_DN);
+
+
+ Name n = new Name();
+
+ n.addCommonName("Me");
+ n.addCountryName("US");
+ n.addElement(new AVA(new OBJECT_IDENTIFIER("0.9.2342.19200300.100.1.1"), new PrintableString("MyUid")));
+
+ if(n1 != null)
+ certTemplate.setSubject(n1);
+ else
+ certTemplate.setSubject(n);
+
+ certTemplate.setPublicKey(new SubjectPublicKeyInfo(pair.getPublic()));
+ // set extension
+ AlgorithmIdentifier algS = new AlgorithmIdentifier(new OBJECT_IDENTIFIER("1.2.840.113549.3.7"), new OCTET_STRING(iv));
+ EncryptedValue encValue = new EncryptedValue(null, algS, new BIT_STRING(session_data, 7),null, null,new BIT_STRING(key_data, 7));
+ EncryptedKey key = new EncryptedKey(encValue);
+ PKIArchiveOptions opt = new PKIArchiveOptions(key);
+ SEQUENCE seq = new SEQUENCE();
+ if (foundTransport) {
+ seq.addElement(new AVA(new OBJECT_IDENTIFIER("1.3.6.1.5.5.7.5.1.4"),opt));
+ }
+
+
+ // Add idPOPLinkWitness control
+ String secretValue = "testing";
+ byte[] key1 = null;
+ byte[] finalDigest = null;
+ try {
+ MessageDigest SHA1Digest = MessageDigest.getInstance("SHA1");
+ key1 = SHA1Digest.digest(secretValue.getBytes());
+ } catch (NoSuchAlgorithmException ex) {
+ }
+
+/* Example of adding the POP link witness control to CRMF */
+byte[] b =
+{0x10, 0x53, 0x42, 0x24, 0x1a, 0x2a, 0x35, 0x3c,
+ 0x7a, 0x52, 0x54, 0x56, 0x71, 0x65, 0x66, 0x4c,
+ 0x51, 0x34, 0x35, 0x23, 0x3c, 0x42, 0x43, 0x45,
+ 0x61, 0x4f, 0x6e, 0x43, 0x1e, 0x2a, 0x2b, 0x31,
+ 0x32, 0x34, 0x35, 0x36, 0x55, 0x51, 0x48, 0x14,
+ 0x16, 0x29, 0x41, 0x42, 0x43, 0x7b, 0x63, 0x44,
+ 0x6a, 0x12, 0x6b, 0x3c, 0x4c, 0x3f, 0x00, 0x14,
+ 0x51, 0x61, 0x15, 0x22, 0x23, 0x5f, 0x5e, 0x69};
+
+ try {
+ MessageDigest SHA1Digest = MessageDigest.getInstance("SHA1");
+ HMACDigest hmacDigest = new HMACDigest(SHA1Digest, key1);
+ hmacDigest.update(b);
+ finalDigest = hmacDigest.digest();
+ } catch (NoSuchAlgorithmException ex) {
+ }
+
+
+ OCTET_STRING ostr = new OCTET_STRING(finalDigest);
+ seq.addElement(new AVA(OBJECT_IDENTIFIER.id_cmc_idPOPLinkWitness, ostr));
+ CertRequest certReq = new CertRequest(new INTEGER(1), certTemplate, seq);
+
+ System.out.println("."); //CertRequest created");
+
+
+ ByteArrayOutputStream bo = new ByteArrayOutputStream();
+ certReq.encode(bo);
+ byte[] toBeVerified = bo.toByteArray();
+
+ byte popdata[] = ASN1Util.encode(certReq);
+ byte signature[];
+
+ System.out.println("."); //CertRequest encoded");
+
+ Signature signer = token.getSignatureContext(
+ SignatureAlgorithm.RSASignatureWithMD5Digest);
+
+ System.out.println("."); //signer created");
+
+ signer.initSign((org.mozilla.jss.crypto.PrivateKey)pair.getPrivate());
+
+ System.out.println("."); //signer inited");
+
+ System.out.println("."); //FAIL_OR_SUCC " + FAIL_OR_SUCC);
+
+ if(POP_OPTION.equals("POP_SUCCESS"))
+ {
+ System.out.println("Generating Legal POP Data.....");
+ signer.update(toBeVerified);
+ }
+ else if(POP_OPTION.equals("POP_FAIL"))
+ {
+ System.out.println("Generating Illegal POP Data.....");
+ signer.update(iv);
+ }
+ else if(dont_do_pop == 1)
+ {
+ System.out.println("Generating NO POP Data.....");
+ }
+
+ System.out.println("."); //signer updated");
+
+ CertReqMsg crmfMsg = null;
+
+ if(dont_do_pop == 0)
+ {
+ signature = signer.sign();
+
+ System.out.println("Signature completed...");
+ System.out.println("");
+
+
+ AlgorithmIdentifier algID =
+ new AlgorithmIdentifier(SignatureAlgorithm.RSASignatureWithMD5Digest.toOID(), null );
+ POPOSigningKey popoKey = new POPOSigningKey(null,algID, new BIT_STRING(signature,0));
+
+ ProofOfPossession pop = ProofOfPossession.createSignature(popoKey);
+
+ crmfMsg = new CertReqMsg(certReq, pop, null);
+
+ }
+ else
+ {
+ crmfMsg = new CertReqMsg(certReq, null, null);
+
+ }
+
+ //crmfMsg.verify();
+
+ SEQUENCE s1 = new SEQUENCE();
+ s1.addElement(crmfMsg);
+ byte encoded[] = ASN1Util.encode(s1);
+
+ String Req1 = com.netscape.osutil.OSUtil.BtoA(encoded);
+
+ if(OUTPUT_CERT_REQ != null)
+ {
+ System.out.println("Generated Cert Request: ...... ");
+ System.out.println("");
+
+ System.out.println(Req1);
+ System.out.println("");
+ System.out.println("End Request:");
+
+ if(doServerHit == 0)
+ return;
+ }
+
+ String Req = URLEncoder.encode(Req1);
+
+ // post PKCS10
+
+ url = new URL("http://" + HOST + ":" + PORT + "/enrollment?importCert=off&uid="+USER_NAME+"&pwd="+ USER_PWORD+"&authenticator=" + authenticator + "&csrRequestorName=" + USER_PREFIX + 0 + "&CN=testuser&UID=" + USER_PREFIX + 0 + "&SMIME=true&SSLClient=true&ObjectSigning=false&csrRequestorEmail=mail&csrRequestorPhone=1234&csrRequestorComments=hello&CRMFRequest=" + Req + "&submit=Submit&subject=CN%3Dtestuser%2CUID%3D$user%2COU%3DPKI%2CO%3DU.S.Government%2CC%3DUS&certType=client&templateType=DisplayBySerial");
+
+ //System.out.println("Posting " + url);
+
+ System.out.println("");
+ System.out.println("Server Response.....");
+ System.out.println("--------------------");
+ System.out.println("");
+
+ long start_time = (new Date()).getTime();
+ conn = url.openConnection();
+ is = conn.getInputStream();
+ reader = new BufferedReader(new InputStreamReader(is));
+ String line = null;
+ while ((line = reader.readLine()) != null) {
+ System.out.println(line);
+ if (line.equals("CMS Enroll Request Success")) {
+ success = true;
+ System.out.println("Enrollment Successful: ......");
+ System.out.println("");
+ }
+ } /* while */
+ long end_time = (new Date()).getTime();
+ total_time += (end_time - start_time);
+ } catch (Exception e) {
+ System.out.println("WARNING: " + e.toString());
+ e.printStackTrace();
+ }
+ } catch (Exception e) {
+ System.out.println("ERROR: " + e.toString());
+ e.printStackTrace();
+ }
+ }
+
+ static Name getJssName(String dn)
+ {
+
+ X500Name x5Name = null;
+
+ try {
+ x5Name= new X500Name(dn);
+
+ } catch(IOException e) {
+
+ System.out.println("Illegal Subject Name: " + dn + " Error: " + e.toString());
+ System.out.println("Filling in default Subject Name......");
+ return null;
+ }
+
+ Name ret = new Name();
+
+ netscape.security.x509.RDN[] names = null;
+
+ names = x5Name.getNames();
+
+ int nameLen = x5Name.getNamesLength();
+
+// System.out.println("x5Name len: " + nameLen);
+
+ netscape.security.x509.RDN cur = null;
+
+ for(int i = 0; i < nameLen ; i++)
+ {
+ cur = names[i];
+
+ String rdnStr = cur.toString();
+
+
+ String[] split = rdnStr.split("=");
+
+ if(split.length != 2)
+ continue;
+
+ try {
+
+ if(split[0].equals("UID"))
+ {
+
+ ret.addElement(new AVA(new OBJECT_IDENTIFIER("0.9.2342.19200300.100.1.1"), new PrintableString(split[1])));
+ // System.out.println("UID found : " + split[1]);
+
+ }
+
+ if(split[0].equals("C"))
+ {
+ ret.addCountryName(split[1]);
+ // System.out.println("C found : " + split[1]);
+ continue;
+
+ }
+
+ if(split[0].equals("CN"))
+ {
+ ret.addCommonName(split[1]);
+ // System.out.println("CN found : " + split[1]);
+ continue;
+ }
+
+ if(split[0].equals("L"))
+ {
+ ret.addLocalityName(split[1]);
+ // System.out.println("L found : " + split[1]);
+ continue;
+ }
+
+ if(split[0].equals("O"))
+ {
+ ret.addOrganizationName(split[1]);
+ // System.out.println("O found : " + split[1]);
+ continue;
+ }
+
+ if(split[0].equals("ST"))
+ {
+ ret.addStateOrProvinceName(split[1]);
+ // System.out.println("ST found : " + split[1]);
+ continue;
+ }
+
+ if(split[0].equals("OU"))
+ {
+ ret.addOrganizationalUnitName(split[1]);
+ // System.out.println("OU found : " + split[1]);
+ continue;
+ }
+ } catch (Exception e) {
+ System.out.println("Error constructing RDN: " + rdnStr + " Error: " + e.toString());
+
+ continue;
+ }
+
+
+ }
+
+ return ret;
+
+
+ }
+}
diff --git a/pki/base/java-tools/src/com/netscape/cmstools/ExtJoiner.java b/pki/base/java-tools/src/com/netscape/cmstools/ExtJoiner.java
new file mode 100644
index 000000000..2854c04a1
--- /dev/null
+++ b/pki/base/java-tools/src/com/netscape/cmstools/ExtJoiner.java
@@ -0,0 +1,98 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmstools;
+
+
+import java.io.*;
+import java.net.*;
+import netscape.security.x509.*;
+import netscape.security.util.*;
+
+
+/**
+ * This program joins a sequence of extensions together
+ * so that the final output can be used in configuration
+ * wizard for specifing extra extensions in default
+ * certificates (i.e. CA certificate, SSL certificate).
+ *
+ * Usage:
+ * <pre>
+ * ExtJoiner \
+ * &lt;ext_file0&gt; &lt;ext_file1&gt; ... &lt;ext_fileN&gt;
+ *
+ * where,
+ * &lt;ext_file&gt; is a file that has the base64
+ * encoded DER encoding of an X509 Extension
+ *
+ * ExtensionSequence ::= SEQUENCE OF Extension;
+ *
+ * 0 30 142: SEQUENCE {
+ * 3 30 69: SEQUENCE {
+ * 5 06 3: OBJECT IDENTIFIER issuerAltName (2 5 29 18)
+ * 10 04 62: OCTET STRING
+ * : 30 3C 82 01 61 82 01 61 A4 10 30 0E 31 0C 30 0A
+ * : 06 03 55 04 03 13 03 64 73 61 87 04 01 01 01 01
+ * : 86 01 61 81 14 74 68 6F 6D 61 73 6B 40 6E 65 74
+ * : 73 63 61 70 65 2E 63 6F 6D 88 03 29 01 01
+ * : }
+ * 74 30 69: SEQUENCE {
+ * 76 06 3: OBJECT IDENTIFIER subjectAltName (2 5 29 17)
+ * 81 04 62: OCTET STRING
+ * : 30 3C 82 01 61 82 01 61 A4 10 30 0E 31 0C 30 0A
+ * : 06 03 55 04 03 13 03 64 73 61 87 04 01 01 01 01
+ * : 86 01 61 81 14 74 68 6F 6D 61 73 6B 40 6E 65 74
+ * : 73 63 61 70 65 2E 63 6F 6D 88 03 29 01 01
+ * : }
+ * : }
+ * </pre>
+ *
+ * @version $Revision$, $Date$
+ */
+public class ExtJoiner {
+
+ public static void main(String args[]) {
+ try {
+ if (args.length == 0) {
+ System.out.println("Usage: ExtJoiner <ext_file0> <ext_file1> ... <ext_fileN>");
+ System.exit(0);
+ }
+ DerValue exts[] = new DerValue[args.length];
+
+ for (int i = 0; i < args.length; i++) {
+ byte data[] = getFileData(args[i]);
+
+ exts[i] = new DerValue(data);
+ }
+ DerOutputStream out = new DerOutputStream();
+
+ out.putSequence(exts);
+ System.out.println(com.netscape.osutil.OSUtil.BtoA(out.toByteArray()));
+ } catch (IOException e) {
+ System.out.println(e.toString());
+ }
+ }
+
+ public static byte[] getFileData(String fileName)
+ throws IOException {
+ FileInputStream fis = new FileInputStream(fileName);
+
+ byte data[] = new byte[fis.available()];
+ fis.read(data);
+ return com.netscape.osutil.OSUtil.BtoA(data).getBytes();
+ }
+}
diff --git a/pki/base/java-tools/src/com/netscape/cmstools/GenExtKeyUsage.java b/pki/base/java-tools/src/com/netscape/cmstools/GenExtKeyUsage.java
new file mode 100644
index 000000000..4f0eb55ca
--- /dev/null
+++ b/pki/base/java-tools/src/com/netscape/cmstools/GenExtKeyUsage.java
@@ -0,0 +1,98 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmstools;
+
+
+import java.io.*;
+import java.util.Vector;
+import netscape.security.x509.*;
+import netscape.security.util.*;
+
+
+/**
+ * Generates a DER-encoded Extended Key Usage extension.
+ * The first parameter is the criticality of the extension, true or false.
+ * The OIDs to be included in the extension are passed as command-line
+ * arguments. The OIDs are described in RFC 2459. For example,
+ * the OID for code signing is 1.3.6.1.5.5.7.3.3.
+ *
+ * @version $Revision$, $Date$
+ */
+public class GenExtKeyUsage {
+
+ public static void main(String[] args) {
+ try {
+ if (args.length < 2) {
+ System.out.println("Usage: GenExtKeyUsage [true|false] <OID> ...");
+ System.exit(-1);
+ }
+
+ boolean critical = false;
+
+ if (args[0].equalsIgnoreCase("true")) {
+ critical = true;
+ } else if (args[0].equalsIgnoreCase("false")) {
+ critical = false;
+ } else {
+ System.out.println("Usage: GenExtKeyUsage [true|false] <OID> ...");
+ System.exit(-1);
+ }
+
+ // Generate vector of object identifiers from command line
+ Vector oids = new Vector();
+
+ for (int i = 1; i < args.length; i++) {
+ ObjectIdentifier oid = new ObjectIdentifier(args[i]);
+
+ oids.addElement(oid);
+ }
+
+ // encode all the object identifiers to the DerOutputStream
+ DerOutputStream contents = new DerOutputStream();
+
+ for (int i = 0; i < oids.size(); i++) {
+ contents.putOID((ObjectIdentifier) oids.elementAt(i));
+ }
+
+ // stuff the object identifiers into a SEQUENCE
+ DerOutputStream seq = new DerOutputStream();
+
+ seq.write(DerValue.tag_Sequence, contents);
+
+ // encode the SEQUENCE in an octet string
+ DerOutputStream octetString = new DerOutputStream();
+
+ octetString.putOctetString(seq.toByteArray());
+
+ // Construct an extension
+ ObjectIdentifier extKeyUsageOID = new ObjectIdentifier("2.5.29.37");
+ Extension extn = new Extension(extKeyUsageOID, critical,
+ octetString.toByteArray());
+ DerOutputStream extdos = new DerOutputStream();
+
+ extn.encode(extdos);
+
+ // BASE64 encode the whole thing and write it to stdout
+
+ System.out.println(com.netscape.osutil.OSUtil.BtoA(extdos.toByteArray()));
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/pki/base/java-tools/src/com/netscape/cmstools/GenIssuerAltNameExt.java b/pki/base/java-tools/src/com/netscape/cmstools/GenIssuerAltNameExt.java
new file mode 100644
index 000000000..3ce25778b
--- /dev/null
+++ b/pki/base/java-tools/src/com/netscape/cmstools/GenIssuerAltNameExt.java
@@ -0,0 +1,130 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmstools;
+
+
+import java.io.*;
+import java.net.*;
+import netscape.security.x509.*;
+import netscape.security.util.*;
+
+
+/**
+ * This program generates an issuer alternative name extension
+ * in base-64 encoding. The encoding output can be used with
+ * the configuration wizard.
+ *
+ * Usage:
+ * <pre>
+ * GenIssuerAltNameExt \
+ * &lt;general_type0&gt; &lt;general_name0&gt; ... &lt;general_typeN&gt; &lt;general_nameN&gt;
+ *
+ * where,
+ * &lt;general_type&gt; can be one of the following string:
+ * DNSName
+ * EDIPartyName
+ * IPAddressName
+ * URIName
+ * RFC822Name
+ * OIDName
+ * X500Name
+ * &lt;general_name&gt; is string
+ * </pre>
+ *
+ * @version $Revision$, $Date$
+ */
+public class GenIssuerAltNameExt {
+
+ public static void main(String args[]) {
+ try {
+ if ((args.length == 0) || (args.length % 2 != 0)) {
+ doUsage();
+ System.exit(0);
+ }
+ GeneralNames gns = new GeneralNames();
+
+ for (int i = 0; i < args.length; i += 2) {
+ GeneralNameInterface gni =
+ buildGeneralNameInterface(
+ args[i], args[i + 1]);
+
+ gns.addElement(gni);
+ }
+
+ IssuerAlternativeNameExtension sane =
+ new IssuerAlternativeNameExtension(gns);
+
+ output(sane);
+ } catch (Exception e) {
+ System.out.println(e.toString());
+ }
+ }
+
+ public static void output(IssuerAlternativeNameExtension ext)
+ throws Exception {
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+
+ ext.encode(os);
+
+ System.out.println(
+ com.netscape.osutil.OSUtil.BtoA(os.toByteArray())
+ );
+ }
+
+ public static void doUsage() {
+ System.out.println();
+ System.out.println("Usage: GenIssuerAltNameExt <general_type0> <general_name0> ... <general_typeN> <general_nameN>");
+ System.out.println("where,");
+ System.out.println("<general_type> can be one of the following string:");
+ System.out.println("\tDNSName");
+ System.out.println("\tEDIPartyName");
+ System.out.println("\tIPAddressName");
+ System.out.println("\tURIName");
+ System.out.println("\tRFC822Name");
+ System.out.println("\tOIDName");
+ System.out.println("\tX500Name");
+ System.out.println("<general_name> is a string");
+ }
+
+ public static GeneralNameInterface buildGeneralNameInterface(
+ String type, String value) throws Exception {
+ if (type.equals("DNSName")) {
+ return new DNSName(value);
+ } else if (type.equals("EDIPartyName")) {
+ return new DNSName(value);
+ } else if (type.equals("IPAddressName")) {
+ InetAddress addr = InetAddress.getByName(value);
+
+ return new IPAddressName(addr.getAddress());
+ } else if (type.equals("URIName")) {
+ return new URIName(value);
+ } else if (type.equals("OIDName")) {
+ return new OIDName(new ObjectIdentifier(value));
+ } else if (type.equals("RFC822Name")) {
+ return new RFC822Name(value);
+ } else if (type.equals("X500Name")) {
+ return new X500Name(value);
+ } else {
+ System.out.println("Error: unknown general_type " +
+ type);
+ doUsage();
+ System.exit(0);
+ return null;
+ }
+ }
+}
diff --git a/pki/base/java-tools/src/com/netscape/cmstools/GenSubjectAltNameExt.java b/pki/base/java-tools/src/com/netscape/cmstools/GenSubjectAltNameExt.java
new file mode 100644
index 000000000..8d28a04e0
--- /dev/null
+++ b/pki/base/java-tools/src/com/netscape/cmstools/GenSubjectAltNameExt.java
@@ -0,0 +1,130 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmstools;
+
+
+import java.io.*;
+import java.net.*;
+import netscape.security.x509.*;
+import netscape.security.util.*;
+
+
+/**
+ * This program generates an subject alternative name extension
+ * in base-64 encoding. The encoding output can be used with
+ * the configuration wizard.
+ *
+ * Usage:
+ * <pre>
+ * GenSubjectAltNameExt \
+ * &lt;general_type0&gt; &lt;general_name0&gt; ... &lt;general_typeN&gt; &lt;general_nameN&gt;
+ *
+ * where,
+ * &lt;general_type&gt; can be one of the following string:
+ * DNSName
+ * EDIPartyName
+ * IPAddressName
+ * URIName
+ * RFC822Name
+ * OIDName
+ * X500Name
+ * &lt;general_name&gt; is string
+ * </pre>
+ *
+ * @version $Revision$, $Date$
+ */
+public class GenSubjectAltNameExt {
+
+ public static void main(String args[]) {
+ try {
+ if ((args.length == 0) || (args.length % 2 != 0)) {
+ doUsage();
+ System.exit(0);
+ }
+ GeneralNames gns = new GeneralNames();
+
+ for (int i = 0; i < args.length; i += 2) {
+ GeneralNameInterface gni =
+ buildGeneralNameInterface(
+ args[i], args[i + 1]);
+
+ gns.addElement(gni);
+ }
+
+ SubjectAlternativeNameExtension sane =
+ new SubjectAlternativeNameExtension(gns);
+
+ output(sane);
+ } catch (Exception e) {
+ System.out.println(e.toString());
+ }
+ }
+
+ public static void output(SubjectAlternativeNameExtension ext)
+ throws Exception {
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+
+ ext.encode(os);
+
+ System.out.println(
+ com.netscape.osutil.OSUtil.BtoA(os.toByteArray())
+ );
+ }
+
+ public static void doUsage() {
+ System.out.println();
+ System.out.println("Usage: GenSubjectAltNameExt <general_type0> <general_name0> ... <general_typeN> <general_nameN>");
+ System.out.println("where,");
+ System.out.println("<general_type> can be one of the following string:");
+ System.out.println("\tDNSName");
+ System.out.println("\tEDIPartyName");
+ System.out.println("\tIPAddressName");
+ System.out.println("\tURIName");
+ System.out.println("\tRFC822Name");
+ System.out.println("\tOIDName");
+ System.out.println("\tX500Name");
+ System.out.println("<general_name> is a string");
+ }
+
+ public static GeneralNameInterface buildGeneralNameInterface(
+ String type, String value) throws Exception {
+ if (type.equals("DNSName")) {
+ return new DNSName(value);
+ } else if (type.equals("EDIPartyName")) {
+ return new DNSName(value);
+ } else if (type.equals("IPAddressName")) {
+ InetAddress addr = InetAddress.getByName(value);
+
+ return new IPAddressName(addr.getAddress());
+ } else if (type.equals("URIName")) {
+ return new URIName(value);
+ } else if (type.equals("OIDName")) {
+ return new OIDName(new ObjectIdentifier(value));
+ } else if (type.equals("RFC822Name")) {
+ return new RFC822Name(value);
+ } else if (type.equals("X500Name")) {
+ return new X500Name(value);
+ } else {
+ System.out.println("Error: unknown general_type " +
+ type);
+ doUsage();
+ System.exit(0);
+ return null;
+ }
+ }
+}
diff --git a/pki/base/java-tools/src/com/netscape/cmstools/HttpClient.java b/pki/base/java-tools/src/com/netscape/cmstools/HttpClient.java
new file mode 100644
index 000000000..1cfc72456
--- /dev/null
+++ b/pki/base/java-tools/src/com/netscape/cmstools/HttpClient.java
@@ -0,0 +1,410 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmstools;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import java.security.*;
+
+import org.mozilla.jss.*;
+import org.mozilla.jss.util.*;
+import org.mozilla.jss.asn1.*;
+import org.mozilla.jss.ssl.*;
+import org.mozilla.jss.pkix.primitive.*;
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.crypto.*;
+import org.mozilla.jss.CertDatabaseException;
+import org.mozilla.jss.pkcs11.*;
+import org.mozilla.jss.pkcs11.PK11Token;
+
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509Key;
+import netscape.security.x509.X500Name;
+
+import com.netscape.cmsutil.ocsp.*;
+import com.netscape.cmsutil.ocsp.Request;
+
+
+/**
+ * This class implements a CMC Enroll client for testing.
+ *
+ * @version $Revision$, $Date$
+ */
+public class HttpClient
+{
+ private String _host = null;
+ private int _port = 0;
+ private boolean _secure = false;
+
+ public static final int ARGC = 1;
+ static final int cipherSuites[] = {
+ SSLSocket.SSL3_RSA_WITH_RC4_128_MD5,
+ SSLSocket.SSL3_RSA_WITH_3DES_EDE_CBC_SHA,
+ SSLSocket.SSL3_RSA_WITH_DES_CBC_SHA,
+ SSLSocket.SSL3_RSA_EXPORT_WITH_RC4_40_MD5,
+ SSLSocket.SSL3_RSA_EXPORT_WITH_RC2_CBC_40_MD5,
+ SSLSocket.SSL3_RSA_WITH_NULL_MD5,
+ 0
+ };
+
+ public HttpClient(String host, int port, String secure)
+ throws Exception
+ {
+ _host = host;
+ _port = port;
+ if (secure.equals("true"))
+ _secure = true;
+ }
+
+ public static byte[] getBytesFromFile(String filename) throws IOException {
+ File file = new File(filename);
+ FileInputStream is = new FileInputStream(file);
+
+ long length = file.length();
+
+ if (length > Integer.MAX_VALUE) {
+ throw new IOException("Input file " + filename +
+ " is too large. Must be smaller than " + Integer.MAX_VALUE);
+ }
+
+ byte[] bytes = new byte[(int)length];
+
+ int offset = 0;
+ int numRead = 0;
+ while (offset < bytes.length
+ && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
+ offset += numRead;
+ }
+
+ if (offset < bytes.length) {
+ throw new IOException("Could not completely read file "+filename);
+ }
+
+ is.close();
+ return bytes;
+ }
+
+
+ public void send(String ifilename, String ofilename, String dbdir,
+ String nickname, String password, String servlet, String clientmode)
+ throws Exception
+ {
+ byte[] b = getBytesFromFile(ifilename);
+
+ System.out.println("Total number of bytes read = "+b.length);
+
+ DataOutputStream dos = null;
+ InputStream is = null;
+ if (_secure) {
+ try {
+ CryptoManager.InitializationValues vals =
+ new CryptoManager.InitializationValues(dbdir, "", "", "secmod.db");
+ CryptoManager.initialize(vals);
+ SSLSocket socket = new SSLSocket(_host, _port);
+ int i;
+
+ for (i = SSLSocket.SSL2_RC4_128_WITH_MD5;
+ i <= SSLSocket.SSL2_RC2_128_CBC_EXPORT40_WITH_MD5; ++i) {
+ try {
+ socket.setCipherPreference(i, true);
+ } catch( SocketException e) {
+ }
+ }
+ //skip SSL_EN_IDEA_128_EDE3_CBC_WITH_MD5
+ for (i = SSLSocket.SSL2_DES_64_CBC_WITH_MD5;
+ i <= SSLSocket.SSL2_DES_192_EDE3_CBC_WITH_MD5; ++i) {
+ try {
+ socket.setCipherPreference(i, true);
+ } catch( SocketException e) {
+ }
+ }
+ for (i = 0; cipherSuites[i] != 0; ++i) {
+ try {
+ socket.setCipherPreference(cipherSuites[i], true);
+ } catch( SocketException e) {
+ }
+ }
+ SSLHandshakeCompletedListener listener = new ClientHandshakeCB(this);
+ socket.addHandshakeCompletedListener(listener);
+
+ if (clientmode != null && clientmode.equals("true")) {
+ CryptoManager cm = CryptoManager.getInstance();
+ CryptoToken token = cm.getInternalKeyStorageToken();
+ Password pass = new Password(password.toCharArray());
+ token.login(pass);
+ CryptoStore store = token.getCryptoStore();
+ X509Certificate cert = cm.findCertByNickname(nickname);
+ if (cert == null)
+ System.out.println("client cert is null");
+ else
+ System.out.println("client cert is not null");
+ socket.setUseClientMode(true);
+ socket.setClientCertNickname(nickname);
+ }
+
+ socket.forceHandshake();
+ dos = new DataOutputStream(socket.getOutputStream());
+ is = socket.getInputStream();
+ } catch (Exception e) {
+ System.out.println("Exception: "+e.toString());
+ return;
+ }
+ } else {
+ Socket socket = new Socket(_host, _port);
+ dos = new DataOutputStream(socket.getOutputStream());
+ is = socket.getInputStream();
+ }
+
+ // send request
+ if (servlet == null) {
+ System.out.println("Missing servlet name.");
+ printUsage();
+ } else {
+ String s = "POST "+servlet+" HTTP/1.0\r\n";
+ dos.writeBytes(s);
+ }
+ dos.writeBytes("Content-length: " + b.length + "\r\n");
+ dos.writeBytes("\r\n");
+ dos.write(b);
+ dos.flush();
+
+ FileOutputStream fof = new FileOutputStream(ofilename);
+ boolean startSaving = false;
+ int sum = 0;
+ boolean hack = false;
+ try {
+ while (true)
+ {
+ int r = is.read();
+ if (r == -1)
+ break;
+ if (r == 10) {
+ sum++;
+ }
+ if (sum == 6) {
+ startSaving = true;
+ continue;
+ }
+ if (startSaving) {
+ if (hack) {
+ fof.write(r);
+ }
+ if (hack == false) {
+ hack = true;
+ }
+ }
+ }
+ } catch (IOException e) {
+ }
+ fof.close();
+
+ byte[] bout = getBytesFromFile(ofilename);
+ System.out.println("Total number of bytes read = "+ bout.length);
+
+ ByteArrayOutputStream bs = new ByteArrayOutputStream();
+ PrintStream ps = new PrintStream(bs);
+ ps.print(com.netscape.osutil.OSUtil.BtoA(bout));
+ System.out.println(bs.toString());
+
+ System.out.println("");
+ System.out.println("The response in binary format is stored in "+ofilename);
+ System.out.println("");
+ }
+
+ static void printUsage() {
+ System.out.println("");
+ System.out.println("Usage: HttpClient <configuration file>");
+ System.out.println("For example, HttpClient HttpClient.cfg");
+ System.out.println("");
+ System.out.println("The configuration file should look like as follows:");
+ System.out.println("");
+ System.out.println("#host: host name for the http server");
+ System.out.println("host=host1.a.com");
+ System.out.println("");
+ System.out.println("#port: port number");
+ System.out.println("port=1025");
+ System.out.println("");
+ System.out.println("#secure: true for secure connection, false for nonsecure connection");
+ System.out.println("secure=false");
+ System.out.println("");
+ System.out.println("#input: full path for the enrollment request, the content must be in binary format");
+ System.out.println("input=/u/doc/cmcReqCRMFBin");
+ System.out.println("");
+ System.out.println("#output: full path for the response in binary format");
+ System.out.println("output=/u/doc/cmcResp");
+ System.out.println("");
+ System.out.println("#dbdir: directory for cert8.db, key3.db and secmod.db");
+ System.out.println("#This parameter will be ignored if secure=false");
+ System.out.println("dbdir=/u/smith/.netscape");
+ System.out.println("");
+ System.out.println("#clientmode: true for client authentication, false for no client authentication");
+ System.out.println("#This parameter will be ignored if secure=false");
+ System.out.println("clientmode=false");
+ System.out.println("");
+ System.out.println("#password: password for cert8.db");
+ System.out.println("#This parameter will be ignored if secure=false and clientauth=false");
+ System.out.println("password=");
+ System.out.println("");
+ System.out.println("#nickname: nickname for client certificate");
+ System.out.println("#This parameter will be ignored if clientmode=false");
+ System.out.println("nickname=");
+ System.out.println("");
+ System.out.println("#servlet: servlet name");
+ System.out.println("servlet=/ca/profileSubmitCMCFull");
+ System.out.println("");
+ System.exit(0);
+ }
+
+ public static void main(String args[])
+ {
+ String host = null, portstr = null, secure = null, dbdir = null, nickname = null ;
+ String password = null, ofilename = null, ifilename = null;
+ String servlet = null;
+ String clientmode = null;
+
+ System.out.println("");
+
+ // Check that the correct # of arguments were submitted to the program
+ if( args.length != ( ARGC ) ) {
+ System.out.println("Wrong number of parameters:" + args.length);
+ printUsage();
+ }
+
+ String configFile = args[0];
+ BufferedReader reader = null;
+ try {
+ reader = new BufferedReader(new InputStreamReader(
+ new BufferedInputStream(
+ new FileInputStream(configFile))));
+ } catch (FileNotFoundException e) {
+ System.out.println("HttpClient: can't find configuration file: "+configFile);
+ printUsage();
+ System.exit(1);
+ } catch (Exception e) {
+ e.printStackTrace();
+ printUsage();
+ return;
+ }
+
+ try {
+ String str = "";
+ while ((str = reader.readLine()) != null) {
+ str = str.trim();
+ if (!str.startsWith("#") && str.length() > 0) {
+ StringTokenizer tokenizer = new StringTokenizer(str, "=");
+ if (tokenizer.hasMoreTokens()) {
+ String name = tokenizer.nextToken();
+ String val = null;
+ if (tokenizer.countTokens() > 0)
+ val = tokenizer.nextToken();
+ if (name.equals("host")) {
+ host = val;
+ } else if (name.equals("port")) {
+ portstr = val;
+ } else if (name.equals("secure")) {
+ secure = val;
+ } else if (name.equals("dbdir")) {
+ dbdir = val;
+ } else if (name.equals("nickname")) {
+ nickname = val;
+ } else if (name.equals("password")) {
+ password = val;
+ } else if (name.equals("output")) {
+ ofilename = val;
+ } else if (name.equals("input")) {
+ ifilename = val;
+ } else if (name.equals("clientmode")) {
+ clientmode = val;
+ } else if (name.equals("servlet")) {
+ servlet = val;
+ }
+ }
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ printUsage();
+ }
+
+ if (host == null) {
+ System.out.println("Missing host name.");
+ printUsage();
+ }
+
+ if (portstr == null) {
+ System.out.println("Missing port number.");
+ printUsage();
+ }
+
+ if (servlet == null) {
+ System.out.println("Missing servlet name.");
+ printUsage();
+ }
+
+ if (ifilename == null) {
+ System.out.println("Missing input filename for the enrollment request.");
+ printUsage();
+ }
+
+ if (ofilename == null) {
+ System.out.println("Missing output filename for the response.");
+ printUsage();
+ }
+
+ int port = Integer.parseInt(portstr);
+
+ if (secure != null && secure.equals("true")) {
+ if (dbdir == null) {
+ System.out.println("Missing directory name for the cert7.db.");
+ printUsage();
+ }
+
+ if (clientmode != null && clientmode.equals("true")) {
+ if (password == null) {
+ System.out.println("Missing password for the cert7.db.");
+ printUsage();
+ }
+ if (nickname == null) {
+ System.out.println("Missing nickname for the client certificate");
+ printUsage();
+ }
+ }
+ }
+
+ try {
+ HttpClient client =
+ new HttpClient(host, port, secure);
+ client.send(ifilename, ofilename, dbdir, nickname, password, servlet, clientmode);
+ } catch (Exception e) {
+ System.out.println("Error: " + e.toString());
+ }
+ }
+
+ class ClientHandshakeCB implements SSLHandshakeCompletedListener {
+ Object sc;
+
+ public ClientHandshakeCB(Object sc) {
+ this.sc = sc;
+ }
+
+ public void handshakeCompleted(SSLHandshakeCompletedEvent event) {
+ System.out.println("handshake happened");
+ }
+ }
+}
diff --git a/pki/base/java-tools/src/com/netscape/cmstools/OCSPClient.java b/pki/base/java-tools/src/com/netscape/cmstools/OCSPClient.java
new file mode 100644
index 000000000..30e033926
--- /dev/null
+++ b/pki/base/java-tools/src/com/netscape/cmstools/OCSPClient.java
@@ -0,0 +1,270 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmstools;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import java.security.*;
+
+import org.mozilla.jss.*;
+import org.mozilla.jss.util.*;
+import org.mozilla.jss.asn1.*;
+import org.mozilla.jss.pkix.primitive.*;
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.crypto.*;
+import org.mozilla.jss.CertDatabaseException;
+import org.mozilla.jss.pkcs11.*;
+import org.mozilla.jss.pkcs11.PK11Token;
+
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509Key;
+import netscape.security.x509.X500Name;
+
+import com.netscape.cmsutil.ocsp.*;
+import com.netscape.cmsutil.ocsp.Request;
+
+
+/**
+ * This class implements a OCSP client for testing.
+ *
+ * @version $Revision$, $Date$
+ */
+public class OCSPClient
+{
+ private String _host = null;
+ private int _port = 0;
+
+ public OCSPClient(String host, int port, String dbdir)
+ throws Exception
+ {
+ _host = host;
+ _port = port;
+ CryptoManager.initialize(dbdir);
+ }
+
+ public void send(String uri, String nickname, int serialno, String output)
+ throws Exception
+ {
+ CryptoManager manager = CryptoManager.getInstance();
+ X509Certificate caCert = manager.findCertByNickname(nickname);
+ OCSPRequest request = getOCSPRequest(caCert, serialno);
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ request.encode(os);
+ byte request_data[] = os.toByteArray();
+ sendOCSPRequest(uri, _host, _port, request_data, output);
+ }
+
+ public void sendRequestData(String uri, String nickname, byte request_data[], String output)
+ throws Exception
+ {
+ sendOCSPRequest(uri, _host, _port, request_data, output);
+ }
+
+ public OCSPRequest getOCSPRequest(X509Certificate caCert, int serialno)
+ throws Exception
+ {
+ MessageDigest md = MessageDigest.getInstance("SHA");
+
+ // calculate issuer key hash
+ X509CertImpl x509Cert = new X509CertImpl(caCert.getEncoded());
+ X509Key x509key = (X509Key)x509Cert.getPublicKey();
+ byte issuerKeyHash[] = md.digest(x509key.getKey());
+
+ // calculate name hash
+ X500Name name = (X500Name)x509Cert.getSubjectDN();
+ byte issuerNameHash[] = md.digest(name.getEncoded());
+ // constructing the OCSP request
+ CertID certid = new CertID(
+ new AlgorithmIdentifier(
+ new OBJECT_IDENTIFIER("1.3.14.3.2.26"), new NULL()),
+ new OCTET_STRING(issuerNameHash),
+ new OCTET_STRING(issuerKeyHash),
+ new INTEGER(serialno));
+ Request request = new Request(certid, null);
+ SEQUENCE requestList = new SEQUENCE();
+ requestList.addElement(request);
+ TBSRequest tbsRequest = new TBSRequest(null,null,requestList,null);
+ return new OCSPRequest(tbsRequest, null);
+ }
+
+ public void sendOCSPRequest(String uri, String host, int port,
+ byte request_data[], String output) throws Exception
+ {
+ Socket socket = new Socket(host, port);
+
+ // send request
+ System.out.println("URI: " + uri);
+
+ DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
+ dos.writeBytes("POST " + uri + " HTTP/1.0\r\n");
+ dos.writeBytes("Content-length: " + request_data.length + "\r\n");
+ dos.writeBytes("\r\n");
+ dos.write(request_data);
+ dos.flush();
+
+ System.out.println("Data Length: " + request_data.length);
+ System.out.println("Data: " + com.netscape.osutil.OSUtil.BtoA(request_data));
+
+ InputStream iiss = socket.getInputStream();
+ FileOutputStream fof = new FileOutputStream(output);
+ boolean startSaving = false;
+ int sum = 0;
+ boolean hack = false;
+ try {
+ while (true)
+ {
+ int r = iiss.read();
+ if (r == -1)
+ break;
+ if (r == 10) {
+ sum++;
+ }
+ if (sum == 6) {
+ startSaving = true;
+ continue;
+ }
+ if (startSaving) {
+ if (hack) {
+ fof.write(r);
+ }
+ if (hack == false) {
+ hack = true;
+ }
+ }
+ } // while
+ } catch (IOException e) {
+ }
+ fof.close();
+
+ // parse OCSPResponse
+ BufferedInputStream fis =
+ new BufferedInputStream(
+ new FileInputStream(output));
+ OCSPResponse resp = (OCSPResponse)
+ OCSPResponse.getTemplate().decode(fis);
+ OCSPResponseStatus status = resp.getResponseStatus();
+ ResponseBytes bytes = resp.getResponseBytes();
+ BasicOCSPResponse basic = (BasicOCSPResponse)
+ BasicOCSPResponse.getTemplate().decode(
+ new ByteArrayInputStream(bytes.getResponse().toByteArray()));
+ ResponseData rd = basic.getResponseData();
+ for (int i = 0; i < rd.getResponseCount(); i++) {
+ SingleResponse rd1 = rd.getResponseAt(i);
+ System.out.println("CertID.serialNumber=" +
+ rd1.getCertID().getSerialNumber());
+ CertStatus status1 = rd1.getCertStatus();
+ if (status1 instanceof GoodInfo) {
+ System.out.println("CertStatus=Good");
+ }
+ if (status1 instanceof UnknownInfo) {
+ System.out.println("CertStatus=Unknown");
+ }
+ if (status1 instanceof RevokedInfo) {
+ System.out.println("CertStatus=Revoked");
+ }
+ }
+ }
+
+ public static void printUsage()
+ {
+ System.out.println("Usage: OCSPClient " +
+ "<host> <port> <dbdir> <nickname> <serialno_or_filename> <output> <times>");
+ System.out.println(" <host> = OCSP server hostname");
+ System.out.println(" <port> = OCSP server port number");
+ System.out.println(" <dbdir> = Certificate Database Directory");
+ System.out.println(" <nickname> = Nickname of CA Certificate");
+ System.out.println(" <serialno_or_filename> = Serial Number Being Checked, Or Name of file that contains the request");
+ System.out.println(" <output> = Filename of Response in DER encoding");
+ System.out.println(" <times> = Submit Request Multiple Times");
+ System.out.println(" [<uri>] = OCSP Service URI (i.e. /ocsp/ee/ocsp)");
+ }
+
+ public static void main(String args[])
+ {
+ if (args.length != 7 && args.length !=8 )
+ {
+ System.out.println("ERROR: Invalid number of arguments - got "
+ + args.length + " expected 7!");
+ for (int i = 0; i < args.length; i++) {
+ System.out.println("arg[" + i + "]=" + args[i]);
+ }
+ printUsage();
+ System.exit(0);
+ }
+
+ String host = args[0];
+ int port = -1;
+ try {
+ port = Integer.parseInt(args[1]);
+ } catch (Exception e) {
+ System.out.println("Error: Invalid Port Number");
+ printUsage();
+ System.exit(0);
+ }
+ String dbdir = args[2];
+ String nickname = args[3];
+ int serialno = -1;
+ byte data[] = null;
+ try {
+ serialno = Integer.parseInt(args[4]);
+ } catch (Exception e) {
+ try {
+ System.out.println("Warning: Serial Number not found. It may be a filename.");
+ /* it could be a file name */
+ FileInputStream fis = new FileInputStream(args[4]);
+ System.out.println("File Size: " + fis.available());
+ data = new byte[fis.available()];
+ fis.read(data);
+ } catch (Exception e1) {
+ System.out.println("Error: Invalid Serial Number or File Name");
+ printUsage();
+ System.exit(0);
+ }
+ }
+ String output = args[5];
+ int times = 1;
+ try {
+ times = Integer.parseInt(args[6]);
+ } catch (Exception e) {
+ System.out.println("Error: Invalid Times");
+ printUsage();
+ System.exit(0);
+ }
+ String uri = "/ocsp/ee/ocsp";
+ if (args.length > 7) {
+ uri = args[7];
+ }
+ try {
+ OCSPClient client =
+ new OCSPClient(host, port, dbdir);
+ for (int i = 0; i < times; i ++) {
+ if (data != null) {
+ client.sendRequestData(uri, nickname, data, output);
+ } else {
+ client.send(uri, nickname, serialno, output);
+ }
+ }
+ System.out.println("Success: Output " + output);
+ } catch (Exception e) {
+ System.out.println("Error: " + e.toString());
+ printUsage();
+ System.exit(0);
+ }
+ }
+}
diff --git a/pki/base/java-tools/src/com/netscape/cmstools/PKCS10Client.java b/pki/base/java-tools/src/com/netscape/cmstools/PKCS10Client.java
new file mode 100644
index 000000000..150fe5105
--- /dev/null
+++ b/pki/base/java-tools/src/com/netscape/cmstools/PKCS10Client.java
@@ -0,0 +1,269 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmstools;
+
+import java.util.Date;
+import java.util.StringTokenizer;
+import java.net.URL;
+import java.net.URLConnection;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.BufferedReader;
+import java.io.PrintStream;
+import java.io.File;
+import java.io.FileOutputStream;
+
+import java.net.URLEncoder;
+import java.security.KeyPair;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import org.mozilla.jss.util.Password;
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.crypto.CryptoToken;
+import org.mozilla.jss.pkcs10.*;
+import org.mozilla.jss.crypto.KeyPairGenerator;
+import org.mozilla.jss.crypto.KeyPairAlgorithm;
+//import netscape.security.provider.RSAPublicKey;
+import netscape.security.pkcs.PKCS10;
+//import java.security.Signature;
+import netscape.security.x509.X500Name;
+import netscape.security.util.BigInt;
+import netscape.security.x509.X500Signer;
+import java.io.ByteArrayOutputStream;
+
+import org.mozilla.jss.crypto.*;
+import org.mozilla.jss.asn1.*;
+import org.mozilla.jss.pkix.primitive.*;
+import org.mozilla.jss.pkix.crmf.*;
+import com.netscape.cmsutil.util.*;
+
+
+/**
+ * Generates a 1024-bit RSA key pair in the security database, constructs a
+ * PKCS#10 certificate request with the public key, and outputs the request
+ * to a file.
+ * <p>
+ * PKCS #10 is a certification request syntax standard defined by RSA. A CA
+ * may support multiple types of certificate requests. The Certificate System
+ * CA supports KEYGEN, PKCS#10, CRMF, and CMC.
+ * <p>
+ * To get a certificate from the CA, the certificate request needs to be
+ * submitted to and approved by a CA agent. Once approved, a certificate is
+ * created for the request, and certificate attributes, such as extensions,
+ * are populated according to certificate profiles.
+ * <p>
+ * @version $Revision$, $Date$
+ */
+public class PKCS10Client
+{
+
+ private static void printUsage() {
+ System.out.println("Usage: PKCS10Client -p <certdb password> -d <location of certdb> -o <output file which saves the base64 PKCS10> -s <subjectDN>\n");
+ }
+
+ public static void main(String args[])
+ {
+ String dbdir = null, ofilename = null, password = null, subjectName = null;
+
+ if (args.length != 8) {
+ printUsage();
+ System.exit(1);
+ }
+
+ for (int i=0; i<args.length; i++) {
+ String name = args[i];
+ if (name.equals("-p")) {
+ password = args[i+1];
+ } else if (name.equals("-d")) {
+ dbdir = args[i+1];
+ } else if (name.equals("-o")) {
+ ofilename = args[i+1];
+ } else if (name.equals("-s")) {
+ subjectName = args[i+1];
+ }
+ }
+
+ if (password == null || ofilename == null || subjectName == null) {
+ System.out.println("Illegal input parameters.");
+ printUsage();
+ System.exit(1);
+ }
+
+ if (dbdir == null)
+ dbdir = ".";
+
+ try {
+ // initialize CryptoManager
+ if (dbdir == null)
+ dbdir = ".";
+ String mPrefix = "";
+ CryptoManager.InitializationValues vals =
+ new CryptoManager.InitializationValues(dbdir, mPrefix,
+ mPrefix, "secmod.db");
+
+ CryptoManager.initialize(vals);
+ CryptoManager cm = CryptoManager.getInstance();
+ CryptoToken token = cm.getInternalKeyStorageToken();
+ Password pass = new Password(password.toCharArray());
+
+ token.login(pass);
+ KeyPairGenerator kg = token.getKeyPairGenerator(KeyPairAlgorithm.RSA);
+ kg.initialize(1024);
+ KeyPair pair = kg.genKeyPair();
+
+ // Add idPOPLinkWitness control
+ String secretValue = "testing";
+ byte[] key1 = null;
+ byte[] finalDigest = null;
+ MessageDigest SHA1Digest = MessageDigest.getInstance("SHA1");
+ key1 = SHA1Digest.digest(secretValue.getBytes());
+
+/* seed */
+byte[] b =
+{0x10, 0x53, 0x42, 0x24, 0x1a, 0x2a, 0x35, 0x3c,
+ 0x7a, 0x52, 0x54, 0x56, 0x71, 0x65, 0x66, 0x4c,
+ 0x51, 0x34, 0x35, 0x23, 0x3c, 0x42, 0x43, 0x45,
+ 0x61, 0x4f, 0x6e, 0x43, 0x1e, 0x2a, 0x2b, 0x31,
+ 0x32, 0x34, 0x35, 0x36, 0x55, 0x51, 0x48, 0x14,
+ 0x16, 0x29, 0x41, 0x42, 0x43, 0x7b, 0x63, 0x44,
+ 0x6a, 0x12, 0x6b, 0x3c, 0x4c, 0x3f, 0x00, 0x14,
+ 0x51, 0x61, 0x15, 0x22, 0x23, 0x5f, 0x5e, 0x69};
+
+ HMACDigest hmacDigest = new HMACDigest(SHA1Digest, key1);
+ hmacDigest.update(b);
+ finalDigest = hmacDigest.digest();
+
+ OCTET_STRING ostr = new OCTET_STRING(finalDigest);
+ Attribute attr = new Attribute(OBJECT_IDENTIFIER.id_cmc_idPOPLinkWitness, ostr);
+
+ SET attributes = new SET();
+ attributes.addElement(attr);
+ Name n = getJssName(subjectName);
+ SubjectPublicKeyInfo subjectPub = new SubjectPublicKeyInfo(pair.getPublic());
+ CertificationRequestInfo certReqInfo =
+ new CertificationRequestInfo(new INTEGER(0), n, subjectPub, attributes);
+ CertificationRequest certRequest = new CertificationRequest(certReqInfo,
+ pair.getPrivate(), SignatureAlgorithm.RSASignatureWithMD5Digest);
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ certRequest.encode(bos);
+ byte[] bb = bos.toByteArray();
+
+ String b64E = com.netscape.osutil.OSUtil.BtoA(bb);
+
+ System.out.println("");
+ System.out.println(b64E);
+ System.out.println("");
+
+ PrintStream ps = null;
+ ps = new PrintStream(new FileOutputStream(ofilename));
+ ps.println(b64E);
+ ps.flush();
+ ps.close();
+ } catch (Exception e) {
+ }
+ }
+
+ static Name getJssName(String dn)
+ {
+
+ X500Name x5Name = null;
+
+ try {
+ x5Name= new X500Name(dn);
+ } catch(IOException e) {
+
+ System.out.println("Illegal Subject Name: " + dn + " Error: " + e.toString());
+ System.out.println("Filling in default Subject Name......");
+ return null;
+ }
+
+ Name ret = new Name();
+ netscape.security.x509.RDN[] names = null;
+ names = x5Name.getNames();
+ int nameLen = x5Name.getNamesLength();
+
+ netscape.security.x509.RDN cur = null;
+
+ for(int i = 0; i < nameLen ; i++)
+ {
+ cur = names[i];
+ String rdnStr = cur.toString();
+ String[] split = rdnStr.split("=");
+
+ if(split.length != 2)
+ continue;
+
+ try {
+ if(split[0].equals("UID"))
+ {
+ ret.addElement(new AVA(new OBJECT_IDENTIFIER("0.9.2342.19200300.100.1.1"), new PrintableString(split[1])));
+ // System.out.println("UID found : " + split[1]);
+ }
+
+ if(split[0].equals("C"))
+ {
+ ret.addCountryName(split[1]);
+ // System.out.println("C found : " + split[1]);
+ continue;
+ }
+
+ if(split[0].equals("CN"))
+ {
+ ret.addCommonName(split[1]);
+ // System.out.println("CN found : " + split[1]);
+ continue;
+ }
+
+ if(split[0].equals("L"))
+ {
+ ret.addLocalityName(split[1]);
+ // System.out.println("L found : " + split[1]);
+ continue;
+ }
+
+ if(split[0].equals("O"))
+ {
+ ret.addOrganizationName(split[1]);
+ // System.out.println("O found : " + split[1]);
+ continue;
+ }
+
+ if(split[0].equals("ST"))
+ {
+ ret.addStateOrProvinceName(split[1]);
+ // System.out.println("ST found : " + split[1]);
+ continue;
+ }
+
+ if(split[0].equals("OU"))
+ {
+ ret.addOrganizationalUnitName(split[1]);
+ // System.out.println("OU found : " + split[1]);
+ continue;
+ }
+ } catch (Exception e) {
+ System.out.println("Error constructing RDN: " + rdnStr + " Error: " + e.toString());
+ continue;
+ }
+ }
+
+ return ret;
+ }
+}
diff --git a/pki/base/java-tools/src/com/netscape/cmstools/PKCS12Export.java b/pki/base/java-tools/src/com/netscape/cmstools/PKCS12Export.java
new file mode 100644
index 000000000..61058776f
--- /dev/null
+++ b/pki/base/java-tools/src/com/netscape/cmstools/PKCS12Export.java
@@ -0,0 +1,301 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmstools;
+
+
+import org.mozilla.jss.pkix.cmc.*;
+import org.mozilla.jss.pkix.cms.*;
+import org.mozilla.jss.pkix.cert.*;
+import org.mozilla.jss.pkix.primitive.*;
+import org.mozilla.jss.asn1.*;
+import org.mozilla.jss.pkcs10.*;
+import org.mozilla.jss.pkcs11.*;
+import org.mozilla.jss.pkcs12.*;
+import org.mozilla.jss.crypto.*;
+import org.mozilla.jss.pkix.crmf.*;
+import org.mozilla.jss.pkix.cmmf.*;
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.crypto.CryptoToken;
+import org.mozilla.jss.crypto.SignatureAlgorithm;
+import org.mozilla.jss.crypto.DigestAlgorithm;
+import org.mozilla.jss.crypto.X509Certificate;
+import org.mozilla.jss.util.*;
+
+import org.mozilla.jss.*;
+
+import netscape.security.util.*;
+import netscape.security.x509.*;
+import netscape.security.pkcs.PKCS10;
+
+import java.security.*;
+import java.security.cert.CertificateException;
+import java.math.*;
+import java.security.Principal;
+import java.lang.*;
+import java.lang.reflect.*;
+import java.io.*;
+import java.util.*;
+
+import com.netscape.cmsutil.util.*;
+
+
+/**
+ * Tool for creating PKCS12 file
+ *
+ * <P>
+ * @version $Revision$, $Date$
+ *
+ */
+public class PKCS12Export {
+
+ private static boolean debugMode = false;
+
+ private static void debug(String s) {
+ if (debugMode)
+ System.out.println("PKCS12Export debug: " + s);
+ }
+
+ private static void printUsage() {
+ System.out.println("Usage: PKCS12Export -d <cert/key db directory> -p <file containing password for keydb> -w <file containing pkcs12 password> -o <output file for pkcs12>");
+ System.out.println("");
+ System.out.println("If you want to turn on debug, do the following:");
+ System.out.println("Usage: PKCS12Export -debug -d <cert/key db directory> -p <file containing password for keydb> -w <file containing pkcs12 password> -o <output file for pkcs12>");
+ }
+
+ private static byte[] getEncodedKey(org.mozilla.jss.crypto.PrivateKey pkey) {
+ try {
+ CryptoManager cm = CryptoManager.getInstance();
+ CryptoToken token = cm.getInternalKeyStorageToken();
+ KeyGenerator kg = token.getKeyGenerator(KeyGenAlgorithm.DES3);
+ SymmetricKey sk = kg.generate();
+ KeyWrapper wrapper = token.getKeyWrapper(KeyWrapAlgorithm.DES3_CBC_PAD);
+ byte iv[] = {0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1};
+ IVParameterSpec param = new IVParameterSpec(iv);
+ wrapper.initWrap(sk, param);
+ byte[] enckey = wrapper.wrap(pkey);
+ Cipher c = token.getCipherContext(EncryptionAlgorithm.DES3_CBC_PAD);
+ c.initDecrypt(sk, param);
+ byte[] recovered = c.doFinal(enckey);
+ return recovered;
+ } catch (Exception e) {
+ debug("PKCS12Export getEncodedKey: Exception="+e.toString());
+ System.exit(1);
+ }
+
+ return null;
+ }
+
+ private static void addKeyBag(org.mozilla.jss.crypto.PrivateKey pkey, X509Certificate x509cert,
+ Password pass, byte[] localKeyId, SEQUENCE safeContents) {
+ try {
+ PasswordConverter passConverter = new PasswordConverter();
+ byte salt[] = {0x01, 0x01, 0x01, 0x01};
+ byte[] priData = getEncodedKey(pkey);
+
+ PrivateKeyInfo pki = (PrivateKeyInfo)
+ ASN1Util.decode(PrivateKeyInfo.getTemplate(), priData);
+ ASN1Value key = EncryptedPrivateKeyInfo.createPBE(
+ PBEAlgorithm.PBE_SHA1_DES3_CBC,
+ pass, salt, 1, passConverter, pki);
+ SET keyAttrs = createBagAttrs(
+ x509cert.getSubjectDN().toString(), localKeyId);
+ SafeBag keyBag = new SafeBag(SafeBag.PKCS8_SHROUDED_KEY_BAG,
+ key, keyAttrs);
+ safeContents.addElement(keyBag);
+ } catch (Exception e) {
+ debug("PKCS12Export addKeyBag: Exception="+e.toString());
+ System.exit(1);
+ }
+ }
+
+ private static byte[] addCertBag(X509Certificate x509cert, String nickname,
+ SEQUENCE safeContents) throws IOException {
+ byte[] localKeyId = null;
+ try {
+ ASN1Value cert = new OCTET_STRING(x509cert.getEncoded());
+ localKeyId = createLocalKeyId(x509cert);
+ SET certAttrs = null;
+ if (nickname != null)
+ certAttrs = createBagAttrs(nickname, localKeyId);
+ SafeBag certBag = new SafeBag(SafeBag.CERT_BAG,
+ new CertBag(CertBag.X509_CERT_TYPE, cert), certAttrs);
+ safeContents.addElement(certBag);
+ } catch (Exception e) {
+ debug("PKCS12Export addCertBag: "+e.toString());
+ System.exit(1);
+ }
+
+ return localKeyId;
+ }
+
+ private static byte[] createLocalKeyId(X509Certificate cert) {
+ try {
+ // SHA1 hash of the X509Cert der encoding
+ byte certDer[] = cert.getEncoded();
+
+ MessageDigest md = MessageDigest.getInstance("SHA");
+
+ md.update(certDer);
+ return md.digest();
+ } catch (Exception e) {
+ debug("PKCS12Export createLocalKeyId: Exception: "+e.toString());
+ System.exit(1);
+ }
+
+ return null;
+ }
+
+ private static SET createBagAttrs(String nickName, byte localKeyId[])
+ throws IOException {
+ try {
+ SET attrs = new SET();
+ SEQUENCE nickNameAttr = new SEQUENCE();
+
+ nickNameAttr.addElement(SafeBag.FRIENDLY_NAME);
+ SET nickNameSet = new SET();
+
+ nickNameSet.addElement(new BMPString(nickName));
+ nickNameAttr.addElement(nickNameSet);
+ attrs.addElement(nickNameAttr);
+ SEQUENCE localKeyAttr = new SEQUENCE();
+
+ localKeyAttr.addElement(SafeBag.LOCAL_KEY_ID);
+ SET localKeySet = new SET();
+
+ localKeySet.addElement(new OCTET_STRING(localKeyId));
+ localKeyAttr.addElement(localKeySet);
+ attrs.addElement(localKeyAttr);
+ return attrs;
+ } catch (Exception e) {
+ debug("PKCS12Export createBagAttrs: Exception="+e.toString());
+ System.exit(1);
+ }
+
+ return null;
+ }
+
+ public static void main(String args[]) {
+ if (args.length < 8) {
+ printUsage();
+ System.exit(1);
+ }
+
+ String pwdfile = null;
+ String dir = null;
+ String snickname = null;
+ String pk12pwdfile = null;
+ String pk12output = null;
+ for (int i=0; i<args.length; i++) {
+ if (args[i].equals("-d")) {
+ dir = args[i+1];
+ } else if (args[i].equals("-p")) {
+ pwdfile = args[i+1];
+ } else if (args[i].equals("-s")) {
+ snickname = args[i+1];
+ } else if (args[i].equals("-w")) {
+ pk12pwdfile = args[i+1];
+ } else if (args[i].equals("-o")) {
+ pk12output = args[i+1];
+ } else if (args[i].equals("-debug")) {
+ debugMode = true;
+ }
+ }
+
+ debug("The directory for certdb/keydb is "+dir);
+ debug("The password file for keydb is "+pwdfile);
+
+ // get password
+ String pwd = null;
+ try {
+ BufferedReader in = new BufferedReader(new FileReader(pwdfile));
+ pwd = in.readLine();
+ } catch (Exception e) {
+ debug("Failed to read the keydb password from the file. Exception: "+e.toString());
+ System.exit(1);
+ }
+
+ String pk12pwd = null;
+ try {
+ BufferedReader in = new BufferedReader(new FileReader(pk12pwdfile));
+ pk12pwd = in.readLine();
+ } catch (Exception e) {
+ debug("Failed to read the keydb password from the file. Exception: "+e.toString());
+ System.exit(1);
+ }
+
+ CryptoManager cm = null;
+ try {
+ CryptoManager.InitializationValues vals =
+ new CryptoManager.InitializationValues(dir, "", "", "secmod.db");
+ CryptoManager.initialize(vals);
+ cm = CryptoManager.getInstance();
+ } catch (Exception e) {
+ debug("Failed to initialize the certdb.");
+ System.exit(1);
+ }
+
+ SEQUENCE encSafeContents = new SEQUENCE();
+ SEQUENCE safeContents = new SEQUENCE();
+ try {
+ CryptoToken token = cm.getInternalKeyStorageToken();
+ Password pass = new Password(pwd.toCharArray());
+ token.login(pass);
+ CryptoStore store = token.getCryptoStore();
+ X509Certificate[] certs = store.getCertificates();
+ debug("Number of user certificates = "+certs.length);
+ Password pass12 = new Password(pk12pwd.toCharArray());
+ for (int i=0; i<certs.length; i++) {
+ String nickname = certs[i].getNickname();
+ debug("Certificate nickname = "+nickname);
+ org.mozilla.jss.crypto.PrivateKey prikey = null;
+ try {
+ prikey = cm.findPrivKeyByCert(certs[i]);
+ } catch (Exception e) {
+ debug("PKCS12Export Exception: "+e.toString());
+ }
+
+ if (prikey == null) {
+ debug("Private key is null");
+ byte[] localKeyId = addCertBag(certs[i], null, safeContents);
+ } else {
+ debug("Private key is not null");
+ byte localKeyId[] =
+ addCertBag(certs[i], nickname, safeContents);
+ addKeyBag(prikey, certs[i], pass12, localKeyId, encSafeContents);
+ }
+ }
+
+ AuthenticatedSafes authSafes = new AuthenticatedSafes();
+ authSafes.addSafeContents(safeContents);
+ authSafes.addSafeContents(encSafeContents);
+ PFX pfx = new PFX(authSafes);
+ pfx.computeMacData(pass12, null, 5);
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ pfx.encode(bos);
+ FileOutputStream fos = new FileOutputStream(pk12output);
+ fos.write(bos.toByteArray());
+ fos.flush();
+ fos.close();
+ pass.clear();
+ pass12.clear();
+ } catch (Exception e) {
+ debug("PKCS12Export Exception: "+e.toString());
+ System.exit(1);
+ }
+ }
+}
diff --git a/pki/base/java-tools/src/com/netscape/cmstools/PasswordCache.java b/pki/base/java-tools/src/com/netscape/cmstools/PasswordCache.java
new file mode 100644
index 000000000..259fbf914
--- /dev/null
+++ b/pki/base/java-tools/src/com/netscape/cmstools/PasswordCache.java
@@ -0,0 +1,879 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmstools;
+
+
+import java.lang.*;
+import java.lang.reflect.*;
+import java.io.*;
+import java.util.*;
+import org.mozilla.jss.util.*;
+import org.mozilla.jss.asn1.*;
+import org.mozilla.jss.*;
+import org.mozilla.jss.crypto.*;
+import org.mozilla.jss.SecretDecoderRing.KeyManager;
+import org.mozilla.jss.SecretDecoderRing.Encryptor;
+import org.mozilla.jss.SecretDecoderRing.Decryptor;
+import org.mozilla.jss.util.Base64OutputStream;
+
+/**
+ * Tool for interacting with the PWcache
+ *
+ * @version $Revision$, $Date$
+ */
+
+public class PasswordCache {
+
+ /* These are the tags that identify various passwords
+ * They should probably be converted instances of some
+ * class so that we can expose an API to add additional
+ * TAG's for use if I want to add a password for use
+ * with my own authenticaion module
+ */
+ public static final String PROP_PWC_NICKNAME = "sso_key";
+ public static final String PW_TAG_INTERNAL_LDAP_DB = "Internal LDAP Database";
+ private static final String WRONG_NUM_ARGS = "Error: wrong number of arguments";
+ private static final String CERTDB = "cert8.db";
+ private static final String KEYDB = "key3.db";
+
+ private static void usage() {
+ System.out.println("This tool has to be run from the same directory where pwcache.db file resides, normally <cms instance>/config directory, unless the file's full path is specified in the -c option..\nUsage: PasswordCache <SSO_PASSWORD> <-d cert/key db directory> <-h tokenName> <-P cert/key db prefix> <-c pwcache.db_file_full_path> <-k file containing Base64EncodedKeyID> <COMMAND> ...");
+ System.out.println(" commands:");
+ System.out.println(" 'add <password_name> <password>'");
+ System.out.println(" 'change <password_name> <password>'");
+ System.out.println(" 'delete <password_name>'");
+ System.out.println(" 'rekey'");
+ System.out.println(" 'list'");
+ System.out.println("\nExample:\n\tPasswordCache thePassword1 -d /usr/netscape/servers/cms/alias -P cert-instance1-machine1- -c pwcache.db -k keyidFile list");
+ System.exit(1);
+ }
+
+ private static boolean debugMode = false;
+
+ public PasswordCache() {
+ }
+
+ private static void debug (String s) {
+ if (debugMode == true)
+ System.out.println("PasswordCache debug: "+s);
+ }
+
+ /**
+ * clean up an argv by removing the trailing, empty arguments
+ *
+ * This is necessary to support the script wrapper which calls the
+ * tool with arguments in quotes such as:
+ * "$1" "$2"
+ * if $2 is not specified, the empty arg "" gets passed, which causes
+ * an error in the arg-count checking code.
+ */
+ private static String[] cleanArgs(String[] s) {
+ int length;
+ int i;
+
+ length = s.length;
+ debug("before cleanArgs argv length ="+length);
+
+ for (i = length - 1; i >= 0; i--) {
+ if (s[i].equals("")) {
+ length--;
+ } else {
+ break;
+ }
+ }
+
+ String[] new_av = new String[length];
+ for (i = 0; i < length; i++) {
+ new_av[i] = s[i];
+ debug("arg "+i+" is "+new_av[i]);
+ }
+ debug("after cleanArgs argv length ="+length);
+
+ return new_av;
+ }
+
+ public static byte[] base64Decode(String s) throws IOException {
+ byte[] d = com.netscape.osutil.OSUtil.AtoB(s);
+ return d;
+ }
+
+ public static String base64Encode(byte[] bytes) throws IOException {
+ // All this streaming is lame, but Base64OutputStream needs a
+ // PrintStream
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ Base64OutputStream b64 = new Base64OutputStream(new
+ PrintStream(new
+ FilterOutputStream(output)
+ )
+ );
+
+ b64.write(bytes);
+ b64.flush();
+
+ // This is internationally safe because Base64 chars are
+ // contained within 8859_1
+ return output.toString("8859_1");
+ }
+
+ public static void main(String[]av) {
+ // default path is "."
+ String mPath = ".";
+ String mTokenName = null;
+ // default prefix is ""
+ String mPrefix = "";
+ String mKeyIdString = null;
+ byte[] mKeyId = null;
+ String mCertDB = CERTDB;
+ String mKeyDB = KEYDB;
+ String mCacheFile = "pwcache.db";
+
+ String pwdPath = null;
+ String instancePath = null;
+ String instanceName = null;
+
+ String[] argv = cleanArgs(av);
+
+ if (argv.length < 2) {
+ usage();
+ }
+
+ String pw = argv[0];
+
+ char[] testpw = pw.toCharArray();
+ Password pass = new Password(testpw);
+
+ String command = "";
+ String aTag = "";
+ String aPasswd = "";
+
+ int i = 0;
+ for ( i = 1; i < argv.length; ++i) {
+ if( argv[i].equals("-d") ) {
+ if( ++i >= argv.length ) usage();
+ mPath = argv[i];
+ } else if( argv[i].equals("-h") ) {
+ if( ++i >= argv.length ) usage();
+ mTokenName = argv[i];
+ } else if( argv[i].equals("-P") ) {
+ if( ++i >= argv.length ) usage();
+ mPrefix = argv[i];
+ } else if( argv[i].equals("-c") ) {
+ if( ++i >= argv.length ) usage();
+ mCacheFile = argv[i];
+ } else if (argv[i].equals("-k") ) {
+ if( ++i >= argv.length ) usage();
+ String keyFile = argv[i];
+ try {
+ BufferedReader r = new BufferedReader(new FileReader(keyFile));
+ String listLine;
+ mKeyIdString = r.readLine();
+ } catch (Exception e) {
+ System.out.println("Error: "+e.toString());
+ System.exit(1);
+ }
+
+ if (mKeyIdString != null) {
+ try {
+ mKeyId = base64Decode(mKeyIdString);
+ debug("base64Decode of key id string successful");
+ } catch (IOException e) {
+ System.out.println("base64Decode of key id string failed");
+ System.exit(1);
+ }
+ }
+ } else {
+ command = argv[i++];
+ debug("command = "+command);
+
+ if ((command.equals("add")) ||
+ (command.equals("change"))) {
+ aTag = argv[i++];
+ aPasswd = argv[i];
+ debug("command is "+command+" "+aTag+":"+aPasswd);
+ } else if (command.equals("delete")) {
+ aTag = argv[i];
+ } else if (command.equals("list")) {
+ } else if (command.equals("rekey")) {
+ }
+ break;
+ }
+ }
+
+ try {
+ // initialize CryptoManager
+ System.out.println("cert/key prefix = " + mPrefix);
+ System.out.println("cert/key db path = " + mPath);
+ System.out.println("password cache file = " + mCacheFile);
+
+ CryptoManager.InitializationValues vals =
+ new CryptoManager.InitializationValues(mPath, mPrefix,
+ mPrefix, "secmod.db");
+
+ CryptoManager.initialize(vals);
+
+ CryptoManager cm = CryptoManager.getInstance();
+ CryptoToken token = null;
+ if (mTokenName == null) {
+ token = cm.getInternalKeyStorageToken();
+ System.out.println("token name = internal");
+ } else {
+ token = cm.getTokenByName(mTokenName);
+ System.out.println("token name = "+ mTokenName);
+ }
+
+ token.login(pass);
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.exit(1);
+ }
+
+ // generating new key
+ if (command.equals("rekey")) {
+ System.out.println("generating new key...");
+ PWsdrCache cache = null;
+ try {
+ // compose instance name
+ File passwordCacheDB = new File( mCacheFile );
+ pwdPath = passwordCacheDB.getAbsolutePath();
+ int beginIndex = pwdPath.lastIndexOf( "cert-" );
+ instancePath = pwdPath.substring( beginIndex );
+ int endIndex = 0;
+ endIndex = instancePath.lastIndexOf( "config" );
+ instanceName = instancePath.substring( 0, ( endIndex - 1 ) );
+
+ cache = new PWsdrCache(mCacheFile, mTokenName, null, true);
+ cache.deleteUniqueNamedKey( PROP_PWC_NICKNAME
+ + " "
+ + instanceName );
+ byte[] newKeyId = cache.generateSDRKeyWithNickName(
+ PROP_PWC_NICKNAME
+ + " "
+ + instanceName );
+ if (newKeyId != null) {
+ String newKeyIDString = base64Encode(newKeyId);
+ System.out.println("key generated successfully with key id = "+
+ newKeyIDString);
+ System.out.println("Save the VALUE portion of this key id in a local file,");
+ System.out.println("and under variable \"pwcKeyid\" in CS.cfg !!");
+ System.out.println("If you have not already done so,");
+ System.out.println("remove the old pwcache.db and use this local file to add passwords.");
+ // job is done
+ System.exit(0);
+ } else {
+ System.out.println("key expected to be generated but wasn't");
+ System.exit(1);
+ }
+ } catch (Exception e) {
+ System.out.println(e.toString());
+ System.exit(1);
+ }
+ }
+
+ PWsdrCache cache = null;
+ try {
+ cache = new PWsdrCache(mCacheFile, mTokenName, mKeyId, true);
+ } catch (Exception e) {
+ System.out.println(e.toString());
+ System.exit(1);
+ }
+
+ if ((command.equals("add")) || (command.equals("change"))) {
+ // current key id must be specified
+ if (mKeyId == null) {
+ System.out.println("operation failed: no key id specified");
+ System.exit(1);
+ }
+
+ try {
+ System.out.println("adding "+aTag+":"+aPasswd);
+ cache.addEntry(aTag, aPasswd);
+ } catch (Exception e) {
+ System.out.println("--failed--"+ e.toString());
+ }
+ } else if (command.equals("list")) {
+ cache.pprint();
+ } else if (command.equals("delete")) {
+ // current key id must be specified
+ if (mKeyId == null) {
+ System.out.println("operation failed: no key id specified");
+ System.exit(1);
+ }
+
+ try {
+ cache.deleteEntry(aTag);
+ } catch (Exception e) {
+ System.out.println("User not found");
+ }
+ } else {
+ System.out.println("Illegal command: " + command);
+ System.exit(1);
+ }
+ }
+
+ private static boolean badPassword(String pwd) {
+ // XXX - implement only password checking
+ return false;
+/*
+ PasswordChecker pwdChecker = new PasswordChecker();
+
+ if (!pwdChecker.isGoodPassword(pwd)) {
+ String reason = pwdChecker.getReason(pwd);
+
+ System.out.println("New password does not pass password " +
+ "quality test: " + reason);
+ return true;
+ } else {
+ return false;
+ }
+*/
+ }
+}
+
+
+/*
+ * A class for managing passwords in the SDR password cache
+ *
+ * @author Christina Fu
+ * @version $Revision$, $Date$
+ */
+class PWsdrCache {
+
+ public static final String PROP_PWC_NICKNAME = "sso_key";
+
+ private String mPWcachedb = null;
+ private byte[] mKeyID = null;
+ private String mTokenName = null;
+ private CryptoToken mToken = null;
+
+ // mTool tells if this is called from the PasswordCache tool
+ private boolean mIsTool = false;
+
+ // for PasswordCache tool (isTool == true)
+ public PWsdrCache(String pwCache, String pwcTokenname, byte[] keyId,
+ boolean isTool) throws Exception {
+ mPWcachedb = pwCache;
+ mIsTool = isTool;
+ mTokenName = pwcTokenname;
+ CryptoManager cm = null;
+
+ if (keyId != null) {
+ mKeyID = keyId;
+ }
+
+ cm = CryptoManager.getInstance();
+ if (mTokenName != null) {
+ mToken = cm.getTokenByName(mTokenName);
+ debug("PWsdrCache: mToken = "+mTokenName);
+ } else {
+ mToken = cm.getInternalKeyStorageToken();
+ debug("PWsdrCache: mToken = internal");
+ }
+ }
+
+ public byte[] getKeyId() {
+ return mKeyID;
+ }
+
+ public String getTokenName() {
+ return mTokenName;
+ }
+
+ public void deleteUniqueNamedKey( String nickName )
+ throws Exception
+ {
+ KeyManager km = new KeyManager( mToken );
+ km.deleteUniqueNamedKey( nickName );
+ }
+
+ public byte[] generateSDRKey() throws Exception {
+ return generateSDRKeyWithNickName(PROP_PWC_NICKNAME);
+ }
+
+ public byte[] generateSDRKeyWithNickName( String nickName )
+ throws Exception
+ {
+ try {
+ if (mIsTool == true) {
+ // generate SDR key
+ KeyManager km = new KeyManager(mToken);
+ try {
+ // Bugscape Bug #54838: Due to the CMS cloning feature,
+ // we must check for the presence of
+ // a uniquely named symmetric key
+ // prior to making an attempt to
+ // generate it!
+ //
+ if( !( km.uniqueNamedKeyExists( nickName ) ) ) {
+ mKeyID = km.generateUniqueNamedKey( nickName );
+ debug("PWsdrCache: SDR key generated");
+ }
+ } catch (TokenException e) {
+ log (0, "generateSDRKey() failed on "+e.toString());
+ throw e;
+ }
+ }
+ } catch (Exception e) {
+ log (0, e.toString());
+ throw e;
+ }
+ return mKeyID;
+ }
+
+ public void addEntry(String tag, String pwd) throws IOException {
+ addEntry(tag, pwd, (Hashtable) null);
+ }
+
+ /*
+ * Store passwd in pwcache.
+ */
+ public void addEntry(Hashtable ht) throws IOException {
+ addEntry((String) null, (String) null, ht);
+ }
+
+ /*
+ * add passwd in pwcache.
+ */
+ public void addEntry(String tag, String pwd, Hashtable tagPwds) throws IOException {
+ System.out.println("PWsdrCache: in addEntry");
+ String stringToAdd = null;
+ String bufs = null;
+
+ if (tagPwds == null) {
+ stringToAdd = tag + ":" + pwd + "\n";
+ } else {
+ Enumeration enum1 = tagPwds.keys();
+
+ while (enum1.hasMoreElements()) {
+ tag = (String) enum1.nextElement();
+ pwd = (String) tagPwds.get(tag);
+ debug("password tag: " + tag + " stored in " + mPWcachedb);
+
+ if (stringToAdd == null) {
+ stringToAdd = tag + ":" + pwd + "\n";
+ } else {
+ stringToAdd += tag + ":" + pwd + "\n";
+ }
+ }
+ }
+
+ String dcrypts = readPWcache();
+ System.out.println("PWsdrCache: after readPWcache()");
+ if (dcrypts != null) {
+ // converts to Hashtable, replace if tag exists, add
+ // if tag doesn't exist
+ Hashtable ht = string2Hashtable(dcrypts);
+
+ if (ht.containsKey(tag) == false) {
+ debug("adding new tag: " + tag);
+ ht.put(tag, pwd);
+ } else {
+ debug("replacing tag: " + tag);
+ ht.put(tag, pwd);
+ }
+ bufs = hashtable2String(ht);
+ } else {
+ debug("adding new tag: " + tag);
+ bufs = stringToAdd;
+ }
+
+ // write update to cache
+ writePWcache(bufs);
+ }
+
+ /*
+ * delete passwd in pwcache.
+ */
+ public void deleteEntry(String tag) throws IOException {
+ String bufs = null;
+
+ String dcrypts = readPWcache();
+
+ if (dcrypts != null) {
+ // converts to Hashtable, replace if tag exists, add
+ // if tag doesn't exist
+ Hashtable ht = string2Hashtable(dcrypts);
+
+ if (ht.containsKey(tag) == false) {
+ debug("tag: " + tag + " does not exist");
+ return;
+ } else {
+ debug("deleting tag: " + tag);
+ ht.remove(tag);
+ }
+ bufs = hashtable2String(ht);
+ } else {
+ debug("password cache contains no tags");
+ return;
+ }
+
+ // write update to cache
+ writePWcache(bufs);
+ }
+
+ /*
+ * reads and decrypts the pwcache.db content
+ */
+ public String readPWcache() throws IOException {
+ debug("about to read password cache");
+ String dcrypts = null;
+ if (mToken == null) {
+ debug("mToken is null");
+ throw new IOException("token must be specified");
+ }
+
+ Decryptor sdr = new Decryptor(mToken);
+
+ // not used, but could used for debugging
+ int totalRead = 0;
+ FileInputStream inputs = null;
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+
+ try {
+ // for SDR -> read, decrypt, append, and write
+ inputs = new FileInputStream(mPWcachedb);
+ byte[] readbuf = new byte[2048]; // for now
+ int numRead = 0;
+
+ while ((numRead = inputs.read(readbuf)) != -1) {
+ bos.write(readbuf, 0, numRead);
+ totalRead += numRead;
+ }
+ inputs.close();
+ } catch (FileNotFoundException e) {
+ System.out.println("Failed for file " + mPWcachedb + " " + e.toString());
+ throw new IOException(e.toString() + ": " + mPWcachedb);
+ } catch (IOException e) {
+ System.out.println("Failed for file " + mPWcachedb + " " + e.toString());
+ throw new IOException(e.toString() + ": " + mPWcachedb);
+ }
+
+ if (totalRead > 0) {
+ try {
+ // decrypt it first to append
+ byte[] dcryptb = sdr.decrypt(bos.toByteArray());
+
+ dcrypts = new String(dcryptb, "UTF-8");
+ } catch (TokenException e) {
+ System.out.println("password cache decrypto failed " + e.toString());
+ e.printStackTrace();
+ throw new IOException("password cache decrypt failed");
+ } catch (UnsupportedEncodingException e) {
+ System.out.println("password cache decrypto failed " + e.toString());
+ e.printStackTrace();
+ throw new IOException("password cache decrypt failed");
+ } catch (Exception e) {
+ System.out.println("password cache decrypto failed " + e.toString());
+ e.printStackTrace();
+ throw new IOException("password cache decrypt failed");
+ }
+ }
+
+ return dcrypts;
+ }
+
+ /*
+ * encrypts and writes the whole String buf into pwcache.db
+ */
+ public void writePWcache(String bufs) throws IOException {
+
+
+ try {
+ Encryptor sdr = new Encryptor(mToken, mKeyID,
+ Encryptor.DEFAULT_ENCRYPTION_ALG);
+
+ byte[] writebuf = null;
+
+ try {
+ // now encrypt it again
+ writebuf = sdr.encrypt(bufs.getBytes("UTF-8"));
+ } catch (Exception e) {
+ System.out.println("password cache encrypt failed " + e.toString());
+ e.printStackTrace();
+ throw new IOException("password cache encrypt failed");
+ }
+
+ File tmpPWcache = new File(mPWcachedb + ".tmp");
+
+ if (tmpPWcache.exists()) {
+ // it wasn't removed?
+ tmpPWcache.delete();
+ }
+ FileOutputStream outstream = new FileOutputStream(mPWcachedb + ".tmp");
+
+ outstream.write(writebuf);
+ outstream.close();
+
+ // Make certain that this temporary file has
+ // the correct permissions.
+ if( !isNT() ) {
+ exec( "chmod 00660 " + tmpPWcache.getAbsolutePath() );
+ }
+
+ File origFile = new File(mPWcachedb);
+
+ try {
+ // Always remove any pre-existing target file
+ if( origFile.exists() ) {
+ origFile.delete();
+ }
+
+ if (isNT()) {
+ // NT is very picky on the path
+ exec("copy " +
+ tmpPWcache.getAbsolutePath().replace('/', '\\') + " " +
+ origFile.getAbsolutePath().replace('/', '\\'));
+ } else {
+ // Create a copy of the temporary file which
+ // preserves the temporary file's permissions.
+ exec("cp -p " + tmpPWcache.getAbsolutePath() + " " +
+ origFile.getAbsolutePath());
+ }
+
+ // Remove the temporary file if and only if
+ // the "rename" was successful.
+ if( origFile.exists() ) {
+ tmpPWcache.delete();
+
+ // Make certain that the final file has
+ // the correct permissions.
+ if( !isNT() ) {
+ exec( "chmod 00660 " + origFile.getAbsolutePath() );
+ }
+
+ // report success
+ debug( "Renaming operation completed for " + mPWcachedb );
+ } else {
+ // report failure and exit
+ debug( "Renaming operation failed for " + mPWcachedb );
+ System.exit(1);
+ }
+ } catch (IOException exx) {
+ System.out.println("sdrPWcache: Error " + exx.toString());
+ throw new IOException(exx.toString() + ": " + mPWcachedb);
+ }
+ } catch (FileNotFoundException e) {
+ System.out.println("sdrPWcache: Error " + e.toString());
+ throw new IOException(e.toString() + ": " + mPWcachedb);
+ } catch (IOException e) {
+ System.out.println("Failed for file " + mPWcachedb + " " + e.toString());
+ throw new IOException(e.toString() + ": " + mPWcachedb);
+ } catch (Exception e) {
+ System.out.println("sdrPWcache: Error " + e.toString());
+ throw new IOException(e.toString());
+ }
+ }
+
+ public String hashtable2String(Hashtable ht) {
+ Enumeration enum1 = ht.keys();
+ String returnString = null;
+
+ while (enum1.hasMoreElements()) {
+ String tag = (String) enum1.nextElement();
+ String pwd = (String) ht.get(tag);
+
+ if (returnString == null) {
+ returnString = tag + ":" + pwd + "\n";
+ } else {
+ returnString += tag + ":" + pwd + "\n";
+ }
+ }
+ return returnString;
+ }
+
+ public Hashtable string2Hashtable(String cache) {
+ Hashtable ht = new Hashtable();
+
+ // first, break into lines
+ StringTokenizer st = new StringTokenizer(cache, "\n");
+
+ while (st.hasMoreTokens()) {
+ String line = (String) st.nextToken();
+ // break into tag:password format for each line
+ int colonIdx = line.indexOf(":");
+
+ if (colonIdx != -1) {
+ String tag = line.substring(0, colonIdx);
+ String passwd = line.substring(colonIdx + 1,
+ line.length());
+
+ ht.put(tag.trim(), passwd.trim());
+ } else {
+ //invalid format...log or throw...later
+ }
+ }
+ return ht;
+ }
+
+ /*
+ * get password from cache. This one supplies cache file name
+ */
+ public Password getEntry(String fileName, String tag) {
+ mPWcachedb = fileName;
+ return getEntry(tag);
+ }
+
+ /*
+ * if tag found with pwd, return it
+ * if tag not found, return null, which will cause it to give up
+ */
+ public Password getEntry(String tag) {
+ Hashtable pwTable = null;
+ String pw = null;
+
+ debug("in getEntry, tag=" + tag);
+
+ if (mPWcachedb == null) {
+ debug("mPWcachedb file path name is not initialized");
+ return null;
+ }
+
+ String dcrypts = null;
+
+ try {
+ dcrypts = readPWcache();
+ } catch (IOException e) {
+ System.out.println("dfailed readPWcache() " + e.toString());
+ return null;
+ }
+
+ if (dcrypts != null) {
+ // parse the cache
+ String cache = dcrypts;
+
+ // this is created and destroyed at each use
+ pwTable = string2Hashtable(cache);
+ debug("in getEntry, pw cache parsed");
+ pw = (String) pwTable.get(tag);
+ }
+
+ if (pw != null) {
+ debug("getEntry gotten password for " + tag);
+ return new Password(pw.toCharArray());
+ } else {
+ System.out.println("getEntry did not get password for tag " + tag);
+ return null;
+ }
+ }
+
+ //copied from IOUtil.java
+ /**
+ * Checks if this is NT.
+ */
+ public static boolean isNT() {
+ return ((File.separator).equals("\\"));
+ }
+
+ public static boolean exec(String cmd) throws IOException {
+ try {
+ String cmds[] = null;
+
+ if (isNT()) {
+ // NT
+ cmds = new String[3];
+ cmds[0] = "cmd";
+ cmds[1] = "/c";
+ cmds[2] = cmd;
+ } else {
+ // UNIX
+ cmds = new String[3];
+ cmds[0] = "/bin/sh";
+ cmds[1] = "-c";
+ cmds[2] = cmd;
+ }
+ Process process = Runtime.getRuntime().exec(cmds);
+
+ process.waitFor();
+ BufferedReader pOut = null;
+ String l = null;
+
+ if (process.exitValue() == 0) {
+
+ /**
+ pOut = new BufferedReader(
+ new InputStreamReader(process.getInputStream()));
+ while ((l = pOut.readLine()) != null) {
+ System.out.println(l);
+ }
+ **/
+ return true;
+ } else {
+
+ /**
+ pOut = new BufferedReader(
+ new InputStreamReader(process.getErrorStream()));
+ l = null;
+ while ((l = pOut.readLine()) != null) {
+ System.out.println(l);
+ }
+ **/
+ return false;
+ }
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
+ public void debug(String msg) {
+ System.out.println(msg);
+ }
+
+ public void log(int level, String msg) {
+ System.out.println(msg);
+ }
+
+ /*
+ * list passwds in pwcache.
+ */
+ public boolean pprint() {
+ String bufs = null;
+ String dcrypts = null;
+
+ try {
+ dcrypts = readPWcache();
+ } catch (IOException e) {
+ System.out.println("failed readPWcache() " + e.toString());
+ return false;
+ }
+
+ debug("----- Password Cache Content -----");
+
+ if (dcrypts != null) {
+ // first, break into lines
+ StringTokenizer st = new StringTokenizer(dcrypts, "\n");
+
+ while (st.hasMoreTokens()) {
+ String line = (String) st.nextToken();
+ // break into tag:password format for each line
+ int colonIdx = line.indexOf(":");
+
+ if (colonIdx != -1) {
+ String tag = line.substring(0, colonIdx);
+ String passwd = line.substring(colonIdx + 1,
+ line.length());
+
+ debug(tag.trim() +
+ " : " + passwd.trim());
+ } else {
+ //invalid format...log or throw...later
+ debug("invalid format");
+ }
+ }
+ } // else print nothing
+ return true;
+ }
+}
diff --git a/pki/base/java-tools/src/com/netscape/cmstools/PrettyPrintCert.java b/pki/base/java-tools/src/com/netscape/cmstools/PrettyPrintCert.java
new file mode 100644
index 000000000..b5ed8177f
--- /dev/null
+++ b/pki/base/java-tools/src/com/netscape/cmstools/PrettyPrintCert.java
@@ -0,0 +1,233 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmstools;
+
+
+import java.io.*;
+import java.util.*;
+import java.security.*;
+import java.security.cert.*;
+import netscape.security.x509.*;
+import netscape.security.util.*;
+
+
+/**
+ * The PrettyPrintCert class is a utility program designed to "pretty print"
+ * a certificate. It assumes that the name of a data file is passed to the
+ * program via the command line, and that the contents contain a certificate
+ * encoded in an ASCII BASE 64 format. Note that the data file may contain
+ * an optional "-----BEGIN" header and/or an optional "-----END" trailer.
+ *
+ * <P>
+ * The program may be invoked as follows:
+ * <PRE>
+ *
+ * PrettyPrintCert &lt;input filename&gt; [output filename]
+ *
+ * NOTE: &lt;input filename&gt; must contain an ASCII
+ * BASE 64 encoded certificate
+ *
+ * &lt;output filename&gt; contains a certificate displayed
+ * in a "pretty print" ASCII format
+ * </PRE>
+ *
+ * @version $Revision$, $Date$
+ */
+
+public class PrettyPrintCert {
+ // Define constants
+ public static final int ARGC = 2;
+ public static final String HEADER = "-----BEGIN";
+ public static final String TRAILER = "-----END";
+
+ public static void usageAndExit() {
+ System.out.println("Usage: PrettyPrintCert " +
+ "[options] " +
+ "<input filename> " +
+ "[output filename]");
+ System.out.println("\n options: ");
+ System.out.println(" -simpleinfo : prints limited cert info in easy to parse format");
+ System.exit(0);
+ }
+
+ public static void main(String argv[]) {
+
+ BufferedReader inputCert = null;
+ String encodedBASE64CertChunk = new String();
+ String encodedBASE64Cert = new String();
+ byte decodedBASE64Cert[] = null;
+ X509CertImpl cert = null;
+ Locale aLocale = null;
+ CertPrettyPrint certDetails = null;
+ String pp = new String();
+ FileOutputStream outputCert = null;
+ boolean mSimpleInfo = false;
+ String inputfile = null;
+ String outputfile = null;
+
+ // parse arguments
+
+ for (int i = 0; i < argv.length; i++) {
+
+ // deal with empty arguments passed in by script
+ if (argv[i].equals("")) {
+ continue;
+ }
+
+ // parse options
+ if (argv[i].charAt(0) == '-') {
+ if (argv[i].equals("-simpleinfo")) {
+ mSimpleInfo = true;
+ continue;
+ } else {
+ System.out.println("Illegal option: " + argv[i]);
+ usageAndExit();
+ }
+ }
+
+ // deal with filename
+
+ if (inputfile == null) {
+ inputfile = argv[i];
+ continue;
+ }
+
+ if (outputfile == null) {
+ outputfile = argv[i];
+ continue;
+ }
+
+ System.out.println("Error - Too many arguments");
+ System.exit(0);
+ }
+
+ if (inputfile == null) {
+ usageAndExit();
+ }
+
+ // (2) Create a DataInputStream() object to the BASE 64
+ // encoded certificate contained within the file
+ // specified on the command line
+ try {
+ inputCert = new BufferedReader(new InputStreamReader(
+ new BufferedInputStream(
+ new FileInputStream(
+ inputfile))));
+ } catch (FileNotFoundException e) {
+ System.out.println("PrettyPrintCert: can't find file " +
+ inputfile + ":\n" + e);
+ return;
+ }
+
+ // (3) Read the entire contents of the specified BASE 64 encoded
+ // certificate into a String() object throwing away any
+ // headers beginning with HEADER and any trailers beginning
+ // with TRAILER
+ try {
+ while ((encodedBASE64CertChunk = inputCert.readLine()) != null) {
+ if (!(encodedBASE64CertChunk.startsWith(HEADER)) &&
+ !(encodedBASE64CertChunk.startsWith(TRAILER))) {
+ encodedBASE64Cert += encodedBASE64CertChunk.trim();
+ }
+ }
+ } catch (IOException e) {
+ System.out.println("PrettyPrintCert: Unexpected BASE64 " +
+ "encoded error encountered in readLine():\n" +
+ e);
+ }
+
+ // (4) Close the DataInputStream() object
+ try {
+ inputCert.close();
+ } catch (IOException e) {
+ System.out.println("PrettyPrintCert: Unexpected BASE64 " +
+ "encoded error encountered in close():\n" + e);
+ }
+
+ // (5) Decode the ASCII BASE 64 certificate enclosed in the
+ // String() object into a BINARY BASE 64 byte[] object
+
+ decodedBASE64Cert = com.netscape.osutil.OSUtil.AtoB(encodedBASE64Cert);
+
+ // (6) Create an X509CertImpl() object from the BINARY BASE 64
+ // byte[] object
+ try {
+ cert = new X509CertImpl(decodedBASE64Cert);
+ } catch (CertificateException e) {
+ System.out.println("PrettyPrintCert: Error encountered " +
+ "on parsing certificate :\n" + e);
+ }
+
+ if (mSimpleInfo) {
+ try {
+ X509CertInfo certinfo = (X509CertInfo) cert.get("x509.INFO");
+
+ CertificateSubjectName csn = (CertificateSubjectName)
+ certinfo.get(X509CertInfo.SUBJECT);
+
+ Enumeration en = csn.getElements();
+
+ X500Name dname = (X500Name) csn.get(CertificateSubjectName.DN_NAME);
+
+ pp = "";
+ RDN[] rdns = dname.getNames();
+
+ for (int i = rdns.length - 1; i >= 0; i--) {
+ pp = pp + rdns[i] + "\n";
+ }
+
+ } catch (Exception e) {
+ System.out.println("ERROR");
+ e.printStackTrace();
+ }
+ } else {
+ // (7) For this utility, always specify the default Locale
+ aLocale = Locale.getDefault();
+
+ // (8) Create a CertPrettyPrint() object
+ certDetails = new CertPrettyPrint(cert);
+
+ // (9) Convert the CertPrettyPrint() object into a String() object
+ pp = certDetails.toString(aLocale);
+ }
+
+ // (10) Finally, "pretty print" the actual certificate to the console
+ // unless an output file has been specified
+ if (outputfile == null) {
+ System.out.println(pp);
+ } else {
+ try {
+ outputCert = new FileOutputStream(outputfile);
+ } catch (IOException e) {
+ System.out.println("PrettyPrintCert: unable to open file " +
+ argv[1] + " for writing:\n" + e);
+ return;
+ }
+
+ try {
+ outputCert.write(pp.getBytes());
+ outputCert.close();
+ } catch (IOException e) {
+ System.out.println("PrettyPrintCert: Unexpected error " +
+ "encountered while attempting to close() " +
+ outputfile + ":\n" + e);
+ }
+ }
+ }
+}
+
diff --git a/pki/base/java-tools/src/com/netscape/cmstools/PrettyPrintCrl.java b/pki/base/java-tools/src/com/netscape/cmstools/PrettyPrintCrl.java
new file mode 100644
index 000000000..4d410f16f
--- /dev/null
+++ b/pki/base/java-tools/src/com/netscape/cmstools/PrettyPrintCrl.java
@@ -0,0 +1,199 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmstools;
+
+
+import java.io.*;
+import java.util.*;
+import java.security.*;
+import java.security.cert.*;
+import netscape.security.x509.*;
+import netscape.security.util.*;
+
+
+/**
+ * The PrettyPrintCrl class is a utility program designed to "pretty print"
+ * a CRL. It assumes that the name of a data file is passed to the
+ * program via the command line, and that the contents contain a CRL
+ * encoded in an ASCII BASE 64 format. Note that the data file may contain
+ * an optional "-----BEGIN" header and/or an optional "-----END" trailer.
+ *
+ * <P>
+ * The program may be invoked as follows:
+ * <PRE>
+ *
+ * PrettyPrintCrl &lt;input filename&gt; [output filename]
+ *
+ * NOTE: &lt;input filename&gt; must contain an ASCII
+ * BASE 64 encoded CRL
+ *
+ * &lt;output filename&gt; contains a CRL displayed
+ * in a "pretty print" ASCII format
+ * </PRE>
+ *
+ * @version $Revision$, $Date$
+ */
+
+public class PrettyPrintCrl {
+ // Define constants
+ public static final int ARGC = 2;
+ public static final String HEADER = "-----BEGIN";
+ public static final String TRAILER = "-----END";
+
+ public static void main(String argv[]) {
+
+ BufferedReader inputCrl = null;
+ String encodedBASE64CrlChunk = new String();
+ String encodedBASE64Crl = new String();
+ byte decodedBASE64Crl[] = null;
+ X509CRLImpl crl = null;
+ Locale aLocale = null;
+ CrlPrettyPrint CrlDetails = null;
+ String pp = new String();
+ FileOutputStream outputCrl = null;
+
+ // (1) Check that at least one argument was submitted to the program
+ if ((argv.length < 1) || (argv.length > ARGC)) {
+ System.out.println("Usage: PrettyPrintCrl " +
+ "<input filename> " +
+ "[output filename]");
+ return;
+ }
+
+ try {
+ OIDMap.addAttribute(DeltaCRLIndicatorExtension.class.getName(),
+ DeltaCRLIndicatorExtension.OID,
+ DeltaCRLIndicatorExtension.NAME);
+ } catch (CertificateException e) {
+ }
+ try {
+ OIDMap.addAttribute(HoldInstructionExtension.class.getName(),
+ HoldInstructionExtension.OID,
+ HoldInstructionExtension.NAME);
+ } catch (CertificateException e) {
+ }
+ try {
+ OIDMap.addAttribute(InvalidityDateExtension.class.getName(),
+ InvalidityDateExtension.OID,
+ InvalidityDateExtension.NAME);
+ } catch (CertificateException e) {
+ }
+ try {
+ OIDMap.addAttribute(IssuingDistributionPointExtension.class.getName(),
+ IssuingDistributionPointExtension.OID,
+ IssuingDistributionPointExtension.NAME);
+ } catch (CertificateException e) {
+ }
+
+ // (2) Create a DataInputStream() object to the BASE 64
+ // encoded CRL contained within the file
+ // specified on the command line
+ try {
+ inputCrl = new BufferedReader(new InputStreamReader(
+ new BufferedInputStream(
+ new FileInputStream(
+ argv[0]))));
+ } catch (FileNotFoundException e) {
+ System.out.println("PrettyPrintCrl(): can''t find file " +
+ argv[0] + ":\n" + e);
+ return;
+ }
+
+ // (3) Read the entire contents of the specified BASE 64 encoded
+ // CRL into a String() object throwing away any
+ // headers beginning with HEADER and any trailers beginning
+ // with TRAILER
+ try {
+ while ((encodedBASE64CrlChunk = inputCrl.readLine()) != null) {
+ if (!(encodedBASE64CrlChunk.startsWith(HEADER)) &&
+ !(encodedBASE64CrlChunk.startsWith(TRAILER))) {
+ encodedBASE64Crl += encodedBASE64CrlChunk.trim();
+ }
+ }
+ } catch (IOException e) {
+ System.out.println("PrettyPrintCrl(): Unexpected BASE64 " +
+ "encoded error encountered in readLine():\n" +
+ e);
+ }
+
+ // (4) Close the DataInputStream() object
+ try {
+ inputCrl.close();
+ } catch (IOException e) {
+ System.out.println("PrettyPrintCrl(): Unexpected BASE64 " +
+ "encoded error encountered in close():\n" + e);
+ }
+
+ // (5) Decode the ASCII BASE 64 CRL enclosed in the
+ // String() object into a BINARY BASE 64 byte[] object
+
+ decodedBASE64Crl = com.netscape.osutil.OSUtil.AtoB(encodedBASE64Crl);
+
+ // (6) Create an X509CRLImpl() object from the BINARY BASE 64
+ // byte[] object
+ try {
+ crl = new X509CRLImpl(decodedBASE64Crl);
+ } catch (CRLException e) {
+ System.out.println("PrettyPrintCrl(): Error encountered " +
+ "on parsing and initialization errors:\n" + e);
+ } catch (X509ExtensionException e) {
+ System.out.println("PrettyPrintCrl(): Error encountered " +
+ "on parsing and initialization errors:\n" + e);
+ }
+
+ // (7) For this utility, always specify the default Locale
+ aLocale = Locale.getDefault();
+
+ // (8) Create a CrlPrettyPrint() object
+ CrlDetails = new CrlPrettyPrint(crl);
+
+ // (9) Convert the CrlPrettyPrint() object into a String() object
+ pp = CrlDetails.toString(aLocale);
+
+ // (10) Finally, "pretty print" the actual CRL to the console
+ // unless an output file has been specified
+ if (argv.length != ARGC) {
+ System.out.println(pp);
+ } else {
+ try {
+ outputCrl = new FileOutputStream(argv[1]);
+ } catch (IOException e) {
+ System.out.println("PrettyPrintCrl(): unable to open file " +
+ argv[1] + " for writing:\n" + e);
+ return;
+ }
+
+ try {
+ outputCrl.write(pp.getBytes());
+ } catch (IOException e) {
+ System.out.println("PrettyPrintCrl(): I/O error " +
+ "encountered during write():\n" +
+ e);
+ }
+
+ try {
+ outputCrl.close();
+ } catch (IOException e) {
+ System.out.println("PrettyPrintCrl(): Unexpected error " +
+ "encountered while attempting to close() " +
+ argv[1] + ":\n" + e);
+ }
+ }
+ }
+}
+
diff --git a/pki/base/java-tools/src/com/netscape/cmstools/TestCRLSigning.java b/pki/base/java-tools/src/com/netscape/cmstools/TestCRLSigning.java
new file mode 100644
index 000000000..b4fdf5d04
--- /dev/null
+++ b/pki/base/java-tools/src/com/netscape/cmstools/TestCRLSigning.java
@@ -0,0 +1,135 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmstools;
+
+import java.io.*;
+import java.net.*;
+import java.math.*;
+import java.util.*;
+import java.security.*;
+
+import org.mozilla.jss.*;
+import org.mozilla.jss.asn1.*;
+import org.mozilla.jss.util.*;
+import org.mozilla.jss.pkix.primitive.*;
+import org.mozilla.jss.pkix.crmf.*;
+import org.mozilla.jss.pkcs7.ContentInfo;
+import org.mozilla.jss.pkcs7.*;
+import org.mozilla.jss.pkcs11.*;
+import org.mozilla.jss.crypto.*;
+import org.mozilla.jss.crypto.KeyPairGenerator;
+import org.mozilla.jss.crypto.PrivateKey;
+import org.mozilla.jss.crypto.Signature;
+import org.mozilla.jss.crypto.X509Certificate;
+import org.mozilla.jss.util.Base64OutputStream;
+import org.mozilla.jss.util.*;
+import org.mozilla.jss.pkix.primitive.*;
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.crypto.*;
+import org.mozilla.jss.CertDatabaseException;
+import org.mozilla.jss.pkcs11.*;
+import org.mozilla.jss.pkcs11.PK11Token;
+
+import netscape.security.x509.*;
+
+import com.netscape.cmsutil.ocsp.*;
+import com.netscape.cmsutil.ocsp.Request;
+
+/**
+ * Tool used to test out signing a CRL
+ *
+ * <p>
+ * @version $Revision$ Date: $
+ */
+public class TestCRLSigning
+{
+ public static void printUsage()
+ {
+ System.out.println("Command <dbdir> <numreovked> <keysize> <tokenname> <tokenpwd>");
+ }
+
+ public static void main(String args[]) throws Exception
+ {
+ String dir = args[0];
+ String num = args[1];
+ String keysize = args[2];
+ String tokenname = args[3];
+ String tokenpwd = args[4];
+
+ // initialize JSS
+ CryptoManager cm = null;
+ CryptoManager.InitializationValues vals =
+ new CryptoManager.InitializationValues(dir, "", "", "secmod.db");
+ CryptoManager.initialize(vals);
+ cm = CryptoManager.getInstance();
+
+ // Login to token
+ CryptoToken token = null;
+ if (tokenname.equals("internal")) {
+ token = cm.getInternalKeyStorageToken();
+ } else {
+ token = cm.getTokenByName(tokenname);
+ }
+ Password pass = new Password(tokenpwd.toCharArray());
+ token.login(pass);
+
+ // generate key pair
+ KeyPairGenerator g = token.getKeyPairGenerator(KeyPairAlgorithm.RSA);
+ g.initialize(Integer.parseInt(keysize));
+ KeyPair pair = g.genKeyPair();
+
+ // generate revoked certificates
+ long startPutting = System.currentTimeMillis();
+ Date curDate = new Date();
+ Hashtable badCerts = new Hashtable();
+ int n = Integer.parseInt(num);
+ for (int i = 0; i < n; i++) {
+ badCerts.put(Integer.toString(i),
+ new RevokedCertImpl(new BigInteger(Integer.toString(i)), curDate));
+ }
+ long endPutting = System.currentTimeMillis();
+
+ long startConstructing = System.currentTimeMillis();
+ X509CRLImpl crl = new X509CRLImpl(
+ new X500Name("CN=Signer"),
+ null,
+ curDate,
+ curDate,
+ badCerts,
+ null);
+ long endConstructing = System.currentTimeMillis();
+
+
+ System.out.println("Start signing");
+ long startSigning = System.currentTimeMillis();
+ crl.sign(pair.getPrivate(), "SHA1withRSA");
+ long endSigning = System.currentTimeMillis();
+ System.out.println("Done signing");
+
+ long startData = System.currentTimeMillis();
+ byte data[] = crl.getTBSCertList();
+ long endData = System.currentTimeMillis();
+
+ System.out.println("Summary:");
+ System.out.println("Insertion time (ms): " + Long.toString(endPutting - startPutting));
+ System.out.println("Construction time (ms): " + Long.toString(endConstructing - startConstructing));
+ System.out.println("Signing time (ms): " + Long.toString(endSigning - startSigning));
+ System.out.println("Data time (ms): " + Long.toString(endData - startData));
+ System.out.println("Data size (bytes): " + Long.toString(data.length));
+ }
+}
diff --git a/pki/base/java-tools/src/com/netscape/cmstools/TokenInfo.java b/pki/base/java-tools/src/com/netscape/cmstools/TokenInfo.java
new file mode 100644
index 000000000..016839ae9
--- /dev/null
+++ b/pki/base/java-tools/src/com/netscape/cmstools/TokenInfo.java
@@ -0,0 +1,99 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmstools;
+
+
+import org.mozilla.jss.pkix.cmc.*;
+import org.mozilla.jss.pkix.cms.*;
+import org.mozilla.jss.pkix.cert.*;
+import org.mozilla.jss.pkix.primitive.*;
+import org.mozilla.jss.asn1.*;
+import org.mozilla.jss.pkcs10.*;
+import org.mozilla.jss.crypto.*;
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.crypto.CryptoToken;
+import org.mozilla.jss.crypto.SignatureAlgorithm;
+import org.mozilla.jss.crypto.DigestAlgorithm;
+import org.mozilla.jss.crypto.X509Certificate;
+import org.mozilla.jss.util.*;
+import org.mozilla.jss.pkcs11.*;
+
+import org.mozilla.jss.*;
+
+import netscape.security.util.*;
+import netscape.security.x509.*;
+import netscape.security.pkcs.PKCS10;
+
+import java.security.*;
+import java.security.cert.CertificateException;
+import java.math.*;
+import java.security.Principal;
+import java.lang.*;
+import java.lang.reflect.*;
+import java.io.*;
+import java.util.*;
+
+
+
+/**
+ * Tool used to determine which external hardware tokens are visible to the
+ * Certificate System subsystem. This can be used to diagnose whether problems
+ * using tokens are related to the Certificate System being unable to detect it.
+ *
+ * <p>
+ * @version $Revision$ Date: $
+ */
+public class TokenInfo {
+
+ /**
+ * Creates a new instance of CMCRevoke.
+ */
+ public static void main(String[]args) {
+ try {
+ if (args.length != 1) {
+ System.out.println("Usage: TokenInfo <alias directory>");
+ System.exit(0);
+ }
+ System.out.println("Database Path: " + args[0]);
+
+ CryptoManager.InitializationValues vals =
+ new CryptoManager.InitializationValues(args[0],
+ "", "", "secmod.db");
+
+ CryptoManager.initialize(vals);
+
+ CryptoManager cm = CryptoManager.getInstance();
+ Enumeration modules = cm.getModules();
+ while (modules.hasMoreElements()) {
+ PK11Module m = (PK11Module)modules.nextElement();
+ System.out.println("Found external module '" + m.getName() + "'");
+ }
+ Enumeration tokens = cm.getExternalTokens();
+
+ while (tokens.hasMoreElements()) {
+ CryptoToken t = (CryptoToken)tokens.nextElement();
+ System.out.println("Found external token '" + t.getName() + "'");
+ }
+
+ }catch (Exception e) {
+ e.printStackTrace();
+ System.exit(1);
+ }
+
+ }
+}
diff --git a/pki/base/java-tools/templates/CMakeLists.txt b/pki/base/java-tools/templates/CMakeLists.txt
new file mode 100644
index 000000000..4937fbf67
--- /dev/null
+++ b/pki/base/java-tools/templates/CMakeLists.txt
@@ -0,0 +1,39 @@
+project(java-tools-wrapper)
+
+set(PKI_PRODUCT pki)
+set(PKI_COMMANDS
+ AtoB
+ AuditVerify
+ BtoA
+ CMCEnroll
+ CMCRequest
+ CMCResponse
+ CMCRevoke
+ CRMFPopClient
+ ExtJoiner
+ GenExtKeyUsage
+ GenIssuerAltNameExt
+ GenSubjectAltNameExt
+ HttpClient
+ OCSPClient
+ PKCS10Client
+ PKCS12Export
+ PrettyPrintCert
+ PrettyPrintCrl
+ TokenInfo
+)
+
+foreach(PKI_COMMAND ${PKI_COMMANDS})
+ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/pki_java_command_wrapper.in ${CMAKE_CURRENT_BINARY_DIR}/${PKI_COMMAND} @ONLY)
+
+ install(
+ FILES
+ ${CMAKE_CURRENT_BINARY_DIR}/${PKI_COMMAND}
+ DESTINATION
+ ${BIN_INSTALL_DIR}
+ PERMISSIONS
+ OWNER_EXECUTE OWNER_WRITE OWNER_READ
+ GROUP_EXECUTE GROUP_READ
+ WORLD_EXECUTE WORLD_READ
+ )
+endforeach(PKI_COMMAND)
diff --git a/pki/base/java-tools/templates/pki_java_command_wrapper b/pki/base/java-tools/templates/pki_java_command_wrapper
new file mode 100644
index 000000000..27ddf11e4
--- /dev/null
+++ b/pki/base/java-tools/templates/pki_java_command_wrapper
@@ -0,0 +1,149 @@
+#!/bin/sh
+#
+# --- BEGIN COPYRIGHT BLOCK ---
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Copyright (C) 2007 Red Hat, Inc.
+# All rights reserved.
+# --- END COPYRIGHT BLOCK ---
+#
+
+# Check to insure that this script's original invocation directory
+# has not been deleted!
+CWD=`/bin/pwd > /dev/null 2>&1`
+if [ $? -ne 0 ] ; then
+ echo "Cannot invoke '$0' from non-existent directory!"
+ exit 255
+fi
+
+
+###############################################################################
+## (1) Specify variables used by this script. ##
+###############################################################################
+
+PRODUCT=[PKI_PRODUCT]
+COMMAND=[PKI_COMMAND]
+
+
+###############################################################################
+## (2) Check for valid usage of this command wrapper. ##
+###############################################################################
+
+
+
+###############################################################################
+## (3) Define helper functions. ##
+###############################################################################
+
+invalid_operating_system() {
+ echo
+ echo "ERROR: '$0' does not execute on the '$1' operating system!"
+ echo
+}
+
+invalid_architecture() {
+ echo
+ echo "ERROR: '$0' does not execute on the '$1' architecture!"
+ echo
+}
+
+
+###############################################################################
+## (4) Set the LD_LIBRARY_PATH environment variable to determine the ##
+## search order this command wrapper uses to find shared libraries. ##
+###############################################################################
+
+OS=`uname -s`
+
+if [ "${OS}" = "Linux" ] ; then
+ ARCHITECTURE=`uname -i`
+ JAVA="java"
+ JAVA_OPTIONS=""
+
+ if [ "${ARCHITECTURE}" = "i386" ] ; then
+ LD_LIBRARY_PATH=/usr/lib:/lib
+ LD_LIBRARY_PATH=/usr/lib/jss:${LD_LIBRARY_PATH}
+ LD_LIBRARY_PATH=/usr/lib/osutil:${LD_LIBRARY_PATH}
+ export LD_LIBRARY_PATH
+ elif [ "${ARCHITECTURE}" = "x86_64" ] ; then
+ LD_LIBRARY_PATH=/usr/lib:/lib
+ LD_LIBRARY_PATH=/usr/lib/jss:${LD_LIBRARY_PATH}
+ LD_LIBRARY_PATH=/usr/lib/osutil:${LD_LIBRARY_PATH}
+ LD_LIBRARY_PATH=/usr/lib64:/lib64:${LD_LIBRARY_PATH}
+ LD_LIBRARY_PATH=/usr/lib64/jss:${LD_LIBRARY_PATH}
+ LD_LIBRARY_PATH=/usr/lib64/osutil:${LD_LIBRARY_PATH}
+ export LD_LIBRARY_PATH
+ else
+ invalid_architecture "${ARCHITECTURE}"
+ exit 255
+ fi
+elif [ "${OS}" = "SunOS" ] ; then
+ ARCHITECTURE=`uname -p`
+ if [ "${ARCHITECTURE}" = "sparc" ] &&
+ [ -d "/usr/lib/sparcv9/" ] ; then
+ ARCHITECTURE="sparcv9"
+ fi
+ if [ "${ARCHITECTURE}" = "sparc" ] ; then
+ JAVA="/usr/jdk/instances/jdk1.5.0/jre/bin/java"
+ JAVA_OPTIONS=""
+
+ LD_LIBRARY_PATH=/usr/lib:/lib
+ LD_LIBRARY_PATH=/usr/lib/dirsec:${LD_LIBRARY_PATH}
+ LD_LIBRARY_PATH=/usr/lib/${PRODUCT}:${LD_LIBRARY_PATH}
+ export LD_LIBRARY_PATH
+ elif [ "${ARCHITECTURE}" = "sparcv9" ] ; then
+ JAVA="/usr/jdk/instances/jdk1.5.0/jre/bin/java"
+ JAVA_OPTIONS="-d64"
+
+ LD_LIBRARY_PATH=/usr/lib:/lib
+ LD_LIBRARY_PATH=/usr/lib/dirsec:${LD_LIBRARY_PATH}
+ LD_LIBRARY_PATH=/usr/lib/${PRODUCT}:${LD_LIBRARY_PATH}
+ LD_LIBRARY_PATH=/usr/lib/sparcv9:/lib/sparcv9:${LD_LIBRARY_PATH}
+ LD_LIBRARY_PATH=/usr/lib/sparcv9/dirsec:${LD_LIBRARY_PATH}
+ LD_LIBRARY_PATH=/usr/lib/sparcv9/${PRODUCT}:${LD_LIBRARY_PATH}
+ export LD_LIBRARY_PATH
+ else
+ invalid_architecture "${ARCHITECTURE}"
+ exit 255
+ fi
+else
+ invalid_operating_system "${OS}"
+ exit 255
+fi
+
+
+###############################################################################
+## (5) Set the CP environment variable to determine the search ##
+## order this command wrapper uses to find jar files. ##
+###############################################################################
+
+CP=/usr/lib/java/jss4.jar
+CP=/usr/lib/java/dirsec/jss4.jar:${CP}
+CP=/usr/lib/java/osutil.jar:${CP}
+CP=/usr/lib/java/dirsec/osutil.jar:${CP}
+CP=/usr/share/java/ldapjdk.jar:${CP}
+CP=/usr/share/java/${PRODUCT}/pki-nsutil.jar:${CP}
+CP=/usr/share/java/${PRODUCT}/pki-cmsutil.jar:${CP}
+CP=/usr/share/java/${PRODUCT}/pki-tools.jar:${CP}
+export CP
+
+
+###############################################################################
+## (6) Execute the java command specified by this java command wrapper ##
+## based upon the preset LD_LIBRARY_PATH and CP environment variables. ##
+###############################################################################
+
+${JAVA} ${JAVA_OPTIONS} -cp ${CP} com.netscape.cmstools.${COMMAND} "$@"
+exit $?
+
diff --git a/pki/base/java-tools/templates/pki_java_command_wrapper.in b/pki/base/java-tools/templates/pki_java_command_wrapper.in
new file mode 100644
index 000000000..3c804de3f
--- /dev/null
+++ b/pki/base/java-tools/templates/pki_java_command_wrapper.in
@@ -0,0 +1,149 @@
+#!/bin/sh
+#
+# --- BEGIN COPYRIGHT BLOCK ---
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Copyright (C) 2007 Red Hat, Inc.
+# All rights reserved.
+# --- END COPYRIGHT BLOCK ---
+#
+
+# Check to insure that this script's original invocation directory
+# has not been deleted!
+CWD=`/bin/pwd > /dev/null 2>&1`
+if [ $? -ne 0 ] ; then
+ echo "Cannot invoke '$0' from non-existent directory!"
+ exit 255
+fi
+
+
+###############################################################################
+## (1) Specify variables used by this script. ##
+###############################################################################
+
+PRODUCT=@PKI_PRODUCT@
+COMMAND=@PKI_COMMAND@
+
+
+###############################################################################
+## (2) Check for valid usage of this command wrapper. ##
+###############################################################################
+
+
+
+###############################################################################
+## (3) Define helper functions. ##
+###############################################################################
+
+invalid_operating_system() {
+ echo
+ echo "ERROR: '$0' does not execute on the '$1' operating system!"
+ echo
+}
+
+invalid_architecture() {
+ echo
+ echo "ERROR: '$0' does not execute on the '$1' architecture!"
+ echo
+}
+
+
+###############################################################################
+## (4) Set the LD_LIBRARY_PATH environment variable to determine the ##
+## search order this command wrapper uses to find shared libraries. ##
+###############################################################################
+
+OS=`uname -s`
+
+if [ "${OS}" = "Linux" ] ; then
+ ARCHITECTURE=`uname -i`
+ JAVA="java"
+ JAVA_OPTIONS=""
+
+ if [ "${ARCHITECTURE}" = "i386" ] ; then
+ LD_LIBRARY_PATH=/usr/lib:/lib
+ LD_LIBRARY_PATH=/usr/lib/jss:${LD_LIBRARY_PATH}
+ LD_LIBRARY_PATH=/usr/lib/osutil:${LD_LIBRARY_PATH}
+ export LD_LIBRARY_PATH
+ elif [ "${ARCHITECTURE}" = "x86_64" ] ; then
+ LD_LIBRARY_PATH=/usr/lib:/lib
+ LD_LIBRARY_PATH=/usr/lib/jss:${LD_LIBRARY_PATH}
+ LD_LIBRARY_PATH=/usr/lib/osutil:${LD_LIBRARY_PATH}
+ LD_LIBRARY_PATH=/usr/lib64:/lib64:${LD_LIBRARY_PATH}
+ LD_LIBRARY_PATH=/usr/lib64/jss:${LD_LIBRARY_PATH}
+ LD_LIBRARY_PATH=/usr/lib64/osutil:${LD_LIBRARY_PATH}
+ export LD_LIBRARY_PATH
+ else
+ invalid_architecture "${ARCHITECTURE}"
+ exit 255
+ fi
+elif [ "${OS}" = "SunOS" ] ; then
+ ARCHITECTURE=`uname -p`
+ if [ "${ARCHITECTURE}" = "sparc" ] &&
+ [ -d "/usr/lib/sparcv9/" ] ; then
+ ARCHITECTURE="sparcv9"
+ fi
+ if [ "${ARCHITECTURE}" = "sparc" ] ; then
+ JAVA="/usr/jdk/instances/jdk1.5.0/jre/bin/java"
+ JAVA_OPTIONS=""
+
+ LD_LIBRARY_PATH=/usr/lib:/lib
+ LD_LIBRARY_PATH=/usr/lib/dirsec:${LD_LIBRARY_PATH}
+ LD_LIBRARY_PATH=/usr/lib/${PRODUCT}:${LD_LIBRARY_PATH}
+ export LD_LIBRARY_PATH
+ elif [ "${ARCHITECTURE}" = "sparcv9" ] ; then
+ JAVA="/usr/jdk/instances/jdk1.5.0/jre/bin/java"
+ JAVA_OPTIONS="-d64"
+
+ LD_LIBRARY_PATH=/usr/lib:/lib
+ LD_LIBRARY_PATH=/usr/lib/dirsec:${LD_LIBRARY_PATH}
+ LD_LIBRARY_PATH=/usr/lib/${PRODUCT}:${LD_LIBRARY_PATH}
+ LD_LIBRARY_PATH=/usr/lib/sparcv9:/lib/sparcv9:${LD_LIBRARY_PATH}
+ LD_LIBRARY_PATH=/usr/lib/sparcv9/dirsec:${LD_LIBRARY_PATH}
+ LD_LIBRARY_PATH=/usr/lib/sparcv9/${PRODUCT}:${LD_LIBRARY_PATH}
+ export LD_LIBRARY_PATH
+ else
+ invalid_architecture "${ARCHITECTURE}"
+ exit 255
+ fi
+else
+ invalid_operating_system "${OS}"
+ exit 255
+fi
+
+
+###############################################################################
+## (5) Set the CP environment variable to determine the search ##
+## order this command wrapper uses to find jar files. ##
+###############################################################################
+
+CP=/usr/lib/java/jss4.jar
+CP=/usr/lib/java/dirsec/jss4.jar:${CP}
+CP=/usr/lib/java/osutil.jar:${CP}
+CP=/usr/lib/java/dirsec/osutil.jar:${CP}
+CP=/usr/share/java/ldapjdk.jar:${CP}
+CP=/usr/share/java/${PRODUCT}/pki-nsutil.jar:${CP}
+CP=/usr/share/java/${PRODUCT}/pki-cmsutil.jar:${CP}
+CP=/usr/share/java/${PRODUCT}/pki-tools.jar:${CP}
+export CP
+
+
+###############################################################################
+## (6) Execute the java command specified by this java command wrapper ##
+## based upon the preset LD_LIBRARY_PATH and CP environment variables. ##
+###############################################################################
+
+${JAVA} ${JAVA_OPTIONS} -cp ${CP} com.netscape.cmstools.${COMMAND} "$@"
+exit $?
+
diff --git a/pki/base/java-tools/templates/pretty_print_cert_command_wrapper b/pki/base/java-tools/templates/pretty_print_cert_command_wrapper
new file mode 100644
index 000000000..d9f57a05e
--- /dev/null
+++ b/pki/base/java-tools/templates/pretty_print_cert_command_wrapper
@@ -0,0 +1,177 @@
+#!/bin/sh
+#
+# --- BEGIN COPYRIGHT BLOCK ---
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Copyright (C) 2007 Red Hat, Inc.
+# All rights reserved.
+# --- END COPYRIGHT BLOCK ---
+#
+
+# Check to insure that this script's original invocation directory
+# has not been deleted!
+CWD=`/bin/pwd > /dev/null 2>&1`
+if [ $? -ne 0 ] ; then
+ echo "Cannot invoke '$0' from non-existent directory!"
+ exit 255
+fi
+
+
+###############################################################################
+## (1) Specify variables used by this script. ##
+###############################################################################
+
+PRODUCT=[PKI_PRODUCT]
+COMMAND=[PKI_COMMAND]
+
+
+###############################################################################
+## (2) Check for valid usage of this command wrapper. ##
+###############################################################################
+
+
+
+###############################################################################
+## (3) Define helper functions. ##
+###############################################################################
+
+invalid_operating_system() {
+ echo
+ echo "ERROR: '$0' does not execute on the '$1' operating system!"
+ echo
+}
+
+invalid_architecture() {
+ echo
+ echo "ERROR: '$0' does not execute on the '$1' architecture!"
+ echo
+}
+
+
+###############################################################################
+## (4) Set the LD_LIBRARY_PATH environment variable to determine the ##
+## search order this command wrapper uses to find shared libraries. ##
+###############################################################################
+
+OS=`uname -s`
+
+if [ "${OS}" = "Linux" ] ; then
+ ARCHITECTURE=`uname -i`
+ JAVA="java"
+ JAVA_OPTIONS=""
+
+ if [ "${ARCHITECTURE}" = "i386" ] ; then
+ LD_LIBRARY_PATH=/usr/lib:/lib
+ LD_LIBRARY_PATH=/usr/lib/jss:${LD_LIBRARY_PATH}
+ LD_LIBRARY_PATH=/usr/lib/osutil:${LD_LIBRARY_PATH}
+ export LD_LIBRARY_PATH
+ elif [ "${ARCHITECTURE}" = "x86_64" ] ; then
+ LD_LIBRARY_PATH=/usr/lib:/lib
+ LD_LIBRARY_PATH=/usr/lib/jss:${LD_LIBRARY_PATH}
+ LD_LIBRARY_PATH=/usr/lib/osutil:${LD_LIBRARY_PATH}
+ LD_LIBRARY_PATH=/usr/lib64:/lib64:${LD_LIBRARY_PATH}
+ LD_LIBRARY_PATH=/usr/lib64/jss:${LD_LIBRARY_PATH}
+ LD_LIBRARY_PATH=/usr/lib64/osutil:${LD_LIBRARY_PATH}
+ export LD_LIBRARY_PATH
+ else
+ invalid_architecture "${ARCHITECTURE}"
+ exit 255
+ fi
+elif [ "${OS}" = "SunOS" ] ; then
+ ARCHITECTURE=`uname -p`
+ if [ "${ARCHITECTURE}" = "sparc" ] &&
+ [ -d "/usr/lib/sparcv9/" ] ; then
+ ARCHITECTURE="sparcv9"
+ fi
+ if [ "${ARCHITECTURE}" = "sparc" ] ; then
+ JAVA="/usr/jdk/instances/jdk1.5.0/jre/bin/java"
+ JAVA_OPTIONS=""
+
+ LD_LIBRARY_PATH=/usr/lib:/lib
+ LD_LIBRARY_PATH=/usr/lib/dirsec:${LD_LIBRARY_PATH}
+ LD_LIBRARY_PATH=/usr/lib/${PRODUCT}:${LD_LIBRARY_PATH}
+ export LD_LIBRARY_PATH
+ elif [ "${ARCHITECTURE}" = "sparcv9" ] ; then
+ JAVA="/usr/jdk/instances/jdk1.5.0/jre/bin/java"
+ JAVA_OPTIONS="-d64"
+
+ LD_LIBRARY_PATH=/usr/lib:/lib
+ LD_LIBRARY_PATH=/usr/lib/dirsec:${LD_LIBRARY_PATH}
+ LD_LIBRARY_PATH=/usr/lib/${PRODUCT}:${LD_LIBRARY_PATH}
+ LD_LIBRARY_PATH=/usr/lib/sparcv9:/lib/sparcv9:${LD_LIBRARY_PATH}
+ LD_LIBRARY_PATH=/usr/lib/sparcv9/dirsec:${LD_LIBRARY_PATH}
+ LD_LIBRARY_PATH=/usr/lib/sparcv9/${PRODUCT}:${LD_LIBRARY_PATH}
+ export LD_LIBRARY_PATH
+ else
+ invalid_architecture "${ARCHITECTURE}"
+ exit 255
+ fi
+else
+ invalid_operating_system "${OS}"
+ exit 255
+fi
+
+
+###############################################################################
+## (5) Set the CP environment variable to determine the search ##
+## order this command wrapper uses to find jar files. ##
+###############################################################################
+
+CP=/usr/lib/java/jss4.jar
+CP=/usr/lib/java/dirsec/jss4.jar:${CP}
+CP=/usr/lib/java/osutil.jar:${CP}
+CP=/usr/lib/java/dirsec/osutil.jar:${CP}
+CP=/usr/share/java/ldapjdk.jar:${CP}
+CP=/usr/share/java/${PRODUCT}/pki-nsutil.jar:${CP}
+CP=/usr/share/java/${PRODUCT}/pki-cmsutil.jar:${CP}
+CP=/usr/share/java/${PRODUCT}/pki-tools.jar:${CP}
+export CP
+
+
+###############################################################################
+## (6) Execute the java command specified by this java command wrapper ##
+## based upon the preset LD_LIBRARY_PATH and CP environment variables. ##
+###############################################################################
+
+if [ $# -eq 1 ] ||
+ [ $# -eq 2 ] ||
+ [ $# -eq 3 ]
+then
+ if [ "$1" = "-simpleinfo" ]
+ then
+ file $2 | grep 'ASCII text' > /dev/null
+ if [ $? -ne 0 ] ; then
+ ${JAVA} ${JAVA_OPTIONS} -cp ${CP} com.netscape.cmstools.${COMMAND}
+ printf "\n"
+ printf " ERROR: '$2' is not an ASCII file!\n\n"
+ printf " First, use 'BtoA $2 $2.b64'\n"
+ printf " to convert a binary file into an ASCII file.\n\n"
+ exit 255
+ fi
+ else
+ file $1 | grep 'ASCII text' > /dev/null
+ if [ $? -ne 0 ] ; then
+ ${JAVA} ${JAVA_OPTIONS} -cp ${CP} com.netscape.cmstools.${COMMAND}
+ printf "\n"
+ printf " ERROR: '$1' is not an ASCII file!\n\n"
+ printf " First, use 'BtoA $1 $1.b64'\n"
+ printf " to convert a binary file into an ASCII file.\n\n"
+ exit 255
+ fi
+ fi
+fi
+
+${JAVA} ${JAVA_OPTIONS} -cp ${CP} com.netscape.cmstools.${COMMAND} "$@"
+exit $?
+
diff --git a/pki/base/java-tools/templates/pretty_print_crl_command_wrapper b/pki/base/java-tools/templates/pretty_print_crl_command_wrapper
new file mode 100644
index 000000000..8b9b04cdc
--- /dev/null
+++ b/pki/base/java-tools/templates/pretty_print_crl_command_wrapper
@@ -0,0 +1,163 @@
+#!/bin/sh
+#
+# --- BEGIN COPYRIGHT BLOCK ---
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Copyright (C) 2007 Red Hat, Inc.
+# All rights reserved.
+# --- END COPYRIGHT BLOCK ---
+#
+
+# Check to insure that this script's original invocation directory
+# has not been deleted!
+CWD=`/bin/pwd > /dev/null 2>&1`
+if [ $? -ne 0 ] ; then
+ echo "Cannot invoke '$0' from non-existent directory!"
+ exit 255
+fi
+
+
+###############################################################################
+## (1) Specify variables used by this script. ##
+###############################################################################
+
+PRODUCT=[PKI_PRODUCT]
+COMMAND=[PKI_COMMAND]
+
+
+###############################################################################
+## (2) Check for valid usage of this command wrapper. ##
+###############################################################################
+
+
+
+###############################################################################
+## (3) Define helper functions. ##
+###############################################################################
+
+invalid_operating_system() {
+ echo
+ echo "ERROR: '$0' does not execute on the '$1' operating system!"
+ echo
+}
+
+invalid_architecture() {
+ echo
+ echo "ERROR: '$0' does not execute on the '$1' architecture!"
+ echo
+}
+
+
+###############################################################################
+## (4) Set the LD_LIBRARY_PATH environment variable to determine the ##
+## search order this command wrapper uses to find shared libraries. ##
+###############################################################################
+
+OS=`uname -s`
+
+if [ "${OS}" = "Linux" ] ; then
+ ARCHITECTURE=`uname -i`
+ JAVA="java"
+ JAVA_OPTIONS=""
+
+ if [ "${ARCHITECTURE}" = "i386" ] ; then
+ LD_LIBRARY_PATH=/usr/lib:/lib
+ LD_LIBRARY_PATH=/usr/lib/jss:${LD_LIBRARY_PATH}
+ LD_LIBRARY_PATH=/usr/lib/osutil:${LD_LIBRARY_PATH}
+ export LD_LIBRARY_PATH
+ elif [ "${ARCHITECTURE}" = "x86_64" ] ; then
+ LD_LIBRARY_PATH=/usr/lib:/lib
+ LD_LIBRARY_PATH=/usr/lib/jss:${LD_LIBRARY_PATH}
+ LD_LIBRARY_PATH=/usr/lib/osutil:${LD_LIBRARY_PATH}
+ LD_LIBRARY_PATH=/usr/lib64:/lib64:${LD_LIBRARY_PATH}
+ LD_LIBRARY_PATH=/usr/lib64/jss:${LD_LIBRARY_PATH}
+ LD_LIBRARY_PATH=/usr/lib64/osutil:${LD_LIBRARY_PATH}
+ export LD_LIBRARY_PATH
+ else
+ invalid_architecture "${ARCHITECTURE}"
+ exit 255
+ fi
+elif [ "${OS}" = "SunOS" ] ; then
+ ARCHITECTURE=`uname -p`
+ if [ "${ARCHITECTURE}" = "sparc" ] &&
+ [ -d "/usr/lib/sparcv9/" ] ; then
+ ARCHITECTURE="sparcv9"
+ fi
+ if [ "${ARCHITECTURE}" = "sparc" ] ; then
+ JAVA="/usr/jdk/instances/jdk1.5.0/jre/bin/java"
+ JAVA_OPTIONS=""
+
+ LD_LIBRARY_PATH=/usr/lib:/lib
+ LD_LIBRARY_PATH=/usr/lib/dirsec:${LD_LIBRARY_PATH}
+ LD_LIBRARY_PATH=/usr/lib/${PRODUCT}:${LD_LIBRARY_PATH}
+ export LD_LIBRARY_PATH
+ elif [ "${ARCHITECTURE}" = "sparcv9" ] ; then
+ JAVA="/usr/jdk/instances/jdk1.5.0/jre/bin/java"
+ JAVA_OPTIONS="-d64"
+
+ LD_LIBRARY_PATH=/usr/lib:/lib
+ LD_LIBRARY_PATH=/usr/lib/dirsec:${LD_LIBRARY_PATH}
+ LD_LIBRARY_PATH=/usr/lib/${PRODUCT}:${LD_LIBRARY_PATH}
+ LD_LIBRARY_PATH=/usr/lib/sparcv9:/lib/sparcv9:${LD_LIBRARY_PATH}
+ LD_LIBRARY_PATH=/usr/lib/sparcv9/dirsec:${LD_LIBRARY_PATH}
+ LD_LIBRARY_PATH=/usr/lib/sparcv9/${PRODUCT}:${LD_LIBRARY_PATH}
+ export LD_LIBRARY_PATH
+ else
+ invalid_architecture "${ARCHITECTURE}"
+ exit 255
+ fi
+else
+ invalid_operating_system "${OS}"
+ exit 255
+fi
+
+
+###############################################################################
+## (5) Set the CP environment variable to determine the search ##
+## order this command wrapper uses to find jar files. ##
+###############################################################################
+
+CP=/usr/lib/java/jss4.jar
+CP=/usr/lib/java/dirsec/jss4.jar:${CP}
+CP=/usr/lib/java/osutil.jar:${CP}
+CP=/usr/lib/java/dirsec/osutil.jar:${CP}
+CP=/usr/share/java/ldapjdk.jar:${CP}
+CP=/usr/share/java/${PRODUCT}/pki-nsutil.jar:${CP}
+CP=/usr/share/java/${PRODUCT}/pki-cmsutil.jar:${CP}
+CP=/usr/share/java/${PRODUCT}/pki-tools.jar:${CP}
+export CP
+
+
+###############################################################################
+## (6) Execute the java command specified by this java command wrapper ##
+## based upon the preset LD_LIBRARY_PATH and CP environment variables. ##
+###############################################################################
+
+if [ $# -eq 1 ] ||
+ [ $# -eq 2 ]
+then
+ file $1 | grep 'ASCII text' > /dev/null
+ if [ $? -ne 0 ] ; then
+ ${JAVA} ${JAVA_OPTIONS} -cp ${CP} com.netscape.cmstools.${COMMAND}
+ printf "\n"
+ printf "ERROR: '$1' is not an ASCII file!\n\n"
+ printf " First, use 'BtoA $1 $1.b64'\n"
+ printf " to convert a binary file into an ASCII file.\n\n"
+ exit 255
+ fi
+fi
+
+${JAVA} ${JAVA_OPTIONS} -cp ${CP} com.netscape.cmstools.${COMMAND} "$@"
+exit $?
+