diff options
Diffstat (limited to 'security/nss/cmd/certcgi')
-rw-r--r-- | security/nss/cmd/certcgi/HOWTO.txt | 137 | ||||
-rw-r--r-- | security/nss/cmd/certcgi/Makefile | 48 | ||||
-rw-r--r-- | security/nss/cmd/certcgi/ca.html | 19 | ||||
-rw-r--r-- | security/nss/cmd/certcgi/ca_form.html | 357 | ||||
-rw-r--r-- | security/nss/cmd/certcgi/certcgi.c | 2246 | ||||
-rw-r--r-- | security/nss/cmd/certcgi/certcgi.gyp | 33 | ||||
-rw-r--r-- | security/nss/cmd/certcgi/index.html | 789 | ||||
-rw-r--r-- | security/nss/cmd/certcgi/main.html | 76 | ||||
-rw-r--r-- | security/nss/cmd/certcgi/manifest.mn | 22 | ||||
-rw-r--r-- | security/nss/cmd/certcgi/nscp_ext_form.html | 84 | ||||
-rw-r--r-- | security/nss/cmd/certcgi/stnd_ext_form.html | 219 |
11 files changed, 4030 insertions, 0 deletions
diff --git a/security/nss/cmd/certcgi/HOWTO.txt b/security/nss/cmd/certcgi/HOWTO.txt new file mode 100644 index 000000000..54edf8e1a --- /dev/null +++ b/security/nss/cmd/certcgi/HOWTO.txt @@ -0,0 +1,137 @@ + How to setup your very own Cert-O-Matic Root CA server + + This Source Code Form is subject to the terms of the Mozilla Public + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + + How to setup your very own Cert-O-Matic Root CA server + +The program certcgi is part of a small test CA that is used inside +Netscape by the NSS development team. That CA is affectionately known +as "Cert-O-Matic" or "Cert-O-Matic II". It presently runs on a server +named interzone.mcom.com inside Netscape's firewall. + +If you wish to setup your own Cert-O-Matic, here are directions. + +Disclaimer: This program does not follow good practices for root CAs. +It should be used only for playing/testing and never for production use. +Remember, you've been warned! + +Cert-O-Matic consists of some html files, shell scripts, one executable +program that uses NSS and NSPR, the usual set of NSS .db files, and a file +in which to remember the serial number of the last cert issued. The +html files and the source to the executable program are in this directory. +Sample shell scripts are shown below. + +The shell scripts and executable program run as CGI "scripts". The +entire thing runs on an ordinary http web server. It would also run on +an https web server. The shell scripts and html files must be +customized for the server on which they run. + +The package assumes you have a "document root" directory $DOCROOT, and a +"cgi-bin" directory $CGIBIN. In this example, the document root is +assumed to be located in /var/www/htdocs, and the cgi-bin directory in +/var/www/cgi-bin. + +The server is assumed to run all cgi scripts as the user "nobody". +The names of the cgi scripts run directly by the server all end in .cgi +because some servers like it that way. + +Instructions: + +- Create directory $DOCROOT/certomatic +- Copy the following files from nss/cmd/certcgi to $DOCROOT/certomatic + ca.html index.html main.html nscp_ext_form.html stnd_ext_form.html +- Edit the html files, substituting the name of your own server for the + server named in those files. +- In some web page (e.g. your server's home page), provide an html link to + $DOCROOT/certomatic/index.html. This is where users start to get their + own certs from certomatic. +- give these files and directories appropriate permissions. + +- Create directories $CGIBIN/certomatic and $CGIBIN/certomatic/bin + make sure that $CGIBIN/certomatic is writable by "nobody" + +- Create a new set of NSS db files there with the following command: + + certutil -N -d $CGIBIN/certomatic + +- when certutil prompts you for the password, enter the word foo + because that is compiled into the certcgi program. + +- Create the new Root CA cert with this command + + certutil -S -x -d $CGIBIN/certomatic -n "Cert-O-Matic II" \ + -s "CN=Cert-O-Matic II, O=Cert-O-Matic II" -t TCu,cu,cu -k rsa \ + -g 1024 -m 10001 -v 60 + + (adjust the -g, -m and -v parameters to taste. -s and -x must be as +shown.) + +- dump out the new root CA cert in base64 encoding: + + certutil -d $CGIBIN/certomatic -L -n "Cert-O-Matic II" -a > \ + $CGIBIN/certomatic/root.cacert + +- In $CGIBIN/certomatic/bin add two shell scripts - one to download the + root CA cert on demand, and one to run the certcgi program. + +download.cgi, the script to install the root CA cert into a browser on +demand, is this: + +#!/bin/sh +echo "Content-type: application/x-x509-ca-cert" +echo +cat $CGIBIN/certomatic/root.cacert + +You'll have to put the real path into that cat command because CGIBIN +won't be defined when this script is run by the server. + +certcgi.cgi, the script to run the certcgi program is similar to this: + +#!/bin/sh +cd $CGIBIN/certomatic/bin +LD_LIBRARY_PATH=$PLATFORM/lib +export LD_LIBRARY_PATH +$PLATFORM/bin/certcgi $* 2>&1 + +Where $PLATFORM/lib is where the NSPR nad NSS DSOs are located, and +$PLATFORM/bin is where certcgi is located. PLATFORM is not defined when +the server runs this script, so you'll have to substitute the right value +in your script. certcgi requires that the working directory be one level +below the NSS DBs, that is, the DBs are accessed in the directory "..". + +You'll want to provide an html link somewhere to the script that downloads +the root.cacert file. You'll probably want to put that next to the link +that loads the index.html page. On interzone, this is done with the +following html: + +<a href="/certomatic/index.html">Cert-O-Matic II Root CA server</a> +<p> +<a href="/cgi-bin/certomatic/bin/download.cgi">Download and trust Root CA +certificate</a> + +The index.html file in this directory invokes the certcgi.cgi script with +the form post method, so if you change the name of the certcgi.cgi script, +you'll also have to change the index.html file in $DOCROOT/certomatic + +The 4 files used by the certcgi program (the 3 NSS DBs, and the serial +number file) are not required to live in $CGIBIN/certomatic, but they are +required to live in $CWD/.. when certcgi starts. + +Known bugs: + +1. Because multiple of these CAs exist simultaneously, it would be best if +they didn't all have to be called "Cert-O-Matic II", but that string is +presently hard coded into certcgi.c. + +2. the html files in this directory contain numerous extraneous <FORM> tags +which appear to use the post method and have action URLS that are never +actually used. burp.cgi and echoform.cgi are never actually used. This +should be cleaned up. + +3. The html files use <layer> tags which are supported only in Netscape +Navigator and Netscape Communication 4.x browsers. The html files do +not work as intended with Netscape 6.x, Mozilla or Microsoft IE browsers. +The html files should be fixed to work with all those named browsers. + diff --git a/security/nss/cmd/certcgi/Makefile b/security/nss/cmd/certcgi/Makefile new file mode 100644 index 000000000..c2039d82b --- /dev/null +++ b/security/nss/cmd/certcgi/Makefile @@ -0,0 +1,48 @@ +#! gmake +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +####################################################################### +# (1) Include initial platform-independent assignments (MANDATORY). # +####################################################################### + +include manifest.mn + +####################################################################### +# (2) Include "global" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/config.mk + +####################################################################### +# (3) Include "component" configuration information. (OPTIONAL) # +####################################################################### + +####################################################################### +# (4) Include "local" platform-dependent assignments (OPTIONAL). # +####################################################################### + +include ../platlibs.mk + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### + + + +include ../platrules.mk + diff --git a/security/nss/cmd/certcgi/ca.html b/security/nss/cmd/certcgi/ca.html new file mode 100644 index 000000000..3f3f08699 --- /dev/null +++ b/security/nss/cmd/certcgi/ca.html @@ -0,0 +1,19 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<form method="post" name="ca_form" action="mailto:jerdonek@netscape.com"> +<input type="radio" name="caChoiceradio" value="SignWithDefaultkey" + onClick="{parent.choice_change(this.form)}"> + Use the Cert-O-matic certificate to issue the cert</p> +<input type="radio" name="caChoiceradio" value="SignWithRandomChain" + onClick="{parent.choice_change(this.form)}"> Use a + <input type="text" size="2" maxsize="2" name="autoCAs"> CA long + automatically generated chain ending with the Cert-O-Matic Cert + (18 maximum)</p> +<input type="radio" name="caChoiceradio" value="SignWithSpecifiedChain" + onClick="{parent.choice_change(this.form)}"> Use a + <input type="text" size="1" maxlength="1" name="manCAs" + onChange="{parent.ca_num_change(this.value,this.form)}"> CA long + user input chain ending in the Cert-O-Matic Cert.</p> +</form> diff --git a/security/nss/cmd/certcgi/ca_form.html b/security/nss/cmd/certcgi/ca_form.html new file mode 100644 index 000000000..452996b58 --- /dev/null +++ b/security/nss/cmd/certcgi/ca_form.html @@ -0,0 +1,357 @@ +<html> +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + <form method="post" name="primary_form" action="http://interzone.mcom.com/burp.cgi"> + <table border=0 cellspacing=10 cellpadding=0> + <tr> + <td> + Common Name:</td><td> <input type="text" name="name" onChange="{window.top.reset_subject('CN=', value, form)}"></p> + </td> + <td></td><td></td><td> + Mail: </td><td><input type="text" name="email" onChange="var temp;{if (email_type[0].checked) {temp = 'MAIL='} else {temp = 'E='}} ;{window.top.reset_subject(temp, value, form)}"></p> + RFC 1274<input type="radio" name="email_type" value="1" onClick="window.top.switch_mail(form)"> + e-mail<input type="radio" name="email_type" value="2" checked onClick="window.top.switch_mail(form)"></td> + <tr> + <td> + Organization: </td><td> <input type="text" name="org" onChange="{window.top.reset_subject('O=', value, form)}"></p></td> + <td></td><td></td><td> + Organizational Unit: </td><td><input type="text" name="org_unit" onChange="{window.top.reset_subject('OU=', value, form)}"></p></td> + <tr> + <td> + RFC 1274 UID: </td><td><input type="text" name="uid" onChange="{window.top.reset_subject('UID=', value, form)}"></p></td> + <td></td><td></td><td> + Locality: </td><td><input type="text" name="loc" onChange="{window.top.reset_subject('L=', value, form)}"></p></td> + <tr> + <td> + State or Province: </td><td><input type="text" name="state" onChange="{window.top.reset_subject('ST=', value, form)}"></p></td> + <td></td><td></td><td> + Country: </td><td><input type="text" size="2" maxsize="2" name="country" onChange="{window.top.reset_subject('C=', value, form)}"></p></td> + </table> + <table border=0 cellspacing=10 cellpadding=0> + <tr> + <td> + Serial Number:</p> + <DD> + <input type="radio" name="serial" value="auto" checked> Auto Generate</P> + <DD> + <input type="radio" name="serial" value="input"> + Use this value: <input type="text" name="serial_value" size="8" maxlength="8"></p> + </td> + <td></td><td></td><td></td><td></td> + <td> + X.509 version:</p> + <DD> + <input type="radio" name="ver" value="1" checked> Version 1</p> + <DD> + <input type="radio" name="ver" value="3"> Version 3</P></td> + <td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td> + <td> + Key Type:</p> + <DD> + <input type="radio" name="keyType" value="rsa" checked> RSA</p> + <DD> + <input type="radio" name="keyType" value="dsa"> DSA</P></td> + </table> + DN: <input type="text" name="subject" size="70" onChange="{window.top.reset_subjectFields(form)}"></P> + <Select name="keysize"> + <option>1024 (High Grade) + <option>768 (Medium Grade) + <option>512 (Low Grade) + </select> + </p> + <hr> + </p> + <table border=1 cellspacing=5 cellpadding=5> + <tr> + <td> + <b>Netscape Certificate Type: </b></p> + Activate extension: <input type="checkbox" name="netscape-cert-type"></P> + Critical: <input type="checkbox" name="netscape-cert-type-crit"> + <td> + <input type="checkbox" name="netscape-cert-type-ssl-client"> SSL Client</P> + <input type="checkbox" name="netscape-cert-type-ssl-server"> SSL Server</P> + <input type="checkbox" name="netscape-cert-type-smime"> S/MIME</P> + <input type="checkbox" name="netscape-cert-type-object-signing"> Object Signing</P> + <input type="checkbox" name="netscape-cert-type-reserved"> Reserved for future use (bit 4)</P> + <input type="checkbox" name="netscape-cert-type-ssl-ca"> SSL CA</P> + <input type="checkbox" name="netscape-cert-type-smime-ca"> S/MIME CA</P> + <input type="checkbox" name="netscape-cert-type-object-signing-ca"> Object Signing CA</P> + </tr> + <tr> + <td> + <b>Netscape Base URL:</b></p> + Activate extension: <input type="checkbox" name="netscape-base-url"></P> + Critical: <input type="checkbox" name="netscape-base-url-crit"> + <td> + <input type="text" name="netscape-base-url-text" size="50"> + </tr> + <tr> + <td> + <b>Netscape Revocation URL:</b></p> + Activate extension: <input type="checkbox" name="netscape-revocation-url"></P> + Critical: <input type="checkbox" name="netscape-revocation-url-crit"> + <td> + <input type="text" name="netscape-revocation-url-text" size="50"> + </tr> + <tr> + <td> + <b>Netscape CA Revocation URL:</b></p> + Activate extension: <input type="checkbox" name="netscape-ca-revocation-url"></P> + Critical: <input type="checkbox" name="netscape-ca-revocation-url-crit"> + <td> + <input type="text" name="netscape-ca-revocation-url-text" size="50"> + </tr> + <tr> + <td> + <b>Netscape Certificate Renewal URL:</b></p> + Activate extension: <input type="checkbox" name="netscape-cert-renewal-url"></P> + Critical: <input type="checkbox" name="netscape-cert-renewal-url-crit"> + <td> + <input type="text" name="netscape-cert-renewal-url-text" size="50"> + </tr> + <tr> + <td> + <b>Netscape CA Policy URL:</b></p> + Activate extension: <input type="checkbox" name="netscape-ca-policy-url"></P> + Critical: <input type="checkbox" name="netscape-ca-policy-url-crit"> + <td> + <input type="text" name="netscape-ca-policy-url-text" size="50"> + </tr> + <tr> + <td> + <b>Netscape SSL Server Name:</b></p> + Activate extension: <input type="checkbox" name="netscape-ssl-server-name"></P> + Critical: <input type="checkbox" name="netscape-ssl-server-name-crit"> + <td> + <input type="text" name="netscape-ssl-server-name-text" size="50"> + </tr> + <tr> + <td> + <b>Netscape Comment:</b></p> + Activate extension: <input type="checkbox" name="netscape-comment"></P> + Critical: <input type="checkbox" name="netscape-comment-crit"> + <td> + <textarea name="netscape-comment-text" rows="5" cols="50"></textarea> + </tr> + </table> + </p> + <hr> + </p> + <table border=1 cellspacing=5 cellpadding=5> + <form method="post" name="primary_form" action="http://interzone.mcom.com/burp.cgi"> + <tr> + <td> + <b>Key Usage: </b></p> + Activate extension: <input type="checkbox" name="keyUsage"></P> + Critical: <input type="checkbox" name="keyUsage-crit"> + <td> + <input type="checkbox" name="keyUsage-digitalSignature"> Digital Signature</P> + <input type="checkbox" name="keyUsage-nonRepudiation"> Non Repudiation</P> + <input type="checkbox" name="keyUsage-keyEncipherment"> Key Encipherment</P> + <input type="checkbox" name="keyUsage-dataEncipherment"> Data Encipherment</P> + <input type="checkbox" name="keyUsage-keyAgreement"> Key Agreement</P> + <input type="checkbox" name="keyUsage-keyCertSign"> Key Certificate Signing</P> + <input type="checkbox" name="keyUsage-cRLSign"> CRL Signing</P> + </tr> + <tr> + <td> + <b>Extended Key Usage: </b></p> + Activate extension: <input type="checkbox" name="extKeyUsage"></P> + Critical: <input type="checkbox" name="extKeyUsage-crit"> + <td> + <input type="checkbox" name="extKeyUsage-serverAuth"> Server Auth</P> + <input type="checkbox" name="extKeyUsage-clientAuth"> Client Auth</P> + <input type="checkbox" name="extKeyUsage-codeSign"> Code Signing</P> + <input type="checkbox" name="extKeyUsage-emailProtect"> Email Protection</P> + <input type="checkbox" name="extKeyUsage-timeStamp"> Timestamp</P> + <input type="checkbox" name="extKeyUsage-ocspResponder"> OCSP Responder</P> + <input type="checkbox" name="extKeyUsage-NS-govtApproved"> Step-up</P> + <input type="checkbox" name="extKeyUsage-msTrustListSign"> Microsoft Trust List Signing</P> + </tr> + <tr> + <td> + <b>Basic Constraints:</b></p> + Activate extension: <input type="checkbox" name="basicConstraints"></P> + Critical: <input type="checkbox" name="basicConstraints-crit"> + <td> + CA:</p> + <dd><input type=radio name="basicConstraints-cA-radio" value="CA"> True</p> + <dd><input type=radio name="basicConstraints-cA-radio" value="NotCA"> False</p> + <input type="checkbox" name="basicConstraints-pathLengthConstraint"> + Include Path length: <input type="text" name="basicConstraints-pathLengthConstraint-text" size="2"></p> + </tr> + <tr> + <td> + <b>Authority Key Identifier:</b></p> + Activate extension: <input type="checkbox" name="authorityKeyIdentifier"> + <td> + <input type="radio" name="authorityKeyIdentifier-radio" value="keyIdentifier"> Key Identider</p> + <input type="radio" name="authorityKeyIdentifier-radio" value="authorityCertIssuer"> Issuer Name and Serial number</p> + </tr> + <tr> + <td> + <b>Subject Key Identifier:</b></p> + Activate extension: <input type="checkbox" name="subjectKeyIdentifier"> + <td> + Key Identifier: + <input type="text" name="subjectKeyIdentifier-text"></p> + This is an:<p> + <dd><dd><input type="radio" name="subjectKeyIdentifier-radio" value="ascii"> ascii text value<p> + <dd><dd><input type="radio" name="subjectKeyIdentifier-radio" value="hex"> hex value<p> + </tr> + <tr> + <td> + <b>Private Key Usage Period:</b></p> + Activate extension: <input type="checkbox" name="privKeyUsagePeriod"></p> + Critical: <input type="checkbox" name="privKeyUsagePeriod-crit"> + <td> + Use:</p> + <dd><input type="radio" name="privKeyUsagePeriod-radio" value="notBefore"> Not Before</p> + <dd><input type="radio" name="privKeyUsagePeriod-radio" value="notAfter"> Not After</p> + <dd><input type="radio" name="privKeyUsagePeriod-radio" value="both" > Both</p> + <b>Not to be used to sign before:</b></p> + <dd><input type="radio" name="privKeyUsagePeriod-notBefore-radio" value="auto"> Set to time of certificate issue</p> + <dd><input type="radio" name="privKeyUsagePeriod-notBefore-radio" value="manual"> Use This value</p> + <dd><dd>(YYYY/MM/DD HH:MM:SS): + <input type="text" name="privKeyUsagePeriod-notBefore-year" size="4" maxlength="4">/ + <input type="text" name="privKeyUsagePeriod-notBefore-month" size="2" maxlength="2">/ + <input type="text" name="privKeyUsagePeriod-notBefore-day" size="2" maxlength="2"> + <input type="text" name="privKeyUsagePeriod-notBefore-hour" size="2" maxlength="2">: + <input type="text" name="privKeyUsagePeriod-notBefore-minute" size="2" maxlength="2">: + <input type="text" name="privKeyUsagePeriod-notBefore-second" size="2" maxlength="2"></p> + <b>Not to be used to sign after:</b></p> + <dd>(YYYY/MM/DD HH:MM:SS): + <input type="text" name="privKeyUsagePeriod-notAfter-year" size="4" maxlength="4">/ + <input type="text" name="privKeyUsagePeriod-notAfter-month" size="2" maxlength="2">/ + <input type="text" name="privKeyUsagePeriod-notAfter-day" size="2" maxlength="2"> + <input type="text" name="privKeyUsagePeriod-notAfter-hour" size="2" maxlength="2">: + <input type="text" name="privKeyUsagePeriod-notAfter-minute" size="2" maxlength="2">: + <input type="text" name="privKeyUsagePeriod-notAfter-second" size="2" maxlength="2"></p> + </tr> + <tr> + <td> + <b>Subject Alternative Name:</b></p> + Activate extension: <input type="checkbox" name="SubAltName"></P> + Critical: <input type="checkbox" name="SubAltName-crit"> + <td> + <table> + <tr> + <td> + General Names:</p> + <select name="SubAltNameSelect" multiple size="10"> + </select></p></p> + <input type="button" name="SubAltName-add" value="Add" onClick="{parent.addSubAltName(this.form)}"> + <input type="button" name="SubAltName-delete" value="Delete" onClick="parent.deleteSubAltName(this.form)"> + </td><td> + <table><tr><td> + Name Type: </td></tr><tr><td> + <input type="radio" name="SubAltNameRadio" value="otherName" onClick="parent.setSubAltNameType(form)"> Other Name, + OID: <input type="text" name="SubAltNameOtherNameOID" size="6"> </td><td> + <input type="radio" name="SubAltNameRadio" value="rfc822Name" onClick="parent.setSubAltNameType(form)"> RFC 822 Name</td></tr><td> + <input type="radio" name="SubAltNameRadio" value="dnsName" onClick="parent.setSubAltNameType(form)"> DNS Name </td><td> + <input type="radio" name="SubAltNameRadio" value="x400" onClick="parent.setSubAltNameType(form)"> X400 Address</td></tr><td> + <input type="radio" name="SubAltNameRadio" value="directoryName" onClick="parent.setSubAltNameType(form)"> Directory Name</td><td> + <input type="radio" name="SubAltNameRadio" value="ediPartyName" onClick="parent.setSubAltNameType(form)"> EDI Party Name</td></tr><td> + <input type="radio" name="SubAltNameRadio" value="URL" onClick="parent.setSubAltNameType(form)"> Uniform Resource Locator</td><td> + <input type="radio" name="SubAltNameRadio" value="ipAddress" onClick="parent.setSubAltNameType(form)"> IP Address</td></tr><td> + <input type="radio" name="SubAltNameRadio" value="regID"onClick="parent.setSubAltNameType(form)"> Registered ID</td><td> + <input type="radio" name="SubAltNameRadio" value="nscpNickname" onClick="parent.setSubAltNameType(form)"> Netscape Certificate Nickname</td><td></tr> + </table> + Name: <input type="text" name="SubAltNameText"> + Binary Encoded: <input type="checkbox" name="SubAltNameDataType" value="binary" onClick="parent.setSubAltNameType(form)"></p> + </tr> + </table> + </tr> + + + <tr> + <td> + <b>Issuer Alternative Name:</b></p> + Activate extension: <input type="checkbox" name="IssuerAltName"></P> + Critical: <input type="checkbox" name="IssuerAltName-crit"> + <td> + <input type="radio" name="IssuerAltNameSourceRadio" value="auto"> Use the Subject Alternative Name from the Issuers Certificate</p> + <input type="radio" name="IssuerAltNameSourceRadio" value="man"> Use this Name: + <table> + <tr> + <td> + General Names:</p> + <select name="IssuerAltNameSelect" multiple size="10"> + </select></p></p> + <input type="button" name="IssuerAltName-add" value="Add" onClick="{parent.addIssuerAltName(this.form)}"> + <input type="button" name="IssuerAltName-delete" value="Delete" onClick="parent.deleteIssuerAltName(this.form)"> + </td><td> + <table><tr><td> + Name Type: </td></tr><tr><td> + <input type="radio" name="IssuerAltNameRadio" value="otherName" onClick="parent.setIssuerAltNameType(form)"> Other Name, + OID: <input type="text" name="IssuerAltNameOtherNameOID" size="6"> </td><td> + <input type="radio" name="IssuerAltNameRadio" value="rfc822Name" onClick="parent.setIssuerAltNameType(form)"> RFC 822 Name</td></tr><td> + <input type="radio" name="IssuerAltNameRadio" value="dnsName" onClick="parent.setIssuerAltNameType(form)"> DNS Name </td><td> + <input type="radio" name="IssuerAltNameRadio" value="x400" onClick="parent.setIssuerAltNameType(form)"> X400 Address</td></tr><td> + <input type="radio" name="IssuerAltNameRadio" value="directoryName" onClick="parent.setIssuerAltNameType(form)"> Directory Name</td><td> + <input type="radio" name="IssuerAltNameRadio" value="ediPartyName" onClick="parent.setIssuerAltNameType(form)"> EDI Party Name</td></tr><td> + <input type="radio" name="IssuerAltNameRadio" value="URL" onClick="parent.setIssuerAltNameType(form)"> Uniform Resource Locator</td><td> + <input type="radio" name="IssuerAltNameRadio" value="ipAddress" onClick="parent.setIssuerAltNameType(form)"> IP Address</td></tr><td> + <input type="radio" name="IssuerAltNameRadio" value="regID" onClick="parent.setIssuerAltNameType(form)"> Registered ID</td><td></tr> + </table> + Name: <input type="text" name="IssuerAltNameText"> + Binary Encoded: <input type="checkbox" name="IssuerAltNameDataType" value="binary" onClick="parent.setIssuerAltNameType(form)"></p> + </tr> + </table> + </tr> + + <tr> + <td> + <b>Name Constraints:</b></p> + Activate extension: <input type="checkbox" name="NameConstraints"></P> + <td> + <table> + <tr> + <td> + Name Constraints:</p> + + + <select name="NameConstraintSelect" multiple size="10"> + </select></p></p> + <input type="button" name="NameConstraint-add" value="Add" onClick="{parent.addNameConstraint(this.form)}"> + <input type="button" name="NameConstraint-delete" value="Delete" onClick="parent.deleteNameConstraint(this.form)"> + </td><td> + <table><tr><td> + Name Type: </td></tr><tr><td> + <input type="radio" name="NameConstraintRadio" value="otherName" onClick="parent.setNameConstraintNameType(form)"> Other Name, + OID: <input type="text" name="NameConstraintOtherNameOID" size="6"> </td><td> + <input type="radio" name="NameConstraintRadio" value="rfc822Name" onClick="parent.setNameConstraintNameType(form)"> RFC 822 Name</td></tr><td> + <input type="radio" name="NameConstraintRadio" value="dnsName" onClick="parent.setNameConstraintNameType(form)"> DNS Name </td><td> + <input type="radio" name="NameConstraintRadio" value="x400" onClick="parent.setNameConstraintNameType(form)"> X400 Address</td></tr><td> + <input type="radio" name="NameConstraintRadio" value="directoryName" onClick="parent.setNameConstraintNameType(form)"> Directory Name</td><td> + <input type="radio" name="NameConstraintRadio" value="ediPartyName" onClick="parent.setNameConstraintNameType(form)"> EDI Party Name</td></tr><td> + <input type="radio" name="NameConstraintRadio" value="URL" onClick="parent.setNameConstraintNameType(form)"> Uniform Resource Locator</td><td> + <input type="radio" name="NameConstraintRadio" value="ipAddress" onClick="parent.setNameConstraintNameType(form)"> IP Address</td></tr><td> + <input type="radio" name="NameConstraintRadio" value="regID" onClick="parent.setNameConstraintNameType(form)"> Registered ID</td><td></tr> + </table> + Name: <input type="text" name="NameConstraintText"> + Binary Encoded: <input type="checkbox" name="NameConstraintNameDataType" value="binary" onClick="parent.setNameConstraintNameType(form)"></p> + Constraint type:<p> + <dd><input type="radio" name="NameConstraintTypeRadio" value="permited"> permited<p> + <dd><input type="radio" name="NameConstraintTypeRadio" value="excluded"> excluded<p> + Minimum: <input type="text" name="NameConstraintMin" size="8" maxlength="8"></p> + Maximum: <input type="text" name="NameConstraintMax" size="8" maxlength="8"></p> + + + + </tr> + </table> + </tr> + </table> + </form> + + + + + + + + + + diff --git a/security/nss/cmd/certcgi/certcgi.c b/security/nss/cmd/certcgi/certcgi.c new file mode 100644 index 000000000..35409e250 --- /dev/null +++ b/security/nss/cmd/certcgi/certcgi.c @@ -0,0 +1,2246 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Cert-O-Matic CGI */ + +#include "nspr.h" +#include "prtypes.h" +#include "prtime.h" +#include "prlong.h" + +#include "pk11func.h" +#include "cert.h" +#include "cryptohi.h" +#include "secoid.h" +#include "secder.h" +#include "genname.h" +#include "xconst.h" +#include "secutil.h" +#include "pk11pqg.h" +#include "certxutl.h" +#include "nss.h" + +/* #define TEST 1 */ +/* #define FILEOUT 1 */ +/* #define OFFLINE 1 */ +#define START_FIELDS 100 +#define PREFIX_LEN 6 +#define SERIAL_FILE "../serial" +#define DB_DIRECTORY ".." + +static char *progName; + +typedef struct PairStr Pair; + +struct PairStr { + char *name; + char *data; +}; + +char prefix[PREFIX_LEN]; + +const SEC_ASN1Template CERTIA5TypeTemplate[] = { + { SEC_ASN1_IA5_STRING } +}; + +SECKEYPrivateKey *privkeys[9] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL }; + +#ifdef notdef +const SEC_ASN1Template CERT_GeneralNameTemplate[] = { + { SEC_ASN1_SEQUENCE_OF, 0, SEC_AnyTemplate } +}; +#endif + +static void +error_out(char *error_string) +{ + printf("Content-type: text/plain\n\n"); + printf("%s", error_string); + fflush(stderr); + fflush(stdout); + exit(1); +} + +static void +error_allocate(void) +{ + error_out("ERROR: Unable to allocate memory"); +} + +static char * +make_copy_string(char *read_pos, + int length, + char sentinal_value) +/* copys string from to a new string it creates and + returns a pointer to the new string */ +{ + int remaining = length; + char *write_pos; + char *new; + + new = write_pos = (char *)PORT_Alloc(length); + if (new == NULL) { + error_allocate(); + } + while (*read_pos != sentinal_value) { + if (remaining == 1) { + remaining += length; + length = length * 2; + new = PORT_Realloc(new, length); + if (new == NULL) { + error_allocate(); + } + write_pos = new + length - remaining; + } + *write_pos = *read_pos; + ++write_pos; + ++read_pos; + remaining = remaining - 1; + } + *write_pos = '\0'; + return new; +} + +static SECStatus +clean_input(Pair *data) +/* converts the non-alphanumeric characters in a form post + from hex codes back to characters */ +{ + int length; + int hi_digit; + int low_digit; + char character; + char *begin_pos; + char *read_pos; + char *write_pos; + PRBool name = PR_TRUE; + + begin_pos = data->name; + while (begin_pos != NULL) { + length = strlen(begin_pos); + read_pos = write_pos = begin_pos; + while ((read_pos - begin_pos) < length) { + if (*read_pos == '+') { + *read_pos = ' '; + } + if (*read_pos == '%') { + hi_digit = *(read_pos + 1); + low_digit = *(read_pos + 2); + read_pos += 3; + if (isdigit(hi_digit)) { + hi_digit = hi_digit - '0'; + } else { + hi_digit = toupper(hi_digit); + if (isxdigit(hi_digit)) { + hi_digit = (hi_digit - 'A') + 10; + } else { + error_out("ERROR: Form data incorrectly formated"); + } + } + if (isdigit(low_digit)) { + low_digit = low_digit - '0'; + } else { + low_digit = toupper(low_digit); + if ((low_digit >= 'A') && (low_digit <= 'F')) { + low_digit = (low_digit - 'A') + 10; + } else { + error_out("ERROR: Form data incorrectly formated"); + } + } + character = (hi_digit << 4) | low_digit; + if (character != 10) { + *write_pos = character; + ++write_pos; + } + } else { + *write_pos = *read_pos; + ++write_pos; + ++read_pos; + } + } + *write_pos = '\0'; + if (name == PR_TRUE) { + begin_pos = data->data; + name = PR_FALSE; + } else { + data++; + begin_pos = data->name; + name = PR_TRUE; + } + } + return SECSuccess; +} + +static char * +make_name(char *new_data) +/* gets the next field name in the input string and returns + a pointer to a string containing a copy of it */ +{ + int length = 20; + char *name; + + name = make_copy_string(new_data, length, '='); + return name; +} + +static char * +make_data(char *new_data) +/* gets the data for the next field in the input string + and returns a pointer to a string containing it */ +{ + int length = 100; + char *data; + char *read_pos; + + read_pos = new_data; + while (*(read_pos - 1) != '=') { + ++read_pos; + } + data = make_copy_string(read_pos, length, '&'); + return data; +} + +static Pair +make_pair(char *new_data) +/* makes a pair name/data pair from the input string */ +{ + Pair temp; + + temp.name = make_name(new_data); + temp.data = make_data(new_data); + return temp; +} + +static Pair * +make_datastruct(char *data, int len) +/* parses the input from the form post into a data + structure of field name/data pairs */ +{ + Pair *datastruct; + Pair *current; + char *curr_pos; + int fields = START_FIELDS; + int remaining = START_FIELDS; + + curr_pos = data; + datastruct = current = (Pair *)PORT_Alloc(fields * sizeof(Pair)); + if (datastruct == NULL) { + error_allocate(); + } + while (curr_pos - data < len) { + if (remaining == 1) { + remaining += fields; + fields = fields * 2; + datastruct = (Pair *)PORT_Realloc(datastruct, fields * + sizeof(Pair)); + if (datastruct == NULL) { + error_allocate(); + } + current = datastruct + (fields - remaining); + } + *current = make_pair(curr_pos); + while (*curr_pos != '&') { + ++curr_pos; + } + ++curr_pos; + ++current; + remaining = remaining - 1; + } + current->name = NULL; + return datastruct; +} + +static char * +return_name(Pair *data_struct, + int n) +/* returns a pointer to the name of the nth + (starting from 0) item in the data structure */ +{ + char *name; + + if ((data_struct + n)->name != NULL) { + name = (data_struct + n)->name; + return name; + } else { + return NULL; + } +} + +static char * +return_data(Pair *data_struct, int n) +/* returns a pointer to the data of the nth (starting from 0) + itme in the data structure */ +{ + char *data; + + data = (data_struct + n)->data; + return data; +} + +static char * +add_prefix(char *field_name) +{ + extern char prefix[PREFIX_LEN]; + int i = 0; + char *rv; + char *write; + + rv = write = PORT_Alloc(PORT_Strlen(prefix) + PORT_Strlen(field_name) + 1); + for (i = 0; i < PORT_Strlen(prefix); i++) { + *write = prefix[i]; + write++; + } + *write = '\0'; + rv = PORT_Strcat(rv, field_name); + return rv; +} + +static char * +find_field(Pair *data, + char *field_name, + PRBool add_pre) +/* returns a pointer to the data of the first pair + thats name matches the string it is passed */ +{ + int i = 0; + char *retrieved; + int found = 0; + + if (add_pre) { + field_name = add_prefix(field_name); + } + while (return_name(data, i) != NULL) { + if (PORT_Strcmp(return_name(data, i), field_name) == 0) { + retrieved = return_data(data, i); + found = 1; + break; + } + i++; + } + if (!found) { + retrieved = NULL; + } + return retrieved; +} + +static PRBool +find_field_bool(Pair *data, + char *fieldname, + PRBool add_pre) +{ + char *rv; + + rv = find_field(data, fieldname, add_pre); + + if ((rv != NULL) && (PORT_Strcmp(rv, "true")) == 0) { + return PR_TRUE; + } else { + return PR_FALSE; + } +} + +static CERTCertificateRequest * +makeCertReq(Pair *form_data, + int which_priv_key) +/* makes and encodes a certrequest */ +{ + + PK11SlotInfo *slot; + CERTCertificateRequest *certReq = NULL; + CERTSubjectPublicKeyInfo *spki; + SECKEYPrivateKey *privkey = NULL; + SECKEYPublicKey *pubkey = NULL; + CERTName *name; + char *key; + extern SECKEYPrivateKey *privkeys[9]; + int keySizeInBits; + char *challenge = "foo"; + SECStatus rv = SECSuccess; + PQGParams *pqgParams = NULL; + PQGVerify *pqgVfy = NULL; + + name = CERT_AsciiToName(find_field(form_data, "subject", PR_TRUE)); + if (name == NULL) { + error_out("ERROR: Unable to create Subject Name"); + } + key = find_field(form_data, "key", PR_TRUE); + if (key == NULL) { + switch (*find_field(form_data, "keysize", PR_TRUE)) { + case '0': + keySizeInBits = 2048; + break; + case '1': + keySizeInBits = 1024; + break; + case '2': + keySizeInBits = 512; + break; + default: + error_out("ERROR: Unsupported Key length selected"); + } + if (find_field_bool(form_data, "keyType-dsa", PR_TRUE)) { + rv = PK11_PQG_ParamGen(keySizeInBits, &pqgParams, &pqgVfy); + if (rv != SECSuccess) { + error_out("ERROR: Unable to generate PQG parameters"); + } + slot = PK11_GetBestSlot(CKM_DSA_KEY_PAIR_GEN, NULL); + privkey = PK11_GenerateKeyPair(slot, CKM_DSA_KEY_PAIR_GEN, + pqgParams, &pubkey, PR_FALSE, + PR_TRUE, NULL); + } else { + privkey = SECKEY_CreateRSAPrivateKey(keySizeInBits, &pubkey, NULL); + } + privkeys[which_priv_key] = privkey; + spki = SECKEY_CreateSubjectPublicKeyInfo(pubkey); + } else { + spki = SECKEY_ConvertAndDecodePublicKeyAndChallenge(key, challenge, + NULL); + if (spki == NULL) { + error_out("ERROR: Unable to decode Public Key and Challenge String"); + } + } + certReq = CERT_CreateCertificateRequest(name, spki, NULL); + if (certReq == NULL) { + error_out("ERROR: Unable to create Certificate Request"); + } + if (pubkey != NULL) { + SECKEY_DestroyPublicKey(pubkey); + } + if (spki != NULL) { + SECKEY_DestroySubjectPublicKeyInfo(spki); + } + if (pqgParams != NULL) { + PK11_PQG_DestroyParams(pqgParams); + } + if (pqgVfy != NULL) { + PK11_PQG_DestroyVerify(pqgVfy); + } + return certReq; +} + +static CERTCertificate * +MakeV1Cert(CERTCertDBHandle *handle, + CERTCertificateRequest *req, + char *issuerNameStr, + PRBool selfsign, + int serialNumber, + int warpmonths, + Pair *data) +{ + CERTCertificate *issuerCert = NULL; + CERTValidity *validity; + CERTCertificate *cert = NULL; + PRExplodedTime printableTime; + PRTime now, + after; + if (!selfsign) { + issuerCert = CERT_FindCertByNameString(handle, issuerNameStr); + if (!issuerCert) { + error_out("ERROR: Could not find issuer's certificate"); + return NULL; + } + } + if (find_field_bool(data, "manValidity", PR_TRUE)) { + (void)DER_AsciiToTime(&now, find_field(data, "notBefore", PR_TRUE)); + } else { + now = PR_Now(); + } + PR_ExplodeTime(now, PR_GMTParameters, &printableTime); + if (warpmonths) { + printableTime.tm_month += warpmonths; + now = PR_ImplodeTime(&printableTime); + PR_ExplodeTime(now, PR_GMTParameters, &printableTime); + } + if (find_field_bool(data, "manValidity", PR_TRUE)) { + (void)DER_AsciiToTime(&after, find_field(data, "notAfter", PR_TRUE)); + PR_ExplodeTime(after, PR_GMTParameters, &printableTime); + } else { + printableTime.tm_month += 3; + after = PR_ImplodeTime(&printableTime); + } + /* note that the time is now in micro-second unit */ + validity = CERT_CreateValidity(now, after); + + if (selfsign) { + cert = CERT_CreateCertificate(serialNumber, &(req->subject), validity, req); + } else { + cert = CERT_CreateCertificate(serialNumber, &(issuerCert->subject), validity, req); + } + + CERT_DestroyValidity(validity); + if (issuerCert) { + CERT_DestroyCertificate(issuerCert); + } + return (cert); +} + +static int +get_serial_number(Pair *data) +{ + int serial = 0; + int error; + char *filename = SERIAL_FILE; + char *SN; + FILE *serialFile; + + if (find_field_bool(data, "serial-auto", PR_TRUE)) { + serialFile = fopen(filename, "r"); + if (serialFile != NULL) { + size_t nread = fread(&serial, sizeof(int), 1, serialFile); + if (ferror(serialFile) != 0 || nread != 1) { + error_out("Error: Unable to read serial number file"); + } + if (serial == -1) { + serial = 21; + } + fclose(serialFile); + ++serial; + serialFile = fopen(filename, "w"); + if (serialFile == NULL) { + error_out("ERROR: Unable to open serial number file for writing"); + } + fwrite(&serial, sizeof(int), 1, serialFile); + if (ferror(serialFile) != 0) { + error_out("Error: Unable to write to serial number file"); + } + } else { + fclose(serialFile); + serialFile = fopen(filename, "w"); + if (serialFile == NULL) { + error_out("ERROR: Unable to open serial number file"); + } + serial = 21; + fwrite(&serial, sizeof(int), 1, serialFile); + if (ferror(serialFile) != 0) { + error_out("Error: Unable to write to serial number file"); + } + error = ferror(serialFile); + if (error != 0) { + error_out("ERROR: Unable to write to serial file"); + } + } + fclose(serialFile); + } else { + SN = find_field(data, "serial_value", PR_TRUE); + while (*SN != '\0') { + serial = serial * 16; + if ((*SN >= 'A') && (*SN <= 'F')) { + serial += *SN - 'A' + 10; + } else { + if ((*SN >= 'a') && (*SN <= 'f')) { + serial += *SN - 'a' + 10; + } else { + serial += *SN - '0'; + } + } + ++SN; + } + } + return serial; +} + +typedef SECStatus (*EXTEN_VALUE_ENCODER)(PLArenaPool *extHandle, void *value, SECItem *encodedValue); + +static SECStatus +EncodeAndAddExtensionValue( + PLArenaPool *arena, + void *extHandle, + void *value, + PRBool criticality, + int extenType, + EXTEN_VALUE_ENCODER EncodeValueFn) +{ + SECItem encodedValue; + SECStatus rv; + + encodedValue.data = NULL; + encodedValue.len = 0; + rv = (*EncodeValueFn)(arena, value, &encodedValue); + if (rv != SECSuccess) { + error_out("ERROR: Unable to encode extension value"); + } + rv = CERT_AddExtension(extHandle, extenType, &encodedValue, criticality, PR_TRUE); + return (rv); +} + +static SECStatus +AddKeyUsage(void *extHandle, + Pair *data) +{ + SECItem bitStringValue; + unsigned char keyUsage = 0x0; + + if (find_field_bool(data, "keyUsage-digitalSignature", PR_TRUE)) { + keyUsage |= (0x80 >> 0); + } + if (find_field_bool(data, "keyUsage-nonRepudiation", PR_TRUE)) { + keyUsage |= (0x80 >> 1); + } + if (find_field_bool(data, "keyUsage-keyEncipherment", PR_TRUE)) { + keyUsage |= (0x80 >> 2); + } + if (find_field_bool(data, "keyUsage-dataEncipherment", PR_TRUE)) { + keyUsage |= (0x80 >> 3); + } + if (find_field_bool(data, "keyUsage-keyAgreement", PR_TRUE)) { + keyUsage |= (0x80 >> 4); + } + if (find_field_bool(data, "keyUsage-keyCertSign", PR_TRUE)) { + keyUsage |= (0x80 >> 5); + } + if (find_field_bool(data, "keyUsage-cRLSign", PR_TRUE)) { + keyUsage |= (0x80 >> 6); + } + + bitStringValue.data = &keyUsage; + bitStringValue.len = 1; + + return (CERT_EncodeAndAddBitStrExtension(extHandle, SEC_OID_X509_KEY_USAGE, &bitStringValue, + (find_field_bool(data, "keyUsage-crit", PR_TRUE)))); +} + +static CERTOidSequence * +CreateOidSequence(void) +{ + CERTOidSequence *rv = (CERTOidSequence *)NULL; + PLArenaPool *arena = (PLArenaPool *)NULL; + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if ((PLArenaPool *)NULL == arena) { + goto loser; + } + + rv = (CERTOidSequence *)PORT_ArenaZAlloc(arena, sizeof(CERTOidSequence)); + if ((CERTOidSequence *)NULL == rv) { + goto loser; + } + + rv->oids = (SECItem **)PORT_ArenaZAlloc(arena, sizeof(SECItem *)); + if ((SECItem **)NULL == rv->oids) { + goto loser; + } + + rv->arena = arena; + return rv; + +loser: + if ((PLArenaPool *)NULL != arena) { + PORT_FreeArena(arena, PR_FALSE); + } + + return (CERTOidSequence *)NULL; +} + +static SECStatus +AddOidToSequence(CERTOidSequence *os, SECOidTag oidTag) +{ + SECItem **oids; + PRUint32 count = 0; + SECOidData *od; + + od = SECOID_FindOIDByTag(oidTag); + if ((SECOidData *)NULL == od) { + return SECFailure; + } + + for (oids = os->oids; (SECItem *)NULL != *oids; oids++) { + count++; + } + + /* ArenaZRealloc */ + + { + PRUint32 i; + + oids = (SECItem **)PORT_ArenaZAlloc(os->arena, sizeof(SECItem *) * (count + 2)); + if ((SECItem **)NULL == oids) { + return SECFailure; + } + + for (i = 0; i < count; i++) { + oids[i] = os->oids[i]; + } + + /* ArenaZFree(os->oids); */ + } + + os->oids = oids; + os->oids[count] = &od->oid; + + return SECSuccess; +} + +static SECItem * +EncodeOidSequence(CERTOidSequence *os) +{ + SECItem *rv; + extern const SEC_ASN1Template CERT_OidSeqTemplate[]; + + rv = (SECItem *)PORT_ArenaZAlloc(os->arena, sizeof(SECItem)); + if ((SECItem *)NULL == rv) { + goto loser; + } + + if (!SEC_ASN1EncodeItem(os->arena, rv, os, CERT_OidSeqTemplate)) { + goto loser; + } + + return rv; + +loser: + return (SECItem *)NULL; +} + +static SECStatus +AddExtKeyUsage(void *extHandle, Pair *data) +{ + SECStatus rv; + CERTOidSequence *os; + SECItem *value; + PRBool crit; + + os = CreateOidSequence(); + if ((CERTOidSequence *)NULL == os) { + return SECFailure; + } + + if (find_field_bool(data, "extKeyUsage-serverAuth", PR_TRUE)) { + rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_SERVER_AUTH); + if (SECSuccess != rv) + goto loser; + } + + if (find_field_bool(data, "extKeyUsage-msTrustListSign", PR_TRUE)) { + rv = AddOidToSequence(os, SEC_OID_MS_EXT_KEY_USAGE_CTL_SIGNING); + if (SECSuccess != rv) + goto loser; + } + + if (find_field_bool(data, "extKeyUsage-clientAuth", PR_TRUE)) { + rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH); + if (SECSuccess != rv) + goto loser; + } + + if (find_field_bool(data, "extKeyUsage-codeSign", PR_TRUE)) { + rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_CODE_SIGN); + if (SECSuccess != rv) + goto loser; + } + + if (find_field_bool(data, "extKeyUsage-emailProtect", PR_TRUE)) { + rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_EMAIL_PROTECT); + if (SECSuccess != rv) + goto loser; + } + + if (find_field_bool(data, "extKeyUsage-timeStamp", PR_TRUE)) { + rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_TIME_STAMP); + if (SECSuccess != rv) + goto loser; + } + + if (find_field_bool(data, "extKeyUsage-ocspResponder", PR_TRUE)) { + rv = AddOidToSequence(os, SEC_OID_OCSP_RESPONDER); + if (SECSuccess != rv) + goto loser; + } + + if (find_field_bool(data, "extKeyUsage-NS-govtApproved", PR_TRUE)) { + rv = AddOidToSequence(os, SEC_OID_NS_KEY_USAGE_GOVT_APPROVED); + if (SECSuccess != rv) + goto loser; + } + + value = EncodeOidSequence(os); + + crit = find_field_bool(data, "extKeyUsage-crit", PR_TRUE); + + rv = CERT_AddExtension(extHandle, SEC_OID_X509_EXT_KEY_USAGE, value, + crit, PR_TRUE); +/*FALLTHROUGH*/ +loser: + CERT_DestroyOidSequence(os); + return rv; +} + +static SECStatus +AddSubKeyID(void *extHandle, + Pair *data, + CERTCertificate *subjectCert) +{ + SECItem encodedValue; + SECStatus rv; + char *read; + char *write; + char *first; + char character; + int high_digit = 0, + low_digit = 0; + int len; + PRBool odd = PR_FALSE; + + encodedValue.data = NULL; + encodedValue.len = 0; + first = read = write = find_field(data, "subjectKeyIdentifier-text", + PR_TRUE); + len = PORT_Strlen(first); + odd = ((len % 2) != 0) ? PR_TRUE : PR_FALSE; + if (find_field_bool(data, "subjectKeyIdentifier-radio-hex", PR_TRUE)) { + if (odd) { + error_out("ERROR: Improperly formated subject key identifier, hex values must be expressed as an octet string"); + } + while (*read != '\0') { + if (!isxdigit(*read)) { + error_out("ERROR: Improperly formated subject key identifier"); + } + *read = toupper(*read); + if ((*read >= 'A') && (*read <= 'F')) { + high_digit = *read - 'A' + 10; + } else { + high_digit = *read - '0'; + } + ++read; + if (!isxdigit(*read)) { + error_out("ERROR: Improperly formated subject key identifier"); + } + *read = toupper(*read); + if ((*read >= 'A') && (*read <= 'F')) { + low_digit = *(read) - 'A' + 10; + } else { + low_digit = *(read) - '0'; + } + character = (high_digit << 4) | low_digit; + *write = character; + ++write; + ++read; + } + *write = '\0'; + len = write - first; + } + subjectCert->subjectKeyID.data = (unsigned char *)find_field(data, "subjectKeyIdentifier-text", PR_TRUE); + subjectCert->subjectKeyID.len = len; + rv = CERT_EncodeSubjectKeyID(NULL, &subjectCert->subjectKeyID, &encodedValue); + if (rv) { + return (rv); + } + return (CERT_AddExtension(extHandle, SEC_OID_X509_SUBJECT_KEY_ID, + &encodedValue, PR_FALSE, PR_TRUE)); +} + +static SECStatus +AddAuthKeyID(void *extHandle, + Pair *data, + char *issuerNameStr, + CERTCertDBHandle *handle) +{ + CERTAuthKeyID *authKeyID = NULL; + PLArenaPool *arena = NULL; + SECStatus rv = SECSuccess; + CERTCertificate *issuerCert = NULL; + CERTGeneralName *genNames; + CERTName *directoryName = NULL; + + issuerCert = CERT_FindCertByNameString(handle, issuerNameStr); + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (!arena) { + error_allocate(); + } + + authKeyID = PORT_ArenaZAlloc(arena, sizeof(CERTAuthKeyID)); + if (authKeyID == NULL) { + error_allocate(); + } + if (find_field_bool(data, "authorityKeyIdentifier-radio-keyIdentifier", + PR_TRUE)) { + authKeyID->keyID.data = PORT_ArenaAlloc(arena, PORT_Strlen((char *)issuerCert->subjectKeyID.data)); + if (authKeyID->keyID.data == NULL) { + error_allocate(); + } + PORT_Memcpy(authKeyID->keyID.data, issuerCert->subjectKeyID.data, + authKeyID->keyID.len = + PORT_Strlen((char *)issuerCert->subjectKeyID.data)); + } else { + + PORT_Assert(arena); + genNames = (CERTGeneralName *)PORT_ArenaZAlloc(arena, (sizeof(CERTGeneralName))); + if (genNames == NULL) { + error_allocate(); + } + genNames->l.next = genNames->l.prev = &(genNames->l); + genNames->type = certDirectoryName; + + directoryName = CERT_AsciiToName(issuerCert->subjectName); + if (!directoryName) { + error_out("ERROR: Unable to create Directory Name"); + } + rv = CERT_CopyName(arena, &genNames->name.directoryName, + directoryName); + CERT_DestroyName(directoryName); + if (rv != SECSuccess) { + error_out("ERROR: Unable to copy Directory Name"); + } + authKeyID->authCertIssuer = genNames; + if (authKeyID->authCertIssuer == NULL && SECFailure == PORT_GetError()) { + error_out("ERROR: Unable to get Issuer General Name for Authority Key ID Extension"); + } + authKeyID->authCertSerialNumber = issuerCert->serialNumber; + } + rv = EncodeAndAddExtensionValue(arena, extHandle, authKeyID, PR_FALSE, + SEC_OID_X509_AUTH_KEY_ID, + (EXTEN_VALUE_ENCODER) + CERT_EncodeAuthKeyID); + if (arena) { + PORT_FreeArena(arena, PR_FALSE); + } + return (rv); +} + +static SECStatus +AddPrivKeyUsagePeriod(void *extHandle, + Pair *data, + CERTCertificate *cert) +{ + char *notBeforeStr; + char *notAfterStr; + PLArenaPool *arena = NULL; + SECStatus rv = SECSuccess; + CERTPrivKeyUsagePeriod *pkup; + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (!arena) { + error_allocate(); + } + pkup = PORT_ArenaZNew(arena, CERTPrivKeyUsagePeriod); + if (pkup == NULL) { + error_allocate(); + } + notBeforeStr = (char *)PORT_Alloc(16); + if (notBeforeStr == NULL) { + error_allocate(); + } + notAfterStr = (char *)PORT_Alloc(16); + if (notAfterStr == NULL) { + error_allocate(); + } + *notBeforeStr = '\0'; + *notAfterStr = '\0'; + pkup->arena = arena; + pkup->notBefore.len = 0; + pkup->notBefore.data = NULL; + pkup->notAfter.len = 0; + pkup->notAfter.data = NULL; + if (find_field_bool(data, "privKeyUsagePeriod-radio-notBefore", PR_TRUE) || + find_field_bool(data, "privKeyUsagePeriod-radio-both", PR_TRUE)) { + pkup->notBefore.len = 15; + pkup->notBefore.data = (unsigned char *)notBeforeStr; + if (find_field_bool(data, "privKeyUsagePeriod-notBefore-radio-manual", + PR_TRUE)) { + PORT_Strcat(notBeforeStr, find_field(data, + "privKeyUsagePeriod-notBefore-year", + PR_TRUE)); + PORT_Strcat(notBeforeStr, find_field(data, + "privKeyUsagePeriod-notBefore-month", + PR_TRUE)); + PORT_Strcat(notBeforeStr, find_field(data, + "privKeyUsagePeriod-notBefore-day", + PR_TRUE)); + PORT_Strcat(notBeforeStr, find_field(data, + "privKeyUsagePeriod-notBefore-hour", + PR_TRUE)); + PORT_Strcat(notBeforeStr, find_field(data, + "privKeyUsagePeriod-notBefore-minute", + PR_TRUE)); + PORT_Strcat(notBeforeStr, find_field(data, + "privKeyUsagePeriod-notBefore-second", + PR_TRUE)); + if ((*(notBeforeStr + 14) != '\0') || + (!isdigit(*(notBeforeStr + 13))) || + (*(notBeforeStr + 12) >= '5' && *(notBeforeStr + 12) <= '0') || + (!isdigit(*(notBeforeStr + 11))) || + (*(notBeforeStr + 10) >= '5' && *(notBeforeStr + 10) <= '0') || + (!isdigit(*(notBeforeStr + 9))) || + (*(notBeforeStr + 8) >= '2' && *(notBeforeStr + 8) <= '0') || + (!isdigit(*(notBeforeStr + 7))) || + (*(notBeforeStr + 6) >= '3' && *(notBeforeStr + 6) <= '0') || + (!isdigit(*(notBeforeStr + 5))) || + (*(notBeforeStr + 4) >= '1' && *(notBeforeStr + 4) <= '0') || + (!isdigit(*(notBeforeStr + 3))) || + (!isdigit(*(notBeforeStr + 2))) || + (!isdigit(*(notBeforeStr + 1))) || + (!isdigit(*(notBeforeStr + 0))) || + (*(notBeforeStr + 8) == '2' && *(notBeforeStr + 9) >= '4') || + (*(notBeforeStr + 6) == '3' && *(notBeforeStr + 7) >= '1') || + (*(notBeforeStr + 4) == '1' && *(notBeforeStr + 5) >= '2')) { + error_out("ERROR: Improperly formated private key usage period"); + } + *(notBeforeStr + 14) = 'Z'; + *(notBeforeStr + 15) = '\0'; + } else { + if ((*(cert->validity.notBefore.data) > '5') || + ((*(cert->validity.notBefore.data) == '5') && + (*(cert->validity.notBefore.data + 1) != '0'))) { + PORT_Strcat(notBeforeStr, "19"); + } else { + PORT_Strcat(notBeforeStr, "20"); + } + PORT_Strcat(notBeforeStr, (char *)cert->validity.notBefore.data); + } + } + if (find_field_bool(data, "privKeyUsagePeriod-radio-notAfter", PR_TRUE) || + find_field_bool(data, "privKeyUsagePeriod-radio-both", PR_TRUE)) { + pkup->notAfter.len = 15; + pkup->notAfter.data = (unsigned char *)notAfterStr; + PORT_Strcat(notAfterStr, find_field(data, "privKeyUsagePeriod-notAfter-year", + PR_TRUE)); + PORT_Strcat(notAfterStr, find_field(data, "privKeyUsagePeriod-notAfter-month", + PR_TRUE)); + PORT_Strcat(notAfterStr, find_field(data, "privKeyUsagePeriod-notAfter-day", + PR_TRUE)); + PORT_Strcat(notAfterStr, find_field(data, "privKeyUsagePeriod-notAfter-hour", + PR_TRUE)); + PORT_Strcat(notAfterStr, find_field(data, "privKeyUsagePeriod-notAfter-minute", + PR_TRUE)); + PORT_Strcat(notAfterStr, find_field(data, "privKeyUsagePeriod-notAfter-second", + PR_TRUE)); + if ((*(notAfterStr + 14) != '\0') || + (!isdigit(*(notAfterStr + 13))) || + (*(notAfterStr + 12) >= '5' && *(notAfterStr + 12) <= '0') || + (!isdigit(*(notAfterStr + 11))) || + (*(notAfterStr + 10) >= '5' && *(notAfterStr + 10) <= '0') || + (!isdigit(*(notAfterStr + 9))) || + (*(notAfterStr + 8) >= '2' && *(notAfterStr + 8) <= '0') || + (!isdigit(*(notAfterStr + 7))) || + (*(notAfterStr + 6) >= '3' && *(notAfterStr + 6) <= '0') || + (!isdigit(*(notAfterStr + 5))) || + (*(notAfterStr + 4) >= '1' && *(notAfterStr + 4) <= '0') || + (!isdigit(*(notAfterStr + 3))) || + (!isdigit(*(notAfterStr + 2))) || + (!isdigit(*(notAfterStr + 1))) || + (!isdigit(*(notAfterStr + 0))) || + (*(notAfterStr + 8) == '2' && *(notAfterStr + 9) >= '4') || + (*(notAfterStr + 6) == '3' && *(notAfterStr + 7) >= '1') || + (*(notAfterStr + 4) == '1' && *(notAfterStr + 5) >= '2')) { + error_out("ERROR: Improperly formated private key usage period"); + } + *(notAfterStr + 14) = 'Z'; + *(notAfterStr + 15) = '\0'; + } + + PORT_Assert(arena); + + rv = EncodeAndAddExtensionValue(arena, extHandle, pkup, + find_field_bool(data, + "privKeyUsagePeriod-crit", + PR_TRUE), + SEC_OID_X509_PRIVATE_KEY_USAGE_PERIOD, + (EXTEN_VALUE_ENCODER) + CERT_EncodePrivateKeyUsagePeriod); + PORT_FreeArena(arena, PR_FALSE); + PORT_Free(notBeforeStr); + PORT_Free(notAfterStr); + return (rv); +} + +static SECStatus +AddBasicConstraint(void *extHandle, + Pair *data) +{ + CERTBasicConstraints basicConstraint; + SECItem encodedValue; + SECStatus rv; + + encodedValue.data = NULL; + encodedValue.len = 0; + basicConstraint.pathLenConstraint = CERT_UNLIMITED_PATH_CONSTRAINT; + basicConstraint.isCA = (find_field_bool(data, "basicConstraints-cA-radio-CA", + PR_TRUE)); + if (find_field_bool(data, "basicConstraints-pathLengthConstraint", PR_TRUE)) { + basicConstraint.pathLenConstraint = atoi(find_field(data, "basicConstraints-pathLengthConstraint-text", + PR_TRUE)); + } + + rv = CERT_EncodeBasicConstraintValue(NULL, &basicConstraint, + &encodedValue); + if (rv) + return (rv); + rv = CERT_AddExtension(extHandle, SEC_OID_X509_BASIC_CONSTRAINTS, + &encodedValue, + (find_field_bool(data, "basicConstraints-crit", + PR_TRUE)), + PR_TRUE); + + PORT_Free(encodedValue.data); + return (rv); +} + +static SECStatus +AddNscpCertType(void *extHandle, + Pair *data) +{ + SECItem bitStringValue; + unsigned char CertType = 0x0; + + if (find_field_bool(data, "netscape-cert-type-ssl-client", PR_TRUE)) { + CertType |= (0x80 >> 0); + } + if (find_field_bool(data, "netscape-cert-type-ssl-server", PR_TRUE)) { + CertType |= (0x80 >> 1); + } + if (find_field_bool(data, "netscape-cert-type-smime", PR_TRUE)) { + CertType |= (0x80 >> 2); + } + if (find_field_bool(data, "netscape-cert-type-object-signing", PR_TRUE)) { + CertType |= (0x80 >> 3); + } + if (find_field_bool(data, "netscape-cert-type-reserved", PR_TRUE)) { + CertType |= (0x80 >> 4); + } + if (find_field_bool(data, "netscape-cert-type-ssl-ca", PR_TRUE)) { + CertType |= (0x80 >> 5); + } + if (find_field_bool(data, "netscape-cert-type-smime-ca", PR_TRUE)) { + CertType |= (0x80 >> 6); + } + if (find_field_bool(data, "netscape-cert-type-object-signing-ca", PR_TRUE)) { + CertType |= (0x80 >> 7); + } + + bitStringValue.data = &CertType; + bitStringValue.len = 1; + + return (CERT_EncodeAndAddBitStrExtension(extHandle, SEC_OID_NS_CERT_EXT_CERT_TYPE, &bitStringValue, + (find_field_bool(data, "netscape-cert-type-crit", PR_TRUE)))); +} + +static SECStatus +add_IA5StringExtension(void *extHandle, + char *string, + PRBool crit, + int idtag) +{ + SECItem encodedValue; + SECStatus rv; + + encodedValue.data = NULL; + encodedValue.len = 0; + + rv = CERT_EncodeIA5TypeExtension(NULL, string, &encodedValue); + if (rv) { + return (rv); + } + return (CERT_AddExtension(extHandle, idtag, &encodedValue, crit, PR_TRUE)); +} + +static SECItem * +string_to_oid(char *string) +{ + int i; + int length = 20; + int remaining; + int first_value; + int second_value; + int value; + int oidLength; + unsigned char *oidString; + unsigned char *write; + unsigned char *read; + unsigned char *temp; + SECItem *oid; + + remaining = length; + i = 0; + while (*string == ' ') { + string++; + } + while (isdigit(*(string + i))) { + i++; + } + if (*(string + i) == '.') { + *(string + i) = '\0'; + } else { + error_out("ERROR: Improperly formated OID"); + } + first_value = atoi(string); + if (first_value < 0 || first_value > 2) { + error_out("ERROR: Improperly formated OID"); + } + string += i + 1; + i = 0; + while (isdigit(*(string + i))) { + i++; + } + if (*(string + i) == '.') { + *(string + i) = '\0'; + } else { + error_out("ERROR: Improperly formated OID"); + } + second_value = atoi(string); + if (second_value < 0 || second_value > 39) { + error_out("ERROR: Improperly formated OID"); + } + oidString = PORT_ZAlloc(2); + *oidString = (first_value * 40) + second_value; + *(oidString + 1) = '\0'; + oidLength = 1; + string += i + 1; + i = 0; + temp = write = PORT_ZAlloc(length); + while (*string != '\0') { + value = 0; + while (isdigit(*(string + i))) { + i++; + } + if (*(string + i) == '\0') { + value = atoi(string); + string += i; + } else { + if (*(string + i) == '.') { + *(string + i) = '\0'; + value = atoi(string); + string += i + 1; + } else { + *(string + i) = '\0'; + i++; + value = atoi(string); + while (*(string + i) == ' ') + i++; + if (*(string + i) != '\0') { + error_out("ERROR: Improperly formated OID"); + } + } + } + i = 0; + while (value != 0) { + if (remaining < 1) { + remaining += length; + length = length * 2; + temp = PORT_Realloc(temp, length); + write = temp + length - remaining; + } + *write = (value & 0x7f) | (0x80); + write++; + remaining--; + value = value >> 7; + } + *temp = *temp & (0x7f); + oidLength += write - temp; + oidString = PORT_Realloc(oidString, (oidLength + 1)); + read = write - 1; + write = oidLength + oidString - 1; + for (i = 0; i < (length - remaining); i++) { + *write = *read; + write--; + read++; + } + write = temp; + remaining = length; + } + *(oidString + oidLength) = '\0'; + oid = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); + oid->data = oidString; + oid->len = oidLength; + PORT_Free(temp); + return oid; +} + +static SECItem * +string_to_ipaddress(char *string) +{ + int i = 0; + int value; + int j = 0; + SECItem *ipaddress; + + while (*string == ' ') { + string++; + } + ipaddress = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); + ipaddress->data = PORT_ZAlloc(9); + while (*string != '\0' && j < 8) { + while (isdigit(*(string + i))) { + i++; + } + if (*(string + i) == '.') { + *(string + i) = '\0'; + value = atoi(string); + string = string + i + 1; + i = 0; + } else { + if (*(string + i) == '\0') { + value = atoi(string); + string = string + i; + i = 0; + } else { + *(string + i) = '\0'; + while (*(string + i) == ' ') { + i++; + } + if (*(string + i) == '\0') { + value = atoi(string); + string = string + i; + i = 0; + } else { + error_out("ERROR: Improperly formated IP Address"); + } + } + } + if (value >= 0 && value < 256) { + *(ipaddress->data + j) = value; + } else { + error_out("ERROR: Improperly formated IP Address"); + } + j++; + } + *(ipaddress->data + j) = '\0'; + if (j != 4 && j != 8) { + error_out("ERROR: Improperly formated IP Address"); + } + ipaddress->len = j; + return ipaddress; +} + +static int +chr_to_hex(char c) +{ + if (isdigit(c)) { + return c - '0'; + } + if (isxdigit(c)) { + return toupper(c) - 'A' + 10; + } + return -1; +} + +static SECItem * +string_to_binary(char *string) +{ + SECItem *rv; + + rv = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); + if (rv == NULL) { + error_allocate(); + } + rv->data = (unsigned char *)PORT_ZAlloc((PORT_Strlen(string)) / 3 + 2); + rv->len = 0; + while (*string && !isxdigit(*string)) { + string++; + } + while (*string) { + int high, low; + high = chr_to_hex(*string++); + low = chr_to_hex(*string++); + if (high < 0 || low < 0) { + error_out("ERROR: Improperly formated binary encoding"); + } + rv->data[(rv->len)++] = high << 4 | low; + if (*string != ':') { + break; + } + ++string; + } + while (*string == ' ') { + ++string; + } + if (*string) { + error_out("ERROR: Junk after binary encoding"); + } + + return rv; +} + +static SECStatus +MakeGeneralName(char *name, + CERTGeneralName *genName, + PLArenaPool *arena) +{ + SECItem *oid; + SECOidData *oidData; + SECItem *ipaddress; + SECItem *temp = NULL; + int i; + int nameType; + PRBool binary = PR_FALSE; + SECStatus rv = SECSuccess; + PRBool nickname = PR_FALSE; + + PORT_Assert(genName); + PORT_Assert(arena); + nameType = *(name + PORT_Strlen(name) - 1) - '0'; + if (nameType == 0 && *(name + PORT_Strlen(name) - 2) == '1') { + nickname = PR_TRUE; + nameType = certOtherName; + } + if (nameType < 1 || nameType > 9) { + error_out("ERROR: Unknown General Name Type"); + } + *(name + PORT_Strlen(name) - 4) = '\0'; + genName->type = nameType; + + switch (genName->type) { + case certURI: + case certRFC822Name: + case certDNSName: { + genName->name.other.data = (unsigned char *)name; + genName->name.other.len = PORT_Strlen(name); + break; + } + + case certIPAddress: { + ipaddress = string_to_ipaddress(name); + genName->name.other.data = ipaddress->data; + genName->name.other.len = ipaddress->len; + break; + } + + case certRegisterID: { + oid = string_to_oid(name); + genName->name.other.data = oid->data; + genName->name.other.len = oid->len; + break; + } + + case certEDIPartyName: + case certX400Address: { + + genName->name.other.data = PORT_ArenaAlloc(arena, + PORT_Strlen(name) + 2); + if (genName->name.other.data == NULL) { + error_allocate(); + } + + PORT_Memcpy(genName->name.other.data + 2, name, PORT_Strlen(name)); + /* This may not be accurate for all cases. + For now, use this tag type */ + genName->name.other.data[0] = (char)(((genName->type - 1) & + 0x1f) | + 0x80); + genName->name.other.data[1] = (char)PORT_Strlen(name); + genName->name.other.len = PORT_Strlen(name) + 2; + break; + } + + case certOtherName: { + i = 0; + if (!nickname) { + while (!isdigit(*(name + PORT_Strlen(name) - i))) { + i++; + } + if (*(name + PORT_Strlen(name) - i) == '1') { + binary = PR_TRUE; + } else { + binary = PR_FALSE; + } + while (*(name + PORT_Strlen(name) - i) != '-') { + i++; + } + *(name + PORT_Strlen(name) - i - 1) = '\0'; + i = 0; + while (*(name + i) != '-') { + i++; + } + *(name + i - 1) = '\0'; + oid = string_to_oid(name + i + 2); + } else { + oidData = SECOID_FindOIDByTag(SEC_OID_NETSCAPE_NICKNAME); + oid = &oidData->oid; + while (*(name + PORT_Strlen(name) - i) != '-') { + i++; + } + *(name + PORT_Strlen(name) - i) = '\0'; + } + genName->name.OthName.oid.data = oid->data; + genName->name.OthName.oid.len = oid->len; + if (binary) { + temp = string_to_binary(name); + genName->name.OthName.name.data = temp->data; + genName->name.OthName.name.len = temp->len; + } else { + temp = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); + if (temp == NULL) { + error_allocate(); + } + temp->data = (unsigned char *)name; + temp->len = PORT_Strlen(name); + SEC_ASN1EncodeItem(arena, &(genName->name.OthName.name), temp, + CERTIA5TypeTemplate); + } + PORT_Free(temp); + break; + } + + case certDirectoryName: { + CERTName *directoryName = NULL; + + directoryName = CERT_AsciiToName(name); + if (!directoryName) { + error_out("ERROR: Improperly formated alternative name"); + break; + } + rv = CERT_CopyName(arena, &genName->name.directoryName, + directoryName); + CERT_DestroyName(directoryName); + + break; + } + } + genName->l.next = &(genName->l); + genName->l.prev = &(genName->l); + return rv; +} + +static CERTGeneralName * +MakeAltName(Pair *data, + char *which, + PLArenaPool *arena) +{ + CERTGeneralName *SubAltName; + CERTGeneralName *current; + CERTGeneralName *newname; + char *name = NULL; + SECStatus rv = SECSuccess; + int len; + + len = PORT_Strlen(which); + name = find_field(data, which, PR_TRUE); + SubAltName = current = (CERTGeneralName *)PORT_ZAlloc(sizeof(CERTGeneralName)); + if (current == NULL) { + error_allocate(); + } + while (name != NULL) { + + rv = MakeGeneralName(name, current, arena); + + if (rv != SECSuccess) { + break; + } + if (*(which + len - 1) < '9') { + *(which + len - 1) = *(which + len - 1) + 1; + } else { + if (isdigit(*(which + len - 2))) { + *(which + len - 2) = *(which + len - 2) + 1; + *(which + len - 1) = '0'; + } else { + *(which + len - 1) = '1'; + *(which + len) = '0'; + *(which + len + 1) = '\0'; + len++; + } + } + len = PORT_Strlen(which); + name = find_field(data, which, PR_TRUE); + if (name != NULL) { + newname = (CERTGeneralName *)PORT_ZAlloc(sizeof(CERTGeneralName)); + if (newname == NULL) { + error_allocate(); + } + current->l.next = &(newname->l); + newname->l.prev = &(current->l); + current = newname; + newname = NULL; + } else { + current->l.next = &(SubAltName->l); + SubAltName->l.prev = &(current->l); + } + } + if (rv == SECFailure) { + return NULL; + } + return SubAltName; +} + +static CERTNameConstraints * +MakeNameConstraints(Pair *data, + PLArenaPool *arena) +{ + CERTNameConstraints *NameConstraints; + CERTNameConstraint *current = NULL; + CERTNameConstraint *last_permited = NULL; + CERTNameConstraint *last_excluded = NULL; + char *constraint = NULL; + char *which; + SECStatus rv = SECSuccess; + int len; + int i; + long max; + long min; + PRBool permited; + + NameConstraints = (CERTNameConstraints *)PORT_ZAlloc(sizeof(CERTNameConstraints)); + which = make_copy_string("NameConstraintSelect0", 25, '\0'); + len = PORT_Strlen(which); + constraint = find_field(data, which, PR_TRUE); + NameConstraints->permited = NameConstraints->excluded = NULL; + while (constraint != NULL) { + current = (CERTNameConstraint *)PORT_ZAlloc(sizeof(CERTNameConstraint)); + if (current == NULL) { + error_allocate(); + } + i = 0; + while (*(constraint + PORT_Strlen(constraint) - i) != '-') { + i++; + } + *(constraint + PORT_Strlen(constraint) - i - 1) = '\0'; + max = (long)atoi(constraint + PORT_Strlen(constraint) + 3); + if (max > 0) { + (void)SEC_ASN1EncodeInteger(arena, ¤t->max, max); + } + i = 0; + while (*(constraint + PORT_Strlen(constraint) - i) != '-') { + i++; + } + *(constraint + PORT_Strlen(constraint) - i - 1) = '\0'; + min = (long)atoi(constraint + PORT_Strlen(constraint) + 3); + (void)SEC_ASN1EncodeInteger(arena, ¤t->min, min); + while (*(constraint + PORT_Strlen(constraint) - i) != '-') { + i++; + } + *(constraint + PORT_Strlen(constraint) - i - 1) = '\0'; + if (*(constraint + PORT_Strlen(constraint) + 3) == 'p') { + permited = PR_TRUE; + } else { + permited = PR_FALSE; + } + rv = MakeGeneralName(constraint, &(current->name), arena); + + if (rv != SECSuccess) { + break; + } + if (*(which + len - 1) < '9') { + *(which + len - 1) = *(which + len - 1) + 1; + } else { + if (isdigit(*(which + len - 2))) { + *(which + len - 2) = *(which + len - 2) + 1; + *(which + len - 1) = '0'; + } else { + *(which + len - 1) = '1'; + *(which + len) = '0'; + *(which + len + 1) = '\0'; + len++; + } + } + len = PORT_Strlen(which); + if (permited) { + if (NameConstraints->permited == NULL) { + NameConstraints->permited = last_permited = current; + } + last_permited->l.next = &(current->l); + current->l.prev = &(last_permited->l); + last_permited = current; + } else { + if (NameConstraints->excluded == NULL) { + NameConstraints->excluded = last_excluded = current; + } + last_excluded->l.next = &(current->l); + current->l.prev = &(last_excluded->l); + last_excluded = current; + } + constraint = find_field(data, which, PR_TRUE); + if (constraint != NULL) { + current = (CERTNameConstraint *)PORT_ZAlloc(sizeof(CERTNameConstraint)); + if (current == NULL) { + error_allocate(); + } + } + } + if (NameConstraints->permited != NULL) { + last_permited->l.next = &(NameConstraints->permited->l); + NameConstraints->permited->l.prev = &(last_permited->l); + } + if (NameConstraints->excluded != NULL) { + last_excluded->l.next = &(NameConstraints->excluded->l); + NameConstraints->excluded->l.prev = &(last_excluded->l); + } + if (which != NULL) { + PORT_Free(which); + } + if (rv == SECFailure) { + return NULL; + } + return NameConstraints; +} + +static SECStatus +AddAltName(void *extHandle, + Pair *data, + char *issuerNameStr, + CERTCertDBHandle *handle, + int type) +{ + PRBool autoIssuer = PR_FALSE; + PLArenaPool *arena = NULL; + CERTGeneralName *genName = NULL; + char *which = NULL; + char *name = NULL; + SECStatus rv = SECSuccess; + SECItem *issuersAltName = NULL; + CERTCertificate *issuerCert = NULL; + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (arena == NULL) { + error_allocate(); + } + if (type == 0) { + which = make_copy_string("SubAltNameSelect0", 20, '\0'); + genName = MakeAltName(data, which, arena); + } else { + if (autoIssuer) { + autoIssuer = find_field_bool(data, "IssuerAltNameSourceRadio-auto", + PR_TRUE); + issuerCert = CERT_FindCertByNameString(handle, issuerNameStr); + rv = cert_FindExtension((*issuerCert).extensions, + SEC_OID_X509_SUBJECT_ALT_NAME, + issuersAltName); + if (issuersAltName == NULL) { + name = PORT_Alloc(PORT_Strlen((*issuerCert).subjectName) + 4); + PORT_Strcpy(name, (*issuerCert).subjectName); + PORT_Strcat(name, " - 5"); + } + } else { + which = make_copy_string("IssuerAltNameSelect0", 20, '\0'); + genName = MakeAltName(data, which, arena); + } + } + if (type == 0) { + EncodeAndAddExtensionValue(arena, extHandle, genName, + find_field_bool(data, "SubAltName-crit", + PR_TRUE), + SEC_OID_X509_SUBJECT_ALT_NAME, + (EXTEN_VALUE_ENCODER) + CERT_EncodeAltNameExtension); + + } else { + if (autoIssuer && (name == NULL)) { + rv = CERT_AddExtension(extHandle, SEC_OID_X509_ISSUER_ALT_NAME, issuersAltName, + find_field_bool(data, "IssuerAltName-crit", PR_TRUE), PR_TRUE); + } else { + EncodeAndAddExtensionValue(arena, extHandle, genName, + find_field_bool(data, + "IssuerAltName-crit", + PR_TRUE), + SEC_OID_X509_ISSUER_ALT_NAME, + (EXTEN_VALUE_ENCODER) + CERT_EncodeAltNameExtension); + } + } + if (which != NULL) { + PORT_Free(which); + } + if (issuerCert != NULL) { + CERT_DestroyCertificate(issuerCert); + } + return rv; +} + +static SECStatus +AddNameConstraints(void *extHandle, + Pair *data) +{ + PLArenaPool *arena = NULL; + CERTNameConstraints *constraints = NULL; + SECStatus rv = SECSuccess; + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (arena == NULL) { + error_allocate(); + } + constraints = MakeNameConstraints(data, arena); + if (constraints != NULL) { + EncodeAndAddExtensionValue(arena, extHandle, constraints, PR_TRUE, + SEC_OID_X509_NAME_CONSTRAINTS, + (EXTEN_VALUE_ENCODER) + CERT_EncodeNameConstraintsExtension); + } + if (arena != NULL) { + PORT_ArenaRelease(arena, NULL); + } + return rv; +} + +static SECStatus +add_extensions(CERTCertificate *subjectCert, + Pair *data, + char *issuerNameStr, + CERTCertDBHandle *handle) +{ + void *extHandle; + SECStatus rv = SECSuccess; + + extHandle = CERT_StartCertExtensions(subjectCert); + if (extHandle == NULL) { + error_out("ERROR: Unable to get certificates extension handle"); + } + if (find_field_bool(data, "keyUsage", PR_TRUE)) { + rv = AddKeyUsage(extHandle, data); + if (rv != SECSuccess) { + error_out("ERROR: Unable to add Key Usage extension"); + } + } + + if (find_field_bool(data, "extKeyUsage", PR_TRUE)) { + rv = AddExtKeyUsage(extHandle, data); + if (SECSuccess != rv) { + error_out("ERROR: Unable to add Extended Key Usage extension"); + } + } + + if (find_field_bool(data, "basicConstraints", PR_TRUE)) { + rv = AddBasicConstraint(extHandle, data); + if (rv != SECSuccess) { + error_out("ERROR: Unable to add Basic Constraint extension"); + } + } + if (find_field_bool(data, "subjectKeyIdentifier", PR_TRUE)) { + rv = AddSubKeyID(extHandle, data, subjectCert); + if (rv != SECSuccess) { + error_out("ERROR: Unable to add Subject Key Identifier Extension"); + } + } + if (find_field_bool(data, "authorityKeyIdentifier", PR_TRUE)) { + rv = AddAuthKeyID(extHandle, data, issuerNameStr, handle); + if (rv != SECSuccess) { + error_out("ERROR: Unable to add Authority Key Identifier extension"); + } + } + if (find_field_bool(data, "privKeyUsagePeriod", PR_TRUE)) { + rv = AddPrivKeyUsagePeriod(extHandle, data, subjectCert); + if (rv != SECSuccess) { + error_out("ERROR: Unable to add Private Key Usage Period extension"); + } + } + if (find_field_bool(data, "SubAltName", PR_TRUE)) { + rv = AddAltName(extHandle, data, NULL, NULL, 0); + if (rv != SECSuccess) { + error_out("ERROR: Unable to add Subject Alternative Name extension"); + } + } + if (find_field_bool(data, "IssuerAltName", PR_TRUE)) { + rv = AddAltName(extHandle, data, issuerNameStr, handle, 1); + if (rv != SECSuccess) { + error_out("ERROR: Unable to add Issuer Alternative Name Extension"); + } + } + if (find_field_bool(data, "NameConstraints", PR_TRUE)) { + rv = AddNameConstraints(extHandle, data); + if (rv != SECSuccess) { + error_out("ERROR: Unable to add Name Constraints Extension"); + } + } + if (find_field_bool(data, "netscape-cert-type", PR_TRUE)) { + rv = AddNscpCertType(extHandle, data); + if (rv != SECSuccess) { + error_out("ERROR: Unable to add Netscape Certificate Type Extension"); + } + } + if (find_field_bool(data, "netscape-base-url", PR_TRUE)) { + rv = add_IA5StringExtension(extHandle, + find_field(data, "netscape-base-url-text", + PR_TRUE), + find_field_bool(data, + "netscape-base-url-crit", + PR_TRUE), + SEC_OID_NS_CERT_EXT_BASE_URL); + if (rv != SECSuccess) { + error_out("ERROR: Unable to add Netscape Base URL Extension"); + } + } + if (find_field_bool(data, "netscape-revocation-url", PR_TRUE)) { + rv = add_IA5StringExtension(extHandle, + find_field(data, + "netscape-revocation-url-text", + PR_TRUE), + find_field_bool(data, "netscape-revocation-url-crit", + PR_TRUE), + SEC_OID_NS_CERT_EXT_REVOCATION_URL); + if (rv != SECSuccess) { + error_out("ERROR: Unable to add Netscape Revocation URL Extension"); + } + } + if (find_field_bool(data, "netscape-ca-revocation-url", PR_TRUE)) { + rv = add_IA5StringExtension(extHandle, + find_field(data, + "netscape-ca-revocation-url-text", + PR_TRUE), + find_field_bool(data, "netscape-ca-revocation-url-crit", PR_TRUE), + SEC_OID_NS_CERT_EXT_CA_REVOCATION_URL); + if (rv != SECSuccess) { + error_out("ERROR: Unable to add Netscape CA Revocation URL Extension"); + } + } + if (find_field_bool(data, "netscape-cert-renewal-url", PR_TRUE)) { + rv = add_IA5StringExtension(extHandle, + find_field(data, + "netscape-cert-renewal-url-text", + PR_TRUE), + find_field_bool(data, "netscape-cert-renewal-url-crit", + PR_TRUE), + SEC_OID_NS_CERT_EXT_CERT_RENEWAL_URL); + if (rv != SECSuccess) { + error_out("ERROR: Unable to add Netscape Certificate Renewal URL Extension"); + } + } + if (find_field_bool(data, "netscape-ca-policy-url", PR_TRUE)) { + rv = add_IA5StringExtension(extHandle, + find_field(data, + "netscape-ca-policy-url-text", + PR_TRUE), + find_field_bool(data, "netscape-ca-policy-url-crit", + PR_TRUE), + SEC_OID_NS_CERT_EXT_CA_POLICY_URL); + if (rv != SECSuccess) { + error_out("ERROR: Unable to add Netscape CA Policy URL Extension"); + } + } + if (find_field_bool(data, "netscape-ssl-server-name", PR_TRUE)) { + rv = add_IA5StringExtension(extHandle, + find_field(data, + "netscape-ssl-server-name-text", + PR_TRUE), + find_field_bool(data, "netscape-ssl-server-name-crit", + PR_TRUE), + SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME); + if (rv != SECSuccess) { + error_out("ERROR: Unable to add Netscape SSL Server Name Extension"); + } + } + if (find_field_bool(data, "netscape-comment", PR_TRUE)) { + rv = add_IA5StringExtension(extHandle, + find_field(data, "netscape-comment-text", + PR_TRUE), + find_field_bool(data, + "netscape-comment-crit", + PR_TRUE), + SEC_OID_NS_CERT_EXT_COMMENT); + if (rv != SECSuccess) { + error_out("ERROR: Unable to add Netscape Comment Extension"); + } + } + CERT_FinishExtensions(extHandle); + return (rv); +} + +char * +return_dbpasswd(PK11SlotInfo *slot, PRBool retry, void *data) +{ + char *rv; + + /* don't clobber our poor smart card */ + if (retry == PR_TRUE) { + return NULL; + } + rv = PORT_Alloc(4); + PORT_Strcpy(rv, "foo"); + return rv; +} + +SECKEYPrivateKey * +FindPrivateKeyFromNameStr(char *name, + CERTCertDBHandle *certHandle) +{ + SECKEYPrivateKey *key; + CERTCertificate *cert; + CERTCertificate *p11Cert; + + /* We don't presently have a PK11 function to find a cert by + ** subject name. + ** We do have a function to find a cert in the internal slot's + ** cert db by subject name, but it doesn't setup the slot info. + ** So, this HACK works, but should be replaced as soon as we + ** have a function to search for certs accross slots by subject name. + */ + cert = CERT_FindCertByNameString(certHandle, name); + if (cert == NULL || cert->nickname == NULL) { + error_out("ERROR: Unable to retrieve issuers certificate"); + } + p11Cert = PK11_FindCertFromNickname(cert->nickname, NULL); + if (p11Cert == NULL) { + error_out("ERROR: Unable to retrieve issuers certificate"); + } + key = PK11_FindKeyByAnyCert(p11Cert, NULL); + return key; +} + +static SECItem * +SignCert(CERTCertificate *cert, + char *issuerNameStr, + Pair *data, + CERTCertDBHandle *handle, + int which_key) +{ + SECItem der; + SECKEYPrivateKey *caPrivateKey = NULL; + SECStatus rv; + PLArenaPool *arena; + SECOidTag algID; + + if (which_key == 0) { + caPrivateKey = FindPrivateKeyFromNameStr(issuerNameStr, handle); + } else { + caPrivateKey = privkeys[which_key - 1]; + } + if (caPrivateKey == NULL) { + error_out("ERROR: unable to retrieve issuers key"); + } + + arena = cert->arena; + + algID = SEC_GetSignatureAlgorithmOidTag(caPrivateKey->keyType, + SEC_OID_UNKNOWN); + if (algID == SEC_OID_UNKNOWN) { + error_out("ERROR: Unknown key type for issuer."); + goto done; + } + + rv = SECOID_SetAlgorithmID(arena, &cert->signature, algID, 0); + if (rv != SECSuccess) { + error_out("ERROR: Could not set signature algorithm id."); + } + + if (find_field_bool(data, "ver-1", PR_TRUE)) { + *(cert->version.data) = 0; + cert->version.len = 1; + } else { + *(cert->version.data) = 2; + cert->version.len = 1; + } + der.data = NULL; + der.len = 0; + (void)SEC_ASN1EncodeItem(arena, &der, cert, CERT_CertificateTemplate); + if (der.data == NULL) { + error_out("ERROR: Could not encode certificate.\n"); + } + rv = SEC_DerSignData(arena, &(cert->derCert), der.data, der.len, caPrivateKey, + algID); + if (rv != SECSuccess) { + error_out("ERROR: Could not sign encoded certificate data.\n"); + } +done: + SECKEY_DestroyPrivateKey(caPrivateKey); + return &(cert->derCert); +} + +int +main(int argc, char **argv) +{ + int length = 500; + int remaining = 500; + int n; + int i; + int serial; + int chainLen; + int which_key; + char *pos; +#ifdef OFFLINE + char *form_output = "key=MIIBPTCBpzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA7" + "SLqjWBL9Wl11Vlg%0AaMqZCvcQOL%2FnvSqYPPRP0XZy9SoAeyWzQnBOiCm2t8H5mK7r2" + "jnKdAQOmfhjaJil%0A3hNVu3SekHOXF6Ze7bkWa6%2FSGVcY%2FojkydxFSgY43nd1iyd" + "zPQDp8WWLL%2BpVpt%2B%2B%0ATRhFtVXbF0fQI03j9h3BoTgP2lkCAwEAARYDZm9vMA0" + "GCSqGSIb3DQEBBAUAA4GB%0AAJ8UfRKJ0GtG%2B%2BufCC6tAfTzKrq3CTBHnom55EyXc" + "sAsv6WbDqI%2F0rLAPkn2Xo1r%0AnNhtMxIuj441blMt%2Fa3AGLOy5zmC7Qawt8IytvQ" + "ikQ1XTpTBCXevytrmLjCmlURr%0ANJryTM48WaMQHiMiJpbXCqVJC1d%2FpEWBtqvALzZ" + "aOOIy&subject=CN%3D%22test%22%26serial-auto%3Dtrue%26serial_value%3D%" + "26ver-1%3Dtrue%26ver-3%3Dfalse%26caChoiceradio-SignWithDefaultkey%3Dt" + "rue%26caChoiceradio-SignWithRandomChain%3Dfalse%26autoCAs%3D%26caChoi" + "ceradio-SignWithSpecifiedChain%3Dfalse%26manCAs%3D%26%24"; +#else + char *form_output; +#endif + char *issuerNameStr; + char *certName; + char *DBdir = DB_DIRECTORY; + char *prefixs[10] = { "CA#1-", "CA#2-", "CA#3-", + "CA#4-", "CA#5-", "CA#6-", + "CA#7-", "CA#8-", "CA#9-", "" }; + Pair *form_data; + CERTCertificate *cert; + CERTCertDBHandle *handle; + CERTCertificateRequest *certReq = NULL; + int warpmonths = 0; + SECItem *certDER; +#ifdef FILEOUT + FILE *outfile; +#endif + SECStatus status = SECSuccess; + extern char prefix[PREFIX_LEN]; + SEC_PKCS7ContentInfo *certChain; + SECItem *encodedCertChain; + PRBool UChain = PR_FALSE; + + progName = strrchr(argv[0], '/'); + progName = progName ? progName + 1 : argv[0]; + +#ifdef TEST + sleep(20); +#endif + SECU_ConfigDirectory(DBdir); + + PK11_SetPasswordFunc(return_dbpasswd); + status = NSS_InitReadWrite(DBdir); + if (status != SECSuccess) { + SECU_PrintPRandOSError(progName); + return -1; + } + handle = CERT_GetDefaultCertDB(); + + prefix[0] = '\0'; +#if !defined(OFFLINE) + form_output = (char *)PORT_Alloc(length); + if (form_output == NULL) { + error_allocate(); + } + pos = form_output; + while (feof(stdin) == 0) { + if (remaining <= 1) { + remaining += length; + length = length * 2; + form_output = PORT_Realloc(form_output, (length)); + if (form_output == NULL) { + error_allocate(); + } + pos = form_output + length - remaining; + } + n = fread(pos, 1, (size_t)(remaining - 1), stdin); + pos += n; + remaining -= n; + } + *pos = '&'; + pos++; + length = pos - form_output; +#else + length = PORT_Strlen(form_output); +#endif +#ifdef FILEOUT + printf("Content-type: text/plain\n\n"); + fwrite(form_output, 1, (size_t)length, stdout); + printf("\n"); +#endif +#ifdef FILEOUT + fwrite(form_output, 1, (size_t)length, stdout); + printf("\n"); + fflush(stdout); +#endif + form_data = make_datastruct(form_output, length); + status = clean_input(form_data); +#if !defined(OFFLINE) + PORT_Free(form_output); +#endif +#ifdef FILEOUT + i = 0; + while (return_name(form_data, i) != NULL) { + printf("%s", return_name(form_data, i)); + printf("=\n"); + printf("%s", return_data(form_data, i)); + printf("\n"); + i++; + } + printf("I got that done, woo hoo\n"); + fflush(stdout); +#endif + issuerNameStr = PORT_Alloc(200); + if (find_field_bool(form_data, "caChoiceradio-SignWithSpecifiedChain", + PR_FALSE)) { + UChain = PR_TRUE; + chainLen = atoi(find_field(form_data, "manCAs", PR_FALSE)); + PORT_Strcpy(prefix, prefixs[0]); + issuerNameStr = PORT_Strcpy(issuerNameStr, + "CN=Cert-O-Matic II, O=Cert-O-Matic II"); + if (chainLen == 0) { + UChain = PR_FALSE; + } + } else { + if (find_field_bool(form_data, "caChoiceradio-SignWithRandomChain", + PR_FALSE)) { + PORT_Strcpy(prefix, prefixs[9]); + chainLen = atoi(find_field(form_data, "autoCAs", PR_FALSE)); + if (chainLen < 1 || chainLen > 18) { + issuerNameStr = PORT_Strcpy(issuerNameStr, + "CN=CA18, O=Cert-O-Matic II"); + } + issuerNameStr = PORT_Strcpy(issuerNameStr, "CN=CA"); + issuerNameStr = PORT_Strcat(issuerNameStr, + find_field(form_data, "autoCAs", PR_FALSE)); + issuerNameStr = PORT_Strcat(issuerNameStr, ", O=Cert-O-Matic II"); + } else { + issuerNameStr = PORT_Strcpy(issuerNameStr, + "CN=Cert-O-Matic II, O=Cert-O-Matic II"); + } + chainLen = 0; + } + + i = -1; + which_key = 0; + do { + extern SECStatus cert_GetKeyID(CERTCertificate * cert); + i++; + if (i != 0 && UChain) { + PORT_Strcpy(prefix, prefixs[i]); + } + /* find_field(form_data,"subject", PR_TRUE); */ + certReq = makeCertReq(form_data, which_key); +#ifdef OFFLINE + serial = 900; +#else + serial = get_serial_number(form_data); +#endif + cert = MakeV1Cert(handle, certReq, issuerNameStr, PR_FALSE, + serial, warpmonths, form_data); + if (certReq != NULL) { + CERT_DestroyCertificateRequest(certReq); + } + if (find_field_bool(form_data, "ver-3", PR_TRUE)) { + status = add_extensions(cert, form_data, issuerNameStr, handle); + if (status != SECSuccess) { + error_out("ERROR: Unable to add extensions"); + } + } + status = cert_GetKeyID(cert); + if (status == SECFailure) { + error_out("ERROR: Unable to get Key ID."); + } + certDER = SignCert(cert, issuerNameStr, form_data, handle, which_key); + CERT_NewTempCertificate(handle, certDER, NULL, PR_FALSE, PR_TRUE); + issuerNameStr = find_field(form_data, "subject", PR_TRUE); + /* SECITEM_FreeItem(certDER, PR_TRUE); */ + CERT_DestroyCertificate(cert); + if (i == (chainLen - 1)) { + i = 8; + } + ++which_key; + } while (i < 9 && UChain); + +#ifdef FILEOUT + outfile = fopen("../certout", "wb"); +#endif + certName = find_field(form_data, "subject", PR_FALSE); + cert = CERT_FindCertByNameString(handle, certName); + certChain = SEC_PKCS7CreateCertsOnly(cert, PR_TRUE, handle); + if (certChain == NULL) { + error_out("ERROR: No certificates in cert chain"); + } + encodedCertChain = SEC_PKCS7EncodeItem(NULL, NULL, certChain, NULL, NULL, + NULL); + if (encodedCertChain) { +#if !defined(FILEOUT) + printf("Content-type: application/x-x509-user-cert\r\n"); + printf("Content-length: %d\r\n\r\n", encodedCertChain->len); + fwrite(encodedCertChain->data, 1, encodedCertChain->len, stdout); +#else + fwrite(encodedCertChain->data, 1, encodedCertChain->len, outfile); +#endif + + } else { + error_out("Error: Unable to DER encode certificate"); + } +#ifdef FILEOUT + printf("\nI got here!\n"); + fflush(outfile); + fclose(outfile); +#endif + fflush(stdout); + if (NSS_Shutdown() != SECSuccess) { + exit(1); + } + return 0; +} diff --git a/security/nss/cmd/certcgi/certcgi.gyp b/security/nss/cmd/certcgi/certcgi.gyp new file mode 100644 index 000000000..5ad2893e0 --- /dev/null +++ b/security/nss/cmd/certcgi/certcgi.gyp @@ -0,0 +1,33 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +{ + 'includes': [ + '../../coreconf/config.gypi', + '../../cmd/platlibs.gypi' + ], + 'targets': [ + { + 'target_name': 'certcgi', + 'type': 'executable', + 'sources': [ + 'certcgi.c' + ], + 'dependencies': [ + '<(DEPTH)/exports.gyp:dbm_exports', + '<(DEPTH)/exports.gyp:nss_exports', + '<(DEPTH)/lib/sqlite/sqlite.gyp:sqlite3' + ] + } + ], + 'target_defaults': { + 'defines': [ + 'NSPR20', + 'NSS_USE_STATIC_LIBS' + ] + }, + 'variables': { + 'module': 'nss', + 'use_static_libs': 1 + } +}
\ No newline at end of file diff --git a/security/nss/cmd/certcgi/index.html b/security/nss/cmd/certcgi/index.html new file mode 100644 index 000000000..3ae6a10d4 --- /dev/null +++ b/security/nss/cmd/certcgi/index.html @@ -0,0 +1,789 @@ +<HTML> <!-- -*- Mode: Java; tab-width: 8 -*- --> +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<HEAD> +<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> +<SCRIPT LANGUAGE="JavaScript1.2"> + +script_url = 'http://interzone.mcom.com/cgi-bin/certomatic/bin/certcgi.cgi' + +ext_page_ver1 = + make_page_intro('Version 1 extensions', "#FFFFFF") + + '<IFRAME WIDTH="100%" HEIGHT="100%" FRAMEBORDER=0 ID="ext1">' + + 'Version 1 X.509 certs do not support extensions' + + '</IFRAME>' + + '</body></html>'; + +num_ca = 0; + +your_certificate_index_label = 'Your Certificate'; +netscape_extensions_index_label = 'Netscape X.509 Extensions'; +standard_extensions_index_label = 'Standard X.509 Extensions'; +certifying_authorities_index_label = 'Certifying Authorities'; +add_sub_alt_name_index_label = 'Add Subject Alternative Name'; + +index_list = + '0, your_certificate_index_label,' + + '0, netscape_extensions_index_label,' + + '0, standard_extensions_index_label,' + + '0, certifying_authorities_index_label'; + +add_index_list = ''; + +ver = 3 + +max_pages = 13; +cur_page = 1; + +ext_page_array = new Array(max_pages); + +index_label = 'Options'; + +var main_page = + make_page_intro('Your Key', "#FFFFFF") + + '<IFRAME WIDTH="100%" HEIGHT="100%" FRAMEBORDER=0 ID="main" SRC="main.html">' + + '</IFRAME>' + + '</body></html>' ; + +function setSubAltNameType(form) +{ + with(form) { + if (SubAltNameRadio[0].checked) { + return true; + } + if (SubAltNameRadio[3].checked || SubAltNameRadio[5].checked) { + SubAltNameDataType.checked = true; + return true; + } + if (SubAltNameRadio[1].checked || SubAltNameRadio[2].checked || + SubAltNameRadio[4].checked || SubAltNameRadio[6].checked || + SubAltNameRadio[7].checked || SubAltNameRadio[8].checked) { + SubAltNameDataType.checked = false; + return true; + } + } + return true; +} + +function setIssuerAltNameType(form) +{ + with(form) { + if (IssuerAltNameRadio[0].checked) { + return true; + } + if (IssuerAltNameRadio[3].checked || IssuerAltNameRadio[5].checked) { + IssuerAltNameDataType.checked = true; + return true; + } + if (IssuerAltNameRadio[1].checked || IssuerAltNameRadio[2].checked || + IssuerAltNameRadio[4].checked || IssuerAltNameRadio[6].checked || + IssuerAltNameRadio[7].checked || IssuerAltNameRadio[8].checked) { + IssuerAltNameDataType.checked = false; + return true; + } + } + return true; +} + + +function setNameConstraintNameType(form) +{ + with(form) { + if (NameConstraintRadio[0].checked) { + return true; + } + if (NameConstraintRadio[3].checked || NameConstraintRadio[5].checked) { + NameConstraintNameDataType.checked = true; + return true; + } + if (NameConstraintRadio[1].checked || NameConstraintRadio[2].checked || + NameConstraintRadio[4].checked || NameConstraintRadio[6].checked || + NameConstraintRadio[7].checked || NameConstraintRadio[8].checked) { + NameConstraintNameDataType.checked = false; + return true; + } + } + return true; +} + + +function addSubAltName(form) +{ + with(form) { + var len = SubAltNameSelect.length; + var value; + var i = 0; + while(!(i == (SubAltNameRadio.length - 1)) & + !(SubAltNameRadio[i].checked == true)) { + i++; + } + if (i != 0) { + value = SubAltNameText.value + " - " + (i + 1); + } else { + value = SubAltNameText.value + " - " + + SubAltNameOtherNameOID.value + " - "; + if (SubAltNameDataType.checked) { + value += "1 - "; + } else { + value += "0 - "; + } + value += (i + 1); + if (SubAltNameOtherNameOID.value == "") { + alert("Other names must include an OID"); + return false; + } + } + + if ((SubAltNameText.value == "") | (SubAltNameRadio[i].checked != true)) { + alert("Alternative Names must include values for name and name type."); + } else { + SubAltNameSelect.options[len] = new Option(value, value); + } + } + return true; +} + +function deleteSubAltName(form) +{ + with(form) { + while (SubAltNameSelect.selectedIndex >= 0) { + SubAltNameSelect[SubAltNameSelect.selectedIndex] = null; + } + } +} + +function addIssuerAltName(form) +{ + with(form) + { + var len = IssuerAltNameSelect.length; + var value; + var i = 0; + + while(!(i == (IssuerAltNameRadio.length -1)) & + !(IssuerAltNameRadio[i].checked == true)) { + i++; + } + if (i != 0) { + value = IssuerAltNameText.value + " - " + (i + 1); + } else { + value = IssuerAltNameText.value + " - " + + IssuerAltNameOtherNameOID.value + " - "; + if (IssuerAltNameDataType.checked) { + value += "1 - "; + } else { + value += "0 - "; + } + value += (i + 1); + if (IssuerAltNameOtherNameOID.value == "") { + alert("Other names must include an OID"); + return false; + } + } + if ((IssuerAltNameText.value == "") | + (IssuerAltNameRadio[i].checked != true)) { + alert("Alternative Names must include values for name and name type.") + } else { + IssuerAltNameSelect.options[len] = new Option(value, value); + } + } + return true; +} + +function deleteIssuerAltName(form) +{ + with(form) { + while (IssuerAltNameSelect.selectedIndex >= 0) { + IssuerAltNameSelect[IssuerAltNameSelect.selectedIndex] = null; + } + } +} + + + +function addNameConstraint(form) +{ + with(form) { + var len = NameConstraintSelect.length; + var value; + var i = 0; + var min = NameConstraintMin.value; + var max = NameConstraintMax.value; + + while(!(i == (NameConstraintRadio.length - 1) ) & + !(NameConstraintRadio[i].checked == true)) { + i++; + } + value = NameConstraintText.value + " - "; + if (i == 0) { + value += NameConstraintOtherNameOID.value + " - "; + if (NameConstraintNameDataType.checked) { + value += "1 - "; + } else { + value += "0 - "; + } + if (NameConstraintOtherNameOID.value == "") { + alert("Other names must include an OID"); + return false; + } + } + value += (i + 1) + " - "; + if (NameConstraintTypeRadio[0].checked == true) { + value += "p - "; + } else { + value += "e - "; + } + value += min + " - " + max; + if ((min == "") | (NameConstraintText.value == "") | + (NameConstraintRadio[i].checked != true)) { + alert("Name Constraints must include values for minimum, name, and name type.") + } else { + NameConstraintSelect.options[len] = new Option(value, value); + } + } + return true; +} + +function deleteNameConstraint(form) +{ + with(form) { + while (NameConstraintSelect.selectedIndex >= 0) { + NameConstraintSelect[NameConstraintSelect.selectedIndex] = null; + } + } +} + + +function submit_it() +{ + save_cur_page(cur_page); + + var ver1 = (ver == 1); + var ver3 = (ver == 3); + var array_string; + var serial = ext_page_array[0][10][0]; + var serial_number = ext_page_array[0][12][0]; + var manValidity = ext_page_array[0][19][0]; + var notBefore = ext_page_array[0][20][0]; + var notAfter = ext_page_array[0][21][0]; + var subject = ext_page_array[0][22][0]; + + if (subject == "") { + alert("The DN field must contain some data"); + return false; + } + if (!serial & serial_number == "") { + alert("No serial number specified"); + return false; + } + if (ext_page_array[0][15][0]) { + var keygen = "<keygen name=\"key\" challenge=\"foo\">"; + } else { + switch (ext_page_array[0][17][0]) { + case 2: + var keygen = "<keygen keytype=\"dsa\" pqg=\"MIGdAkEAjfKklEkidqo9JXWbsGhpy+rA2Dr7jQz3y7gyTw14guXQdi/FtyEOr8Lprawyq3qsSWk9+/g3JMLsBzbuMcgCkQIVAMdzIYxzfsjumTtPLe0w9I7azpFfAkEAYm0CeDnqChNBMWOlW0y1ACmdVSKVbO/LO/8Q85nOLC5xy53l+iS6v1jlt5UhklycxC6fb0ZLCIzFcq9T5teIAg==\" name=\"key\" challenge=\"foo\">"; + break; + case 1: + var keygen = "<keygen keytype=\"dsa\" pqg=\"MIHaAmDCboVgX0+6pEeMlbwsasWDVBcJNHPKMzkq9kbCRK2U3k+tE15n+Dc2g3ZjDYr1um51e2iLC34/BwAAAAAAAAAAAAAAAAAAAAAAAAABbBhnlFN5Djmt0Mk8cdEBY5H8iPMCFMhUnFtbpjn3EyfH2DjVg3ALh7FtAmA2zWzhpeCwvOTjYnQorlXiv0WcnSiWmaC79CRYkFt5i+UEfRxwP1eNGJBVB1T+CPW6JGd4WhgsqtSf53pn5DEtv++O7lNfXyOhWhb3KaWHYIx8fuAXtioIWkWmpfEIVZA=\" name=\"key\" challenge=\"foo\">"; + break; + case 0: + var keygen = "<keygen keytype=\"dsa\" pqg=\"MIIBHAKBgId8SiiWrcdua5zbsBhPkKfFcnHBG7T/bQla7c6OixGjjmSSuq2fJLvMKa579CaxHxLZzZZXIHmAk9poRgWl2GUUkCJ68XSum8OQzDPXPsofcEdeANjw3mIAAAAAAAAAAAAAAAAAAAAAAAAIE+MkW5hguLIQqWvEVi9dMpbNu6OZAhTIA+y3TgyiwA0D8pt686ofaL1IOQKBgAiZQC6UCXztr2iXxJrAC+51gN5oX/R9Thilln9RGegsWnHrdxUOpcm5vAWp1LU8TOXtujE8kqkm3UxIRhUWQORe9IxLANAXmZJqkw9FEVHkxj6Cy9detwT2MyBzSwS6avsf7aLisgHmI/IHSeapJsQ3NQa3rikb6zRiqIV+TVa6\" name=\"key\" challenge=\"foo\">"; + break; + } + } + array_string = build_array_string(); + hiddens = "<input type=\"hidden\" name=\"subject\" value=\'" + subject + "\'> \n" + + "<input type=\"hidden\" name=\"serial-auto\" value=\"" + serial + "\"> \n" + + "<input type=\"hidden\" name=\"serial_value\" value=\"" + serial_number + "\"> \n" + + "<input type=\"hidden\" name=\"ver-1\" value=\"" + ver1 + "\"> \n" + + "<input type=\"hidden\" name=\"ver-3\" value=\"" + ver3 + "\"> \n" + + "<input type=\"hidden\" name=\"notBefore\" value=\"" + notBefore + "\"> \n" + + "<input type=\"hidden\" name=\"notAfter\" value=\"" + notAfter + "\"> \n" + + "<input type=\"hidden\" name=\"manValidity\" value=\"" + manValidity + "\"> \n" + + array_string; + + var good_submit_page = + '<html>' + + '<BODY TEXT="#000000" LINK="#000000" VLINK="#000000" ALINK="#FF0000" BGCOLOR="#FFFFFF">' + + '<form method="post" action="' + script_url + '">' + + 'Select size for your key:' + keygen + '</p>' + + '<input type="submit"></p>' + + hiddens + + '</form>\n' + + '</body>\n' + + '</html>\n'; + + window.frames['right'].document.write(good_submit_page); + window.frames['right'].document.close(); + cur_page = max_pages + 1; + make_left_frame(window); + return false; +} + + + +function build_array_string() +{ + var pg; + var array_string = ''; + var pages; + + if ((ext_page_array[3][4][0] > 0) && ext_page_array[3][3][0]) { + pages = 4 + parseInt(ext_page_array[3][4][0]); + } else { + pages = 4; + } + for (pg = 1; pg < pages; pg++) { + if ((pg > 1 || (ver == 3)) && (ext_page_array[pg].length > 1)) { + if (pg < 4) { + for (i = 0; i < ext_page_array[pg].length; i++) { + if (ext_page_array[pg][i][3].indexOf("radio") == -1) { + if (ext_page_array[pg][i][3].indexOf("multiple") == -1) { + array_string += '<input type=\"hidden\" name=\"' + + ext_page_array[pg][i][1] + '\" value=\'' + + ext_page_array[pg][i][0] + '\'> \n'; + } else { + for (k = 0; k < ext_page_array[pg][i][0].length; k++) { + array_string += '<input type=\"hidden\" name=\"' + + ext_page_array[pg][i][1] + k + '\" value=\'' + + ext_page_array[pg][i][0][k] + '\'> \n'; + } + } + } else { + array_string += '<input type=\"hidden\" name=\"' + + ext_page_array[pg][i][1] + '-' + + ext_page_array[pg][i][2] + '\" value=\'' + + ext_page_array[pg][i][0] + '\'> \n'; + } + } + } else { + for (i = 0; i < ext_page_array[pg].length; i++) { + if (ext_page_array[pg][i][3].indexOf("radio") == -1) { + if (ext_page_array[pg][i][3].indexOf("multiple") == -1) { + array_string += '<input type=\"hidden\" name=\"' + + 'CA#' + (pg - 3) + '-' + + ext_page_array[pg][i][1] + '\" value=\'' + + ext_page_array[pg][i][0] +'\'> \n'; + } else { + for (k = 0; k < ext_page_array[pg][i][0].length; k++) { + array_string += '<input type=\"hidden\" name=\"' + + 'CA#' + (pg - 3) + '-' + + ext_page_array[pg][i][1] + k + '\" value=\'' + + ext_page_array[pg][i][0][k] + '\'> \n'; + } + } + } else { + array_string += '<input type=\"hidden\" name=\"' + + 'CA#' + (pg - 3) + '-' + + ext_page_array[pg][i][1] + '-' + + ext_page_array[pg][i][2] + '\" value=\'' + + ext_page_array[pg][i][0] + '\'> \n'; + } + } + } + } + } + return array_string; +} + + + +function init_ext_page_array() +{ + for (i = 0; i < max_pages; i++) { + ext_page_array[i] = ''; + } +} + +function ca_num_change(n,ca_form) +{ + with(ca_form) { + n = parseInt(n,10); + if (caChoiceradio[2].checked) { + if (n) { + update_left_frame(n); + } else { + update_left_frame(0); + } + } + } +} + +function choice_change(ca_form) +{ + with(ca_form) { + if (caChoiceradio[2].checked) { + ca_num_change(manCAs.value,ca_form); + } else { + update_left_frame(0); + } + } +} + +function update_left_frame(n) +{ + var add_string = ''; + for (var i = 0; i < n; i++) { + var j = i + 1; + add_string = add_string + ',1, \'CA #' + j + '\''; + } + top.add_index_list = add_string; + num_ca = n; + make_left_frame(window); +} + +function set_ver1() +// redraws the extensions page for version 1 certificates +{ + ver = 1 + if (cur_page == 2 || cur_page == 3) { + switch_right_frame(window, cur_page, cur_page); + } +} + + +function set_ver3() +// redraws the extensions page for version 3 certificates +{ + ver = 3 + if (cur_page == 2) { + switch_right_frame(window, 0, 2); + } else if (cur_page == 3) { + switch_right_frame(window, 0, 3); + } +} + +function reset_subject(marker, value, form) +// Updates the subject field from a subordinate field +{ + with(form) { + var field_sep = '", '; + var begin_index = subject.value.indexOf(marker); + if (begin_index != 0 && subject.value[begin_index - 1] != ' ') { + begin_index = subject.value.indexOf(marker, begin_index +1); + } + var end_index = subject.value.indexOf(field_sep, begin_index); + if (begin_index > -1) { // is it a delete/change? + if (end_index == -1) { // is it the last one (includes only one)? + if (value.length > 0) { // do I have to change it? + if (begin_index == 0) { // is is the only one? + subject.value = marker + '"' + value + '"'; + } else { // it is the last of many + subject.value = subject.value.substring(0,begin_index) + + marker + '"' + value + '"'; + } + } else { // must be a delete + if (begin_index == 0) { // is it the only one? + begin_index += 2; + } + subject.value = subject.value.substring(0,(begin_index - 2)); + } + } else { // it is the first of many or a middle one + if (value.length >0) { // do I have to change it? + subject.value = + subject.value.substring(0,(begin_index + marker.length + 1)) + + value + subject.value.substring(end_index,subject.length); + } else { // it is a delete + subject.value = subject.value.substring(0,begin_index) + + subject.value.substring((end_index + 3),subject.length); + } + } + } else { // It is either an insert or a do nothing + if (value.length > 0) { // is it an insert? + if (subject.value.length == 0) { // is subject currently empty? + subject.value = marker + '"' + value + '"'; + } else { + subject.value = subject.value + ', ' + marker + '"' + value + '"'; + } + } + } + } +} + + + +function reset_subjectFields(form) +// updates all the subordinate fields from the subject field of a form +// **** move the strings to global variables, to make maintentance easier **** +{ + + update_subject_Field(form, 'CN=\"', form.name); + update_subject_Field(form, 'MAIL=\"', form.email); + update_subject_Field(form, 'O=\"', form.org); + update_subject_Field(form, 'C=\"', form.country); + update_subject_Field(form, ' L=\"', form.loc); + update_subject_Field(form, 'ST=\"', form.state); + update_subject_Field(form, 'E=\"', form.email); + update_subject_Field(form, 'OU=\"', form.org_unit); + update_subject_Field(form, 'UID=\"', form.uid); +} + +function update_subject_Field(form, marker, update_field) +//updates a single subordinate field from the subject field of a form +// *** need to deal with the two types of e-mail addresses ************** +{ + with(form) { + var field_sep = '", '; + var begin_index = subject.value.indexOf(marker) + marker.length; + var end_index = subject.value.indexOf(field_sep, begin_index); + if (end_index == -1) { + end_index = subject.value.indexOf('"',begin_index); + } + if (begin_index != (-1 + marker.length) ) { + update_field.value = subject.value.substring(begin_index, end_index); + } else { + update_field.value = ''; + } + } +} + + +function switch_mail(form) +// **** Do I want to delete the other type of e-mail address ? ************ +{ + if (form.email_type[0].checked) { + var del = 'E='; + var ins = 'MAIL='; + } else { + var del = 'MAIL='; + var ins = 'E='; + } + reset_subject(del, '', form); + reset_subject(ins, form.email.value, form); +} + +function make_page_intro(title, bgcolor) +{ + var style = '<STYLE TYPE="text/css">BODY{' + + 'font-family: Geneva,MS Sans Serif,Arial,Lucida,Helvetica,sans-serif;' + + 'font-size: 10pt;' + + '}' + + 'TD{' + + 'font-family: Geneva,MS Sans Serif,Arial,Lucida,Helvetica,sans-serif;' + + 'font-size: 10pt;}' + + '</STYLE>'; + + if (bgcolor == null) { bgcolor = "#C0C0C0"; } + return '<HTML><HEAD>' + + '<TITLE>' + title + '</TITLE>' + + '</HEAD>' + + '<BODY TEXT="#000000" LINK="#000000" VLINK="#000000" ALINK="#FF0000" ' + + 'BGCOLOR="' + bgcolor + '">'; +} + + +function make_left_frame(window) +{ + with (window.frames['index']) { + eval ('index_string = make_left_frame_page(cur_page, ' + + index_list + add_index_list + ' )'); + fool1 = make_page_intro(index_label, "#FFFFFF") + + index_string + '</BODY></HTML>'; + document.write(fool1); + document.close(); + } +} + + +function save_cur_page(page_number) +{ + var len; + var pg = page_number - 1; + if (window.frames['right'].document.forms.length != 0) { + with (window.frames['right'].document) { + if ((page_number != 2 && page_number != 3 && page_number <= max_pages) || + ver == 3) { + ext_page_array[pg] = new Array(forms[0].elements.length); + for (i = 0; i < forms[0].elements.length; i++) { + ext_page_array[pg][i] = new Array(4); + switch (forms[0].elements[i].type) { + case 'radio': + case 'checkbox': + ext_page_array[pg][i][0] = forms[0].elements[i].checked; + break; + case 'select-one': + ext_page_array[pg][i][0] = forms[0].elements[i].selectedIndex; + break; + case 'select-multiple': + len = forms[0].elements[i].options.length; + ext_page_array[pg][i][0] = new Array(len); + for(k = 0; k < len; k++) { + ext_page_array[pg][i][0][k] = forms[0].elements[i].options[k].value; + } + break; + default: + ext_page_array[pg][i][0] = forms[0].elements[i].value; + } + ext_page_array[pg][i][1] = forms[0].elements[i].name; + ext_page_array[pg][i][2] = forms[0].elements[i].value; + ext_page_array[pg][i][3] = forms[0].elements[i].type; + } + } + } + } +} + +function reload_form(page_number) +{ + var j = page_number - 1; + with (window.frames['right'].document) { + if (((page_number < 2 || page_number > 3) || ver == 3) + && page_number != 0 && (ext_page_array[j].length > 1)) { + for (i = 0; i < ext_page_array[j].length; i++) { + switch (forms[0].elements[i].type) { + case 'radio': case 'checkbox': + forms[0].elements[i].checked = ext_page_array[j][i][0]; + break; + case 'select-one': + forms[0].elements[i].selectedIndex = ext_page_array[j][i][0]; + break; + case 'select-multiple': + for (k = 0; k < ext_page_array[j][i][0].length; k++) { + forms[0].elements[i].options[k] = + new Option(ext_page_array[j][i][0][k], + ext_page_array[j][i][0][k]); + } + break; + default: + forms[0].elements[i].value = ext_page_array[j][i][0]; + } + } + } + } +} + +function switch_right_frame(top_window, old_pane, new_pane) +{ + var ext_page_stnd = + make_page_intro(standard_extensions_index_label, "#FFFFFF") + + '<IFRAME WIDTH="100%" HEIGHT="100%" FRAMEBORDER=0 ID="ext" ' + + 'SRC="stnd_ext_form.html">' + + '</IFRAME></body></html>'; + + var ext_page_nscp = + make_page_intro(netscape_extensions_index_label, "#FFFFFF") + + '<IFRAME WIDTH="100%" HEIGHT="100%" FRAMEBORDER=0 ID="ext" ' + + 'SRC="nscp_ext_form.html">' + + '</IFRAME></body></html>'; + + var ext_page_ca = + make_page_intro(certifying_authorities_index_label, "#FFFFFF") + + '<IFRAME WIDTH="100%" HEIGHT="100%" FRAMEBORDER=0 ID="ext" ' + + 'SRC="ca.html">' + + '</IFRAME></body</html>'; + + var ext_page_ca_exp = + make_page_intro('Certifying Authority Details', "#FFFFFF") + + '<IFRAME WIDTH="100%" HEIGHT="100%" FRAMEBORDER=0 ID="ext" ' + + 'SRC="ca_form.html">' + + '</IFRAME></body></html>'; + + + if (old_pane > 0 && cur_page <= max_pages) { + save_cur_page(old_pane); + } + cur_page = new_pane; + make_left_frame(top_window); + if (new_pane == 2 || new_pane == 3) { + if (ver == 1) { + frames['right'].document.write(ext_page_ver1); + frames['right'].document.close(); + } else if (new_pane == 2) { + frames['right'].document.write(ext_page_nscp); + frames['right'].document.close(); + reload_form(new_pane); + } else { + frames['right'].document.write(ext_page_stnd); + frames['right'].document.close(); + reload_form(new_pane); + } + } else if (new_pane == 4) { + frames['right'].document.write(ext_page_ca); + frames['right'].document.close(); + reload_form(new_pane); + } else if (new_pane == 1) { + frames['right'].document.write(main_page); + frames['right'].document.close(); + reload_form(new_pane); + } else { + frames['right'].document.write(ext_page_ca_exp); + frames['right'].document.close(); + reload_form(new_pane); + } +} + +function make_left_frame_page(selected) +{ + var n_strings = ( make_left_frame_page.arguments.length - 1 ) / 2; + var table_background; + var command; + var indent; + var label; + var ret_string = ""; + + ret_string += '<TABLE CELLSPACING=4>'; + for ( var i = 1; i <= n_strings; i++ ) { + if ( i == selected ) { + table_background = 'BGCOLOR=#BBCCBB'; + } else { + table_background = ''; + } + + indent = make_left_frame_page.arguments[(i*2) - 1]; + label = make_left_frame_page.arguments[(i*2)]; + + if ( indent == 0 ) { + ret_string += ('<TR><TD COLSPAN=2 ' + table_background + '>'); + } else { + ret_string += ('<TR><TD> </TD><TD ' + table_background + '>'); + } + + command = "'parent.switch_right_frame(parent," + selected + "," + i + ")'"; + ret_string += ('<A HREF="javascript:void setTimeout(' + command + ',0)">'); + if ( indent == 0 ) { ret_string += "<B>"; } + ret_string += label; + if ( indent == 0 ) { ret_string += "</B>"; } + ret_string += '</A></TD></TR>'; + } + if (selected == (max_pages + 1)) { + table_background = 'BGCOLOR=#BBCCBB'; + } else { + table_background = ''; + } + ret_string += + '<TR><TD COLSPAN=2 ' + table_background + + '><b><A HREF="javascript:void setTimeout(\'top.submit_it()\', 0)">Finish</A></b>' + + '</TD></TR>' + + '<input type="submit"></form>' + + '</TABLE>'; + return(ret_string); +} + + +function make_page(window) +// Draws the initial page setup +{ + selected = cur_page + init_ext_page_array() + + with (window.frames['right']) { + location="main.html"; +// document.write(main_page); +// document.close(); + } + + make_left_frame(window); + +} +</script> + +</HEAD> +<title>Cert-O-Matic</title> + <FRAMESET cols="150,*" BORDER=3 ONLOAD="make_page(window)"> + <FRAME SRC="about:blank" ID="index" NAME="index" + MARGINWIDTH=15 MARGINHEIGHT=10 BORDER=3> + <FRAME SRC="about:blank" ID="right" NAME="right" + MARGINWIDTH=15 MARGINHEIGHT=10 BORDER=3> + </FRAMESET> +</HTML> diff --git a/security/nss/cmd/certcgi/main.html b/security/nss/cmd/certcgi/main.html new file mode 100644 index 000000000..05dd9daad --- /dev/null +++ b/security/nss/cmd/certcgi/main.html @@ -0,0 +1,76 @@ +<HTML> +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<HEAD> + <TITLE>Main Layer for CertOMatic</TITLE> +</HEAD> + + <form method="post" name="primary_form" action="http://interzone.mcom.com/burp.cgi"> + <table border=0 cellspacing=10 cellpadding=0> + <tr> + <td> + Common Name:</td><td> <input type="text" name="name" onChange="{window.top.reset_subject('CN=', value, form)}"></p> + </td> + <td></td><td></td> + <td> + Organization: </td><td> <input type="text" name="org" onChange="{window.top.reset_subject('O=', value, form)}"></p></td> + <tr> + <td> + <input type="radio" name="email_type" value="1" onClick="window.top.switch_mail(form)">MAIL= + + <input type="radio" name="email_type" value="2" checked onClick="window.top.switch_mail(form)">E= + </td> + <td> + <input type="text" name="email" onChange="var temp;{if (email_type[0].checked) {temp = 'MAIL='} else {temp = 'E='}} ;{window.top.reset_subject(temp, value, form)}"> + </td> + <td></td><td></td><td> + Organizational Unit: </td><td><input type="text" name="org_unit" onChange="{window.top.reset_subject('OU=', value, form)}"></p></td> + <tr> + <td> + UID= </td><td><input type="text" name="uid" onChange="{window.top.reset_subject('UID=', value, form)}"></p></td> + <td></td><td></td><td> + Locality: </td><td><input type="text" name="loc" onChange="{window.top.reset_subject('L=', value, form)}"></p></td> + <tr> + <td> + State or Province: </td><td><input type="text" name="state" onChange="{window.top.reset_subject('ST=', value, form)}"></p></td> + <td></td><td></td><td> + Country: </td><td><input type="text" size="2" name="country" onChange="{window.top.reset_subject('C=', value, form)}" maxlength="2"></p></td> + <tr> + <td COLSPAN=2> + Serial Number: + <DD><input type="radio" name="serial" value="auto" checked> Auto Generate + <DD><input type="radio" name="serial" value="input"> + Use this hex value: <input type="text" name="serial_value" size="8" maxlength="8"></p> + </td> + <td></td> <td></td> + <td COLSPAN=2> + X.509 version: + <DD><input type="radio" name="ver" value="1" onClick="if (this.checked) {window.top.set_ver1();}"> Version 1 + <DD><input type="radio" name="ver" value="3" checked onClick="if (this.checked) {window.top.set_ver3();}"> Version 3</P></td> + <tr> + <td COLSPAN=2> + Key Type: + <DD><input type="radio" name="keyType" value="rsa" checked> RSA + <DD><input type="radio" name="keyType" value="dsa"> DSA</p> + Intermediate CA Key Sizes: + <DD><select name="keysize"> + <option>2048 (Very High Grade) + <option>1024 (High Grade) + <option>512 (Low Grade) + </select> + </td> + <td></td> <td></td> + <td COLSPAN=2> + Validity: + <DD><input type="radio" name="validity" value="auto" checked> + Generate Automatically + <DD><input type="radio" name="validity" value="man"> Use these values: + <DD>Not Before: <input type="text" size="15" maxlength="17" name="notBefore"> + <DD>Not After: <input type="text" size="15" maxlength="17" name="notAfter"> + <DD> + <FONT SIZE=-1><TT>YYMMDDhhmm[ss]{Z|+hhmm|-hhmm} </TT></FONT> + </table> + DN: <input type="text" name="subject" size="70" onChange="{window.top.reset_subjectFields(form)}"></P> + </form> +</HTML> diff --git a/security/nss/cmd/certcgi/manifest.mn b/security/nss/cmd/certcgi/manifest.mn new file mode 100644 index 000000000..9e17cef9d --- /dev/null +++ b/security/nss/cmd/certcgi/manifest.mn @@ -0,0 +1,22 @@ +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +CORE_DEPTH = ../.. + +# MODULE public and private header directories are implicitly REQUIREd. +MODULE = nss + +# This next line is used by .mk files +# and gets translated into $LINCS in manifest.mnw +REQUIRES = seccmd dbm + +DEFINES = -DNSPR20 + +CSRCS = certcgi.c + +PROGRAM = certcgi + +USE_STATIC_LIBS = 1 + diff --git a/security/nss/cmd/certcgi/nscp_ext_form.html b/security/nss/cmd/certcgi/nscp_ext_form.html new file mode 100644 index 000000000..f2a4a20c3 --- /dev/null +++ b/security/nss/cmd/certcgi/nscp_ext_form.html @@ -0,0 +1,84 @@ +<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +<html> +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + + <body> + <table border=1 cellspacing=5 cellpadding=5> + <form method="post" name="primary_form" action="http://interzone.mcom.com/burp.cgi"> + <tr> + <td> + <b>Netscape Certificate Type: </b></p> + Activate extension: <input type="checkbox" name="netscape-cert-type"></P> + Critical: <input type="checkbox" name="netscape-cert-type-crit"> + <td> + <input type="checkbox" name="netscape-cert-type-ssl-client"> SSL Client</P> + <input type="checkbox" name="netscape-cert-type-ssl-server"> SSL Server</P> + <input type="checkbox" name="netscape-cert-type-smime"> S/MIME</P> + <input type="checkbox" name="netscape-cert-type-object-signing"> Object Signing</P> + <input type="checkbox" name="netscape-cert-type-reserved"> Reserved for future use (bit 4)</P> + <input type="checkbox" name="netscape-cert-type-ssl-ca"> SSL CA</P> + <input type="checkbox" name="netscape-cert-type-smime-ca"> S/MIME CA</P> + <input type="checkbox" name="netscape-cert-type-object-signing-ca"> Object Signing CA</P> + </tr> + <tr> + <td> + <b>Netscape Base URL:</b></p> + Activate extension: <input type="checkbox" name="netscape-base-url"></P> + Critical: <input type="checkbox" name="netscape-base-url-crit"> + <td> + <input type="text" name="netscape-base-url-text" size="50"> + </tr> + <tr> + <td> + <b>Netscape Revocation URL:</b></p> + Activate extension: <input type="checkbox" name="netscape-revocation-url"></P> + Critical: <input type="checkbox" name="netscape-revocation-url-crit"> + <td> + <input type="text" name="netscape-revocation-url-text" size="50"> + </tr> + <tr> + <td> + <b>Netscape CA Revocation URL:</b></p> + Activate extension: <input type="checkbox" name="netscape-ca-revocation-url"></P> + Critical: <input type="checkbox" name="netscape-ca-revocation-url-crit"> + <td> + <input type="text" name="netscape-ca-revocation-url-text" size="50"> + </tr> + <tr> + <td> + <b>Netscape Certificate Renewal URL:</b></p> + Activate extension: <input type="checkbox" name="netscape-cert-renewal-url"></P> + Critical: <input type="checkbox" name="netscape-cert-renewal-url-crit"> + <td> + <input type="text" name="netscape-cert-renewal-url-text" size="50"> + </tr> + <tr> + <td> + <b>Netscape CA Policy URL:</b></p> + Activate extension: <input type="checkbox" name="netscape-ca-policy-url"></P> + Critical: <input type="checkbox" name="netscape-ca-policy-url-crit"> + <td> + <input type="text" name="netscape-ca-policy-url-text" size="50"> + </tr> + <tr> + <td> + <b>Netscape SSL Server Name:</b></p> + Activate extension: <input type="checkbox" name="netscape-ssl-server-name"></P> + Critical: <input type="checkbox" name="netscape-ssl-server-name-crit"> + <td> + <input type="text" name="netscape-ssl-server-name-text" size="50"> + </tr> + <tr> + <td> + <b>Netscape Comment:</b></p> + Activate extension: <input type="checkbox" name="netscape-comment"></P> + Critical: <input type="checkbox" name="netscape-comment-crit"> + <td> + <textarea name="netscape-comment-text" rows="5" cols="50"></textarea> + </tr> + + </table> + </body> +</html> diff --git a/security/nss/cmd/certcgi/stnd_ext_form.html b/security/nss/cmd/certcgi/stnd_ext_form.html new file mode 100644 index 000000000..60d4d86a0 --- /dev/null +++ b/security/nss/cmd/certcgi/stnd_ext_form.html @@ -0,0 +1,219 @@ +<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +<html> +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + + <body> + <table border=1 cellspacing=5 cellpadding=5> + <form method="post" name="primary_form" action="http://interzone.mcom.com/burp.cgi"> + <tr> + <td> + <b>Key Usage: </b></p> + Activate extension: <input type="checkbox" name="keyUsage"></P> + Critical: <input type="checkbox" name="keyUsage-crit"> + <td> + <input type="checkbox" name="keyUsage-digitalSignature"> Digital Signature</P> + <input type="checkbox" name="keyUsage-nonRepudiation"> Non Repudiation</P> + <input type="checkbox" name="keyUsage-keyEncipherment"> Key Encipherment</P> + <input type="checkbox" name="keyUsage-dataEncipherment"> Data Encipherment</P> + <input type="checkbox" name="keyUsage-keyAgreement"> Key Agreement</P> + <input type="checkbox" name="keyUsage-keyCertSign"> Key Certificate Signing</P> + <input type="checkbox" name="keyUsage-cRLSign"> CRL Signing</P> + </tr> + <tr> + <td> + <b>Extended Key Usage: </b></p> + Activate extension: <input type="checkbox" name="extKeyUsage"></P> + Critical: <input type="checkbox" name="extKeyUsage-crit"> + <td> + <input type="checkbox" name="extKeyUsage-serverAuth"> Server Auth</P> + <input type="checkbox" name="extKeyUsage-clientAuth"> Client Auth</P> + <input type="checkbox" name="extKeyUsage-codeSign"> Code Signing</P> + <input type="checkbox" name="extKeyUsage-emailProtect"> Email Protection</P> + <input type="checkbox" name="extKeyUsage-timeStamp"> Timestamp</P> + <input type="checkbox" name="extKeyUsage-ocspResponder"> OCSP Responder</P> + <input type="checkbox" name="extKeyUsage-NS-govtApproved"> Step-up</P> + <input type="checkbox" name="extKeyUsage-msTrustListSign"> Microsoft Trust List Signing</P> + </tr> + <tr> + <td> + <b>Basic Constraints:</b></p> + Activate extension: <input type="checkbox" name="basicConstraints"></P> + Critical: <input type="checkbox" name="basicConstraints-crit"> + <td> + CA:</p> + <dd><input type=radio name="basicConstraints-cA-radio" value="CA"> True</p> + <dd><input type=radio name="basicConstraints-cA-radio" value="NotCA"> False</p> + <input type="checkbox" name="basicConstraints-pathLengthConstraint"> + Include Path length: <input type="text" name="basicConstraints-pathLengthConstraint-text" size="2"></p> + </tr> + <tr> + <td> + <b>Authority Key Identifier:</b></p> + Activate extension: <input type="checkbox" name="authorityKeyIdentifier"> + <td> + <input type="radio" name="authorityKeyIdentifier-radio" value="keyIdentifier"> Key Identider</p> + <input type="radio" name="authorityKeyIdentifier-radio" value="authorityCertIssuer"> Issuer Name and Serial number</p> + </tr> + <tr> + <td> + <b>Subject Key Identifier:</b></p> + Activate extension: <input type="checkbox" name="subjectKeyIdentifier"> + <td> + Key Identifier: + <input type="text" name="subjectKeyIdentifier-text"></p> + This is an:<p> + <dd><dd><input type="radio" name="subjectKeyIdentifier-radio" value="ascii"> ascii text value<p> + <dd><dd><input type="radio" name="subjectKeyIdentifier-radio" value="hex"> hex value<p> + </tr> + <tr> + <td> + <b>Private Key Usage Period:</b></p> + Activate extension: <input type="checkbox" name="privKeyUsagePeriod"></p> + Critical: <input type="checkbox" name="privKeyUsagePeriod-crit"> + <td> + Use:</p> + <dd><input type="radio" name="privKeyUsagePeriod-radio" value="notBefore"> Not Before</p> + <dd><input type="radio" name="privKeyUsagePeriod-radio" value="notAfter"> Not After</p> + <dd><input type="radio" name="privKeyUsagePeriod-radio" value="both" > Both</p> + <b>Not to be used to sign before:</b></p> + <dd><input type="radio" name="privKeyUsagePeriod-notBefore-radio" value="auto"> Set to time of certificate issue</p> + <dd><input type="radio" name="privKeyUsagePeriod-notBefore-radio" value="manual"> Use This value</p> + <dd><dd>(YYYY/MM/DD HH:MM:SS): + <input type="text" name="privKeyUsagePeriod-notBefore-year" size="4" maxlength="4">/ + <input type="text" name="privKeyUsagePeriod-notBefore-month" size="2" maxlength="2">/ + <input type="text" name="privKeyUsagePeriod-notBefore-day" size="2" maxlength="2"> + <input type="text" name="privKeyUsagePeriod-notBefore-hour" size="2" maxlength="2">: + <input type="text" name="privKeyUsagePeriod-notBefore-minute" size="2" maxlength="2">: + <input type="text" name="privKeyUsagePeriod-notBefore-second" size="2" maxlength="2"></p> + <b>Not to be used to sign after:</b></p> + <dd>(YYYY/MM/DD HH:MM:SS): + <input type="text" name="privKeyUsagePeriod-notAfter-year" size="4" maxlength="4">/ + <input type="text" name="privKeyUsagePeriod-notAfter-month" size="2" maxlength="2">/ + <input type="text" name="privKeyUsagePeriod-notAfter-day" size="2" maxlength="2"> + <input type="text" name="privKeyUsagePeriod-notAfter-hour" size="2" maxlength="2">: + <input type="text" name="privKeyUsagePeriod-notAfter-minute" size="2" maxlength="2">: + <input type="text" name="privKeyUsagePeriod-notAfter-second" size="2" maxlength="2"></p> + </tr> + <tr> + <td> + <b>Subject Alternative Name:</b></p> + Activate extension: <input type="checkbox" name="SubAltName"></P> + Critical: <input type="checkbox" name="SubAltName-crit"> + <td> + <table> + <tr> + <td> + General Names:</p> + <select name="SubAltNameSelect" multiple size="10"> + </select></p></p> + <input type="button" name="SubAltName-add" value="Add" onClick="{parent.addSubAltName(this.form)}"> + <input type="button" name="SubAltName-delete" value="Delete" onClick="parent.deleteSubAltName(this.form)"> + </td><td> + <table><tr><td> + Name Type: </td></tr><tr><td> + <input type="radio" name="SubAltNameRadio" value="otherName" onClick="parent.setSubAltNameType(form)"> Other Name, + OID: <input type="text" name="SubAltNameOtherNameOID" size="6"> </td><td> + <input type="radio" name="SubAltNameRadio" value="rfc822Name" onClick="parent.setSubAltNameType(form)"> RFC 822 Name</td></tr><td> + <input type="radio" name="SubAltNameRadio" value="dnsName" onClick="parent.setSubAltNameType(form)"> DNS Name </td><td> + <input type="radio" name="SubAltNameRadio" value="x400" onClick="parent.setSubAltNameType(form)"> X400 Address</td></tr><td> + <input type="radio" name="SubAltNameRadio" value="directoryName" onClick="parent.setSubAltNameType(form)"> Directory Name</td><td> + <input type="radio" name="SubAltNameRadio" value="ediPartyName" onClick="parent.setSubAltNameType(form)"> EDI Party Name</td></tr><td> + <input type="radio" name="SubAltNameRadio" value="URL" onClick="parent.setSubAltNameType(form)"> Uniform Resource Locator</td><td> + <input type="radio" name="SubAltNameRadio" value="ipAddress" onClick="parent.setSubAltNameType(form)"> IP Address</td></tr><td> + <input type="radio" name="SubAltNameRadio" value="regID"onClick="parent.setSubAltNameType(form)"> Registered ID</td><td> + <input type="radio" name="SubAltNameRadio" value="nscpNickname" onClick="parent.setSubAltNameType(form)"> Netscape Certificate Nickname</td><td></tr> + </table> + Name: <input type="text" name="SubAltNameText"> + Binary Encoded: <input type="checkbox" name="SubAltNameDataType" value="binary" onClick="parent.setSubAltNameType(form)"></p> + </tr> + </table> + </tr> + + + <tr> + <td> + <b>Issuer Alternative Name:</b></p> + Activate extension: <input type="checkbox" name="IssuerAltName"></P> + Critical: <input type="checkbox" name="IssuerAltName-crit"> + <td> + <input type="radio" name="IssuerAltNameSourceRadio" value="auto"> Use the Subject Alternative Name from the Issuers Certificate</p> + <input type="radio" name="IssuerAltNameSourceRadio" value="man"> Use this Name: + <table> + <tr> + <td> + General Names:</p> + <select name="IssuerAltNameSelect" multiple size="10"> + </select></p></p> + <input type="button" name="IssuerAltName-add" value="Add" onClick="{parent.addIssuerAltName(this.form)}"> + <input type="button" name="IssuerAltName-delete" value="Delete" onClick="parent.deleteIssuerAltName(this.form)"> + </td><td> + <table><tr><td> + Name Type: </td></tr><tr><td> + <input type="radio" name="IssuerAltNameRadio" value="otherName" onClick="parent.setIssuerAltNameType(form)"> Other Name, + OID: <input type="text" name="IssuerAltNameOtherNameOID" size="6"> </td><td> + <input type="radio" name="IssuerAltNameRadio" value="rfc822Name" onClick="parent.setIssuerAltNameType(form)"> RFC 822 Name</td></tr><td> + <input type="radio" name="IssuerAltNameRadio" value="dnsName" onClick="parent.setIssuerAltNameType(form)"> DNS Name </td><td> + <input type="radio" name="IssuerAltNameRadio" value="x400" onClick="parent.setIssuerAltNameType(form)"> X400 Address</td></tr><td> + <input type="radio" name="IssuerAltNameRadio" value="directoryName" onClick="parent.setIssuerAltNameType(form)"> Directory Name</td><td> + <input type="radio" name="IssuerAltNameRadio" value="ediPartyName" onClick="parent.setIssuerAltNameType(form)"> EDI Party Name</td></tr><td> + <input type="radio" name="IssuerAltNameRadio" value="URL" onClick="parent.setIssuerAltNameType(form)"> Uniform Resource Locator</td><td> + <input type="radio" name="IssuerAltNameRadio" value="ipAddress" onClick="parent.setIssuerAltNameType(form)"> IP Address</td></tr><td> + <input type="radio" name="IssuerAltNameRadio" value="regID" onClick="parent.setIssuerAltNameType(form)"> Registered ID</td><td></tr> + </table> + Name: <input type="text" name="IssuerAltNameText"> + Binary Encoded: <input type="checkbox" name="IssuerAltNameDataType" value="binary" onClick="parent.setIssuerAltNameType(form)"></p> + </tr> + </table> + </tr> + + <tr> + <td> + <b>Name Constraints:</b></p> + Activate extension: <input type="checkbox" name="NameConstraints"></P> + <td> + <table> + <tr> + <td> + Name Constraints:</p> + <select name="NameConstraintSelect" multiple size="10"> + </select></p></p> + <input type="button" name="NameConstraint-add" value="Add" onClick="{parent.addNameConstraint(this.form)}"> + <input type="button" name="NameConstraint-delete" value="Delete" onClick="parent.deleteNameConstraint(this.form)"> + </td><td> + <table><tr><td> + Name Type: </td></tr><tr><td> + <input type="radio" name="NameConstraintRadio" value="otherName" onClick="parent.setNameConstraintNameType(form)"> Other Name, + OID: <input type="text" name="NameConstraintOtherNameOID" size="6"> </td><td> + <input type="radio" name="NameConstraintRadio" value="rfc822Name" onClick="parent.setNameConstraintNameType(form)"> RFC 822 Name</td></tr><td> + <input type="radio" name="NameConstraintRadio" value="dnsName" onClick="parent.setNameConstraintNameType(form)"> DNS Name </td><td> + <input type="radio" name="NameConstraintRadio" value="x400" onClick="parent.setNameConstraintNameType(form)"> X400 Address</td></tr><td> + <input type="radio" name="NameConstraintRadio" value="directoryName" onClick="parent.setNameConstraintNameType(form)"> Directory Name</td><td> + <input type="radio" name="NameConstraintRadio" value="ediPartyName" onClick="parent.setNameConstraintNameType(form)"> EDI Party Name</td></tr><td> + <input type="radio" name="NameConstraintRadio" value="URL" onClick="parent.setNameConstraintNameType(form)"> Uniform Resource Locator</td><td> + <input type="radio" name="NameConstraintRadio" value="ipAddress" onClick="parent.setNameConstraintNameType(form)"> IP Address</td></tr><td> + <input type="radio" name="NameConstraintRadio" value="regID" onClick="parent.setNameConstraintNameType(form)"> Registered ID</td><td></tr> + </table> + Name: <input type="text" name="NameConstraintText"> + Binary Encoded: <input type="checkbox" name="NameConstraintNameDataType" value="binary" onClick="parent.setNameConstraintNameType(form)"></p> + Constraint type:<p> + <dd><input type="radio" name="NameConstraintTypeRadio" value="permited"> permited<p> + <dd><input type="radio" name="NameConstraintTypeRadio" value="excluded"> excluded<p> + Minimum: <input type="text" name="NameConstraintMin" size="8" maxlength="8"></p> + Maximum: <input type="text" name="NameConstraintMax" size="8" maxlength="8"></p> + </tr> + </table> + </tr> + + </table> + </body> +</html> + + + + + + + + |