diff options
Diffstat (limited to 'pki/base/java-tools')
27 files changed, 8126 insertions, 0 deletions
diff --git a/pki/base/java-tools/LICENSE b/pki/base/java-tools/LICENSE new file mode 100644 index 000000000..e36f2269a --- /dev/null +++ b/pki/base/java-tools/LICENSE @@ -0,0 +1,311 @@ +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. + +In addition, as a special exception, Red Hat, Inc. gives You the additional +right to link the code of this Program with code not covered under the GNU +General Public License ("Non-GPL Code") and to distribute linked combinations +including the two, subject to the limitations in this paragraph. Non-GPL +Code permitted under this exception must only link to the code of this +Program through those well defined interfaces identified in the file named +EXCEPTION found in the source code files (the "Approved Interfaces"). + +The files of Non-GPL Code may instantiate templates or use macros or inline +functions from the Approved Interfaces without causing the resulting work to +be covered by the GNU General Public License. Only Red Hat, Inc. may make +changes or additions to the list of Approved Interfaces. You must obey the +GNU General Public License in all respects for all of the Program code and +other code used in conjunction with the Program except the Non-GPL Code +covered by this exception. If you modify this file, you may extend this +exception to your version of the file, but you are not obligated to do so. +If you do not wish to provide this exception without modification, you must +delete this exception statement from your version and license this file +solely under the GPL without exception. + + 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..9ddd835e3 --- /dev/null +++ b/pki/base/java-tools/build.xml @@ -0,0 +1,576 @@ +<!-- ### 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="certsrv.jar" value="${pki-jar.home}/certsrv.jar"/> + <property name="cms.jar" value="${pki-jar.home}/cms.jar"/> + <property name="cmsutil.jar" value="${pki-jar.home}/cmsutil.jar"/> + <property name="nsutil.jar" value="${pki-jar.home}/nsutil.jar"/> + + <path id="classpath"> + <pathelement location="${jss.jar}"/> + <pathelement location="${ldapjdk.jar}"/> + <pathelement location="${nsutil.jar}"/> + <pathelement location="${osutil.jar}"/> + <pathelement location="${cmsutil.jar}"/> + <pathelement location="${cms.jar}"/> + <pathelement location="${certsrv.jar}"/> + </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}/cstools.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}" + author="true" + breakiterator="true" + version="true" + use="true" + windowtitle="${ant.project.name}" + classpathref="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\]/AudityVerify/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/pki_java_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/pki_java_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="755" + prefix="usr/share/doc/${dist.name}"> + <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="755" + prefix="${dist.name}/usr/share/doc/${dist.name}"> + <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="755" + prefix="${src.dist.name}"> + <include name="${specfile}"/> + <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="755" + prefix="${src.dist.name}"> + <include name="${specfile}"/> + <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/config/product.xml b/pki/base/java-tools/config/product.xml new file mode 100644 index 000000000..33caf48ed --- /dev/null +++ b/pki/base/java-tools/config/product.xml @@ -0,0 +1,305 @@ +<!-- ### 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="product.xml" default="main" basedir="."> + + <!-- Set up properties based upon the user's default Ant configuration --> + <property file=".ant.properties"/> + <property file="${user.home}/.ant.properties"/> + <property environment="env"/> + + + <!-- Check for required properties passed-in via the build scripts --> + <fail message="The '-Dspecfile=SPECFILE' property MUST always be specified!" + unless="specfile"/> + + + <!-- Set up optional properties passed-in via the build scripts --> + <property name="basedir" value=""/> + <property name="dirsec" value=""/> + <property name="target" value=""/> + + + <!-- Set up properties obtained from the spec file --> + <exec executable="perl" + failonerror="true" + outputproperty="Name"> + <arg value="-ne"/> + <arg value="print $1 if /%define base_product\s+(.*)/"/> + <arg value="${specfile}"/> + </exec> + + <exec executable="perl" + failonerror="true" + outputproperty="spec.product.ui.prefix"> + <arg value="-ne"/> + <arg value="print $1 if /%define base_ui_prefix\s+(\S+)/"/> + <arg value="${specfile}"/> + </exec> + + <exec executable="perl" + failonerror="true" + outputproperty="product.prefix"> + <arg value="-ne"/> + <arg value="print $1 if /%define base_prefix\s+(\S+)/"/> + <arg value="${specfile}"/> + </exec> + + <exec executable="perl" + failonerror="true" + outputproperty="product"> + <arg value="-ne"/> + <arg value="print $1 if /%define base_component\s+(\S+)/"/> + <arg value="${specfile}"/> + </exec> + + <!-- if "spec.product.ui.prefix" is "" or "linux", --> + <!-- set "product.ui.prefix" to ""; otherwise --> + <!-- set "product.ui.prefix" to "spec.product.ui.prefix" --> + <condition property="product.ui.prefix" + value="" + else="${spec.product.ui.prefix}"> + <or> + <equals arg1="${spec.product.ui.prefix}" + arg2=""/> + <equals arg1="${spec.product.ui.prefix}" + arg2="linux"/> + </or> + </condition> + + <!-- "product.name" is of the form "x-y-z" --> + <condition property="product.name" + value="${product.ui.prefix}-${product.prefix}-${product}"> + <not> + <equals arg1="${product.ui.prefix}" + arg2=""/> + </not> + </condition> + + <!-- "product.name" is of the form "x-y" --> + <condition property="product.name" + value="${product.prefix}-${product}"> + <and> + <equals arg1="${product.ui.prefix}" + arg2=""/> + <not> + <equals arg1="${product.prefix}" + arg2=""/> + </not> + </and> + </condition> + + <!-- "product.name" is of the form "x" --> + <condition property="product.name" + value="${product}"> + <and> + <equals arg1="${product.ui.prefix}" + arg2=""/> + <equals arg1="${product.prefix}" + arg2=""/> + </and> + </condition> + + <exec executable="perl" + failonerror="true" + outputproperty="version"> + <arg value="-ne"/> + <arg value="print $1 if /%define base_version\s+(\S+)/"/> + <arg value="${specfile}"/> + </exec> + + + <!-- Set up architecture-dependent properties --> + <exec executable="uname" + failonerror="true" + outputproperty="arch"> + <arg line="-i"/> + </exec> + + <!-- Set up architecture-independent properties --> + <property name="jar.home" value="/usr/share/java"/> + <property name="pki-jar.home" value="${jar.home}/${product.prefix}"/> + <property name="jni-jar.home" value="/usr/lib/java"/> + + <!-- Set up properties that control various build options --> + <property name="debug" value="true"/> + <property name="chmod.fail" value="true"/> + <property name="chmod.maxparallel" value="250"/> + <property name="deprecation" value="false"/> + <property name="optimize" value="true"/> + + + <!-- Set up properties related to the source tree --> + <property name="docs.dir" value="docs"/> + <property name="lib.dir" value="lib"/> + <property name="src.dir" value="src"/> + <property name="test.dir" value="test"/> + <property name="etc.dir" value="${src.dir}/etc"/> + <property name="script.dir" value="${src.dir}/script"/> + + + <!-- Set up properties for the release area --> + <property name="release.root" value="."/> + + + <!-- Set up properties for the build area --> + <property name="build.dir" value="build"/> + <property name="bootstrap.dir" value="bootstrap"/> + <property name="build.jars" value="${build.dir}/jars"/> + <property name="build.classes" value="${build.dir}/classes"/> + <property name="build.lib" value="${build.dir}/lib"/> + <property name="build.javadocs" value="${build.dir}/javadocs"/> + <property name="build.tests" value="${build.dir}/testcases"/> + <property name="build.tests.javadocs" value="${build.dir}/javadocs.test/"/> + <property name="manifest.tmp" value="${build.dir}/optional.manifest"/> + + + <!-- Set up properties for the distribution area --> + <property name="dist.name" value="${product.name}-${version}"/> + <property name="dist.base" value="dist"/> + <property name="dist.base.source" value="${dist.base}/source"/> + <property name="dist.base.binaries" value="${dist.base}/binary"/> + <property name="dist.dir" value="dist"/> + <property name="dist.bin" value="${dist.dir}/bin"/> + <property name="dist.lib" value="${dist.dir}/lib"/> + <property name="dist.docs" value="${dist.dir}/docs"/> + <property name="dist.etc" value="${dist.dir}/etc"/> + <property name="src.dist.name" value="${product.name}-${version}"/> + <property name="src.dist.dir" value="dist-src"/> + <property name="src.dist.src" value="${src.dist.dir}/src"/> + <property name="src.dist.docs" value="${src.dist.dir}/docs"/> + <property name="src.dist.lib" value="${src.dist.dir}/lib"/> + + + <!-- Set up properties for log messages --> + <property name="begin.clean.log.message" + value="Removing '${product.name}' component directories ..."/> + <property name="empty.clean.log.message" + value="Nothing to do!"/> + <property name="end.clean.log.message" + value="Completed removing '${product.name}' component directories."/> + <property name="begin.download.log.message" + value="Downloading '${product.name}' dependent components ..."/> + <property name="empty.download.log.message" + value="Nothing to do!"/> + <property name="end.download.log.message" + value="Completed downloading '${product.name}' dependent components."/> + <property name="begin.compile.java.log.message" + value="Compiling '${product.name}' java code from '${src.dir}' into '${build.classes}' ..."/> + <property name="empty.compile.java.log.message" + value="Nothing to do!"/> + <property name="end.compile.java.log.message" + value="Completed compiling '${product.name}' java code from '${src.dir}' into '${build.classes}'."/> + <property name="begin.build.jars.log.message" + value="Generating '${product.name}' jar files ..."/> + <property name="empty.build.jars.log.message" + value="Nothing to do!"/> + <property name="end.build.jars.log.message" + value="Completed generating '${product.name}' jar files."/> + <property name="begin.build.jni.headers.log.message" + value="Generating '${product.name}' java header files ..."/> + <property name="empty.build.jni.headers.log.message" + value="Nothing to do!"/> + <property name="end.build.jni.headers.log.message" + value="Completed generating '${product.name}' java header files."/> + <property name="notify.build.log.message" + value="Built classes, jars, and jni headers for the '${product.name}' component."/> + <property name="begin.compile.junit.tests.log.message" + value="Compiling '${product.name}' junit tests from '${test.dir}' into '${build.tests}' ..."/> + <property name="empty.compile.junit.tests.log.message" + value="Nothing to do!"/> + <property name="end.compile.junit.tests.log.message" + value="Completed compiling '${product.name}' junit tests from '${test.dir}' into '${build.tests}'."/> + <property name="begin.run.junit.tests.log.message" + value="Executing '${product.name}' tests ..."/> + <property name="empty.run.junit.tests.log.message" + value="Nothing to do!"/> + <property name="end.run.junit.tests.log.message" + value="Completed executing '${product.name}' tests."/> + <property name="notify.verify.log.message" + value="Verified the '${product.name}' component."/> + <property name="begin.clean.javadocs.log.message" + value="Removing '${product.name}' javadocs directory ..."/> + <property name="empty.clean.javadocs.log.message" + value="Nothing to do!"/> + <property name="end.clean.javadocs.log.message" + value="Completed removing '${product.name}' javadocs directory."/> + <property name="begin.compose.javadocs.log.message" + value="Composing '${product.name}' javadocs ..."/> + <property name="empty.compose.javadocs.log.message" + value="Nothing to do!"/> + <property name="end.compose.javadocs.log.message" + value="Completed composing '${product.name}' javadocs."/> + <property name="notify.document.log.message" + value="Documented '${product.name}' javadocs."/> + <property name="begin.distribute.binaries.log.message" + value="Creating '${product.name}' binary distributions ..."/> + <property name="begin.binary.wrappers.log.message" + value=" Creating '${product.name}' binary wrappers ..."/> + <property name="empty.binary.wrappers.log.message" + value=" Nothing to do!"/> + <property name="end.binary.wrappers.log.message" + value=" Completed creating '${product.name}' binary wrappers."/> + <property name="begin.binary.zip.log.message" + value=" Creating '${product.name}' binary zip files ..."/> + <property name="empty.binary.zip.log.message" + value=" Nothing to do!"/> + <property name="end.binary.zip.log.message" + value=" Completed creating '${product.name}' binary zip files."/> + <property name="begin.binary.tar.log.message" + value=" Creating '${product.name}' binary tar files ..."/> + <property name="empty.binary.tar.log.message" + value=" Nothing to do!"/> + <property name="end.binary.tar.log.message" + value=" Completed creating '${product.name}' binary tar files."/> + <property name="begin.binary.gtar.log.message" + value=" Creating '${product.name}' binary gzip files ..."/> + <property name="empty.binary.gtar.log.message" + value=" Nothing to do!"/> + <property name="end.binary.gtar.log.message" + value=" Completed creating '${product.name}' binary gzip files."/> + <property name="end.distribute.binaries.log.message" + value="Completed creating '${product.name}' binary distributions."/> + <property name="begin.distribute.source.log.message" + value="Creating '${product.name}' source distributions ..."/> + <property name="begin.source.zip.log.message" + value=" Creating '${product.name}' source zip files ..."/> + <property name="empty.source.zip.log.message" + value=" Nothing to do!"/> + <property name="end.source.zip.log.message" + value=" Completed creating '${product.name}' source zip files."/> + <property name="begin.source.tar.log.message" + value=" Creating '${product.name}' source tar files ..."/> + <property name="empty.source.tar.log.message" + value=" Nothing to do!"/> + <property name="end.source.tar.log.message" + value=" Completed creating '${product.name}' source tar files."/> + <property name="begin.source.gtar.log.message" + value=" Creating '${product.name}' source gzip files ..."/> + <property name="empty.source.gtar.log.message" + value=" Nothing to do!"/> + <property name="end.source.gtar.log.message" + value=" Completed creating '${product.name}' source gzip files."/> + <property name="end.distribute.source.log.message" + value="Completed creating '${product.name}' source distributions."/> + <property name="notify.distribute.log.message" + value="Distributed '${product.name}' distribution packages."/> + <property name="notify.main.log.message" + value="Built, verified, documented, and distributed a fresh '${product.name}' component."/> + +</project> + diff --git a/pki/base/java-tools/config/release.xml b/pki/base/java-tools/config/release.xml new file mode 100644 index 000000000..fc43aaeb7 --- /dev/null +++ b/pki/base/java-tools/config/release.xml @@ -0,0 +1,86 @@ +<!-- ### 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="release.xml" default="main" basedir="${basedir}"> + + <echo message="Importing shared properties ..."/> + <import file="product.xml"/> + <import file="product-ext.xml" optional="true"/> + <import file="release-ext.xml" optional="true"/> + <echo message="Completed importing shared properties."/> + + + <target name="local" + depends="" + description="--> Generate this target locally"> + <echo message="Generating the '${product.name}' target locally ..."/> + <exec executable="ant" dir="${release.root}"> + <arg value="-Dspecfile=${product.name}.spec"/> + <arg value="-Ddirsec=${dirsec}"/> + <arg value="${target}"/> + </exec> + <echo message="Completed generating the '${product.name}' target locally."/> + </target> + + + <target name="main" + depends="" + description="--> Generate component RPMS and SRPMS"> + <echo message="Generating '${product.name}' RPMS and SRPMS ..."/> + + <exec executable="pwd" + failonerror="true" + outputproperty="top.dir"/> + <echo message="Established the '${top.dir}' top-level directory."/> + + <echo message="Creating the '${product.name}' source distribution ..."/> + <exec executable="ant" + dir="${release.root}"> + <arg value="-Dspecfile=${product.name}.spec"/> + <arg value="-Ddirsec=${dirsec}"/> + <arg value="distribute_source"/> + </exec> + <echo message="Completed creating the '${product.name}' source distribution."/> + + <echo message="Creating '${product.name}' RPM directories ..."/> + <mkdir dir="${release.root}/dist/rpmpkg"/> + <mkdir dir="${release.root}/dist/rpmpkg/SOURCES"/> + <mkdir dir="${release.root}/dist/rpmpkg/RPMS"/> + <mkdir dir="${release.root}/dist/rpmpkg/SRPMS"/> + <mkdir dir="${release.root}/dist/rpmpkg/SPECS"/> + <mkdir dir="${release.root}/dist/rpmpkg/BUILD"/> + <echo message="Completed creating '${product.name}' RPM directories."/> + + <echo message="Building '${product.name}' RPMS and SRPMS ..."/> + <exec executable="rpmbuild" + dir="${release.root}"> + <arg value="--define"/> + <arg value="_topdir ${top.dir}/${release.root}/dist/rpmpkg"/> + <arg value="-ta"/> + <arg value="${top.dir}/${release.root}/dist/source/${product.name}-${version}.tar.gz"/> + </exec> + <echo message="Completed building '${product.name}' RPMS and SRPMS."/> + + <echo message="Removing various '${product.name}' RPM directories and files ..."/> + <delete dir="${release.root}/dist/rpmpkg/BUILD"/> + <echo message="Completed removing various '${product.name}' RPM directories and files."/> + + <echo message="Completed generating '${product.name}' RPMS and SRPMS."/> + </target> + +</project> + diff --git a/pki/base/java-tools/doc/README b/pki/base/java-tools/doc/README new file mode 100644 index 000000000..a7f15bb25 --- /dev/null +++ b/pki/base/java-tools/doc/README @@ -0,0 +1,133 @@ + Fedora 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/com/netscape/cmstools/AtoB.java b/pki/base/java-tools/src/com/netscape/cmstools/AtoB.java new file mode 100644 index 000000000..0f49aa4eb --- /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 <input filename> <output filename> + * + * NOTE: <input filename> must contain an ASCII + * BASE 64 encoded blob + * + * <output filename> contains a BINARY + * BASE 64 encoded blob + * </PRE> + * + * @version $Revision: 14569 $, $Date: 2007-05-01 10:50:46 -0700 (Tue, 01 May 2007) $ + */ +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..3207c2f76 --- /dev/null +++ b/pki/base/java-tools/src/com/netscape/cmstools/AuditVerify.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 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.*; + +/** + * Tool for verifying signed audit logs + * + * @version $Revision: 14569 $, $Date: 2007-05-01 10:50:46 -0700 (Tue, 01 May 2007) $ + */ +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 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); + + // verify signer's certificate + if( ! cm.isCertValid(signerNick, true, + CryptoManager.CertUsage.EmailSigner) ) + { + System.out.println("Error: signing certificate is not valid"); + System.exit(1); + } + + PublicKey pubk = signerCert.getPublicKey(); + String sigAlgorithm=null; + if( pubk instanceof RSAPublicKey ) { + sigAlgorithm = "SHA-1/RSA"; + } else if( pubk instanceof DSAPublicKey ) { + sigAlgorithm = "SHA-1/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..8518dae21 --- /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 <input filename> <output filename> + * + * NOTE: <input filename> must contain a BINARY + * BASE 64 encoded blob + * + * <output filename> contains an ASCII + * BASE 64 encoded blob + * </PRE> + * + * @version $Revision: 14569 $, $Date: 2007-05-01 10:50:46 -0700 (Tue, 01 May 2007) $ + */ +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..0c5e15a3b --- /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: 14569 $, $Date: 2007-05-01 10:50:46 -0700 (Tue, 01 May 2007) $ + + */ +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..34de417a1 --- /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: 14569 $, $Date: 2007-05-01 10:50:46 -0700 (Tue, 01 May 2007) $ + * + */ +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..38411feb0 --- /dev/null +++ b/pki/base/java-tools/src/com/netscape/cmstools/CMCResponse.java @@ -0,0 +1,237 @@ +// --- 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.*; + +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..cf37025bd --- /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 PKCS #10 , return CMC + * + * <P> + * @version $Revision: 14569 $, $Date: 2007-05-01 10:50:46 -0700 (Tue, 01 May 2007) $ + */ +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..2748af24f --- /dev/null +++ b/pki/base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java @@ -0,0 +1,643 @@ +// --- 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.*; + + +/** + * Description: A command-line utility used to generate a + * Certificate Request Message Format (CRMF) + * request with proof of possesion (POP). + * + * Usage: + * + * 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] + * + * + * Examples: + * + * 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 + * + * + * 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. + */ +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..e0f07ecc2 --- /dev/null +++ b/pki/base/java-tools/src/com/netscape/cmstools/ExtJoiner.java @@ -0,0 +1,97 @@ +// --- 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: + * ExtJoiner \ + * <ext_file0> <ext_file1> ... <ext_fileN> + * + * where, + * <ext_file> 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 + * : } + * : } + * + * + * @version $Revision: 14569 $, $Date: 2007-05-01 10:50:46 -0700 (Tue, 01 May 2007) $ + */ +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..b688d619a --- /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: 14569 $, $Date: 2007-05-01 10:50:46 -0700 (Tue, 01 May 2007) $ + */ +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..e1ee55cc8 --- /dev/null +++ b/pki/base/java-tools/src/com/netscape/cmstools/GenIssuerAltNameExt.java @@ -0,0 +1,128 @@ +// --- 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: + * GenIssuerAltNameExt \ + * <general_type0> <general_name0> ... <general_typeN> <general_nameN> + * + * where, + * <general_type> can be one of the following string: + * DNSName + * EDIPartyName + * IPAddressName + * URIName + * RFC822Name + * OIDName + * X500Name + * <general_name> is string + * + * @version $Revision: 14569 $, $Date: 2007-05-01 10:50:46 -0700 (Tue, 01 May 2007) $ + */ +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..c8fcc257c --- /dev/null +++ b/pki/base/java-tools/src/com/netscape/cmstools/GenSubjectAltNameExt.java @@ -0,0 +1,128 @@ +// --- 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: + * GenSubjectAltNameExt \ + * <general_type0> <general_name0> ... <general_typeN> <general_nameN> + * + * where, + * <general_type> can be one of the following string: + * DNSName + * EDIPartyName + * IPAddressName + * URIName + * RFC822Name + * OIDName + * X500Name + * <general_name> is string + * + * @version $Revision: 14569 $, $Date: 2007-05-01 10:50:46 -0700 (Tue, 01 May 2007) $ + */ +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..4ad7ee6c2 --- /dev/null +++ b/pki/base/java-tools/src/com/netscape/cmstools/HttpClient.java @@ -0,0 +1,396 @@ +// --- 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. + */ +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 void send(String ifilename, String ofilename, String dbdir, + String nickname, String password, String servlet, String clientmode) + throws Exception + { + byte[] b = new byte[5000]; + FileInputStream fis = new FileInputStream(ifilename); + int totalnum = 0; + while (fis.available() > 0) { + int num = fis.read(b, 0, 4999); + totalnum += num; + } + System.out.println("Total number of bytes read = "+totalnum); + + 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: " + totalnum + "\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(); + fis.close(); + + b = new byte[10000]; + fis = new FileInputStream(ofilename); + totalnum = 0; + while (fis.available() > 0) { + int num = fis.read(b, 0, 10000); + totalnum += num; + } + + System.out.println("Total number of bytes read = "+totalnum); + + byte[] bout = new byte[totalnum]; + for (int i=0; i<totalnum; i++) { + bout[i] = b[i]; + } + 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..6d10a2c0b --- /dev/null +++ b/pki/base/java-tools/src/com/netscape/cmstools/OCSPClient.java @@ -0,0 +1,268 @@ +// --- 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. + */ +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..02d3cf80a --- /dev/null +++ b/pki/base/java-tools/src/com/netscape/cmstools/PKCS10Client.java @@ -0,0 +1,253 @@ +// --- 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.*; + + +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..7ce92c59a --- /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..388fedcd8 --- /dev/null +++ b/pki/base/java-tools/src/com/netscape/cmstools/PasswordCache.java @@ -0,0 +1,852 @@ +// --- 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: 14569 $, $Date: 2007-05-01 10:50:46 -0700 (Tue, 01 May 2007) $ + */ + +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: 14569 $, $Date: 2007-05-01 10:50:46 -0700 (Tue, 01 May 2007) $ + */ +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(); + tmpPWcache = new File(mPWcachedb + ".tmp"); + } + FileOutputStream outstream = new FileOutputStream(mPWcachedb + ".tmp"); + + outstream.write(writebuf); + outstream.close(); + + File origFile = new File(mPWcachedb); + + try { + if (tmpPWcache.renameTo(origFile) == true) { + debug("operation completed for " + mPWcachedb); + } else { + if (isNT()) { + // NT is very picky on the path + exec("copy " + + tmpPWcache.getAbsolutePath().replace('/', '\\') + " " + + origFile.getAbsolutePath().replace('/', '\\')); + } else { + exec("cp " + tmpPWcache.getAbsolutePath() + " " + + origFile.getAbsolutePath()); + } + } + } 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..8d6d22a6c --- /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 <input filename> [output filename] + * + * NOTE: <input filename> must contain an ASCII + * BASE 64 encoded certificate + * + * [output filename] contains a certificate displayed + * in a "pretty print" ASCII format + * </PRE> + * + * @version $Revision: 14569 $, $Date: 2007-05-01 10:50:46 -0700 (Tue, 01 May 2007) $ + */ + +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..ea9b68e7a --- /dev/null +++ b/pki/base/java-tools/src/com/netscape/cmstools/PrettyPrintCrl.java @@ -0,0 +1,193 @@ +// --- 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 <input filename> [output filename] + * + * NOTE: <input filename> must contain an ASCII + * BASE 64 encoded CRL + * + * [output filename] contains a CRL displayed + * in a "pretty print" ASCII format + * </PRE> + * + * @version $Revision: 14569 $, $Date: 2007-05-01 10:50:46 -0700 (Tue, 01 May 2007) $ + */ + +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) { + } + + // (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..240f60d27 --- /dev/null +++ b/pki/base/java-tools/src/com/netscape/cmstools/TestCRLSigning.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 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; + + +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..c24fa3afe --- /dev/null +++ b/pki/base/java-tools/src/com/netscape/cmstools/TokenInfo.java @@ -0,0 +1,91 @@ +// --- 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.*; + + + +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/pki_java_command_wrapper b/pki/base/java-tools/templates/pki_java_command_wrapper new file mode 100644 index 000000000..5fdf46622 --- /dev/null +++ b/pki/base/java-tools/templates/pki_java_command_wrapper @@ -0,0 +1,144 @@ +#!/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=`pkiname` +ARCHITECTURE=`pkiarch` + +if [ "${OS}" = "Linux" ] ; then + JAVA="java" + JAVA_OPTIONS="" + + if [ "${ARCHITECTURE}" = "i386" ] ; then + 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}" = "x86_64" ] ; then + 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/lib64:/lib64:${LD_LIBRARY_PATH} + LD_LIBRARY_PATH=/usr/lib64/dirsec:${LD_LIBRARY_PATH} + LD_LIBRARY_PATH=/usr/lib64/${PRODUCT}:${LD_LIBRARY_PATH} + export LD_LIBRARY_PATH + else + invalid_architecture "${ARCHITECTURE}" + exit 255 + fi +elif [ "${OS}" = "SunOS" ] ; then + 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/share/java/ldapjdk.jar:${CP} +CP=/usr/share/java/${PRODUCT}/nsutil.jar:${CP} +CP=/usr/share/java/${PRODUCT}/cmsutil.jar:${CP} +CP=/usr/share/java/${PRODUCT}/cstools.jar:${CP} +CP=/usr/share/${PRODUCT}/classes:${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 $? + |