
org.globus.tools.GridCertRequest Maven / Gradle / Ivy
The newest version!
/**
* Copyright (c) 2003, National Research Council of Canada
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to
* do so, subject to the following conditions:
*
* The above copyright notice(s) and this licence appear in all copies of the
* Software or substantial portions of the Software, and that both the above
* copyright notice(s) and this license appear in supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE
* FOR ANY CLAIM, OR ANY DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL
* DAMAGES, OR ANY DAMAGES WHATSOEVER (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWSOEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OF THE SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Except as contained in this notice, the name of a copyright holder shall NOT
* be used in advertising or otherwise to promote the sale, use or other
* dealings in this Software without specific prior written authorization.
* Title to copyright in this software and any associated documentation will at
* all times remain with copyright holders.
*/
package org.globus.tools;
import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import org.bouncycastle.asn1.DERSet;
import org.bouncycastle.asn1.x509.X509Name;
import org.bouncycastle.jce.PKCS10CertificationRequest;
import org.bouncycastle.util.encoders.Base64;
import org.globus.common.Version;
import org.globus.common.CoGProperties;
import org.globus.gsi.CertUtil;
import org.globus.gsi.OpenSSLKey;
import org.globus.gsi.bc.BouncyCastleOpenSSLKey;
import org.globus.gsi.bc.X509NameHelper;
import org.globus.util.PEMUtils;
import org.globus.util.Util;
import org.globus.util.ConfigUtil;
/**
* GridCertRequest Command Line Client.
*
* @author Jean-Claude Cote
*/
public final class GridCertRequest {
public static final String USAGE =
"\n"
+ "\ngrid-cert-request [-help] [ options ...]"
+ "\n"
+ "\n Example Usage:"
+ "\n"
+ "\n Creating a user certifcate:"
+ "\n grid-cert-request"
+ "\n"
+ "\n Creating a host or gatekeeper certifcate:"
+ "\n grid-cert-request -host [my.host.fqdn]"
+ "\n"
+ "\n Creating a LDAP server certificate:"
+ "\n grid-cert-request -service ldap -host [my.host.fqdn]"
+ "\n"
+ "\n Options:"
+ "\n"
+ "\n -version : Display version"
+ "\n -?, -h, -help, : Display usage"
+ "\n -usage"
+ "\n -cn , : Common name of the user"
+ "\n -commonname "
+ "\n -service : Create certificate for a service. Requires"
+ "\n the -host option and implies that the generated"
+ "\n key will not be password protected (ie implies -nopw)."
+ "\n -host : Create certificate for a host named "
+ "\n -dir : Changes the directory the private key and certificate"
+ "\n request will be placed in. By default user certificates"
+ "\n are placed in " + System.getProperty("user.home") + File.separator + ".globus"
+ "\n directory. On Unix machines, host certificates are"
+ "\n placed in /etc/grid-security directory and service"
+ "\n certificates are placed in /etc/grid-security/."
+ "\n On Windows machines they are placed in the same"
+ "\n location as the user certificates."
+ "\n -prefix : Causes the generated files to be named"
+ "\n cert.pem, key.pem and"
+ "\n cert_request.pem"
+ "\n -nopw, : Create certificate without a password"
+ "\n -nodes,"
+ "\n -nopassphrase,"
+ "\n -verbose : Don't clear the screen <>"
+ "\n -int[eractive] : Prompt user for each component of the DN"
+ "\n -force : Overwrites preexisting certifictes"
+ "\n -caEmail : CA email address, if request is to be mailed to CA"
+ "\n -orgBaseDN : The base DN of this organization (in LDAP format)";
private static final String MESSAGE =
"A certificate request and private key will be created."
+ "\nYou will be asked to enter a PEM pass phrase."
+ "\nThis pass phrase is akin to your account password,"
+ "\nand is used to protect your key file."
+ "\nIf you forget your pass phrase, you will need to"
+ "\nobtain a new certificate.\n";
private static String caEmail = null;
private static String cn = null;
private static boolean interactive = false;
private static boolean verbose = false;
private static boolean noPswd = false;
private static String dir = null;
private static boolean force = false;
private static String prefix = null;
private static boolean debug = false;
public static void main(String[] args) {
parseCmdLine(args);
File certDir = new File(dir);
// Create dir if does not exists.
if (!certDir.exists()) {
// if fails exit
if (!certDir.mkdirs()) {
exit("Unable to create " + certDir + " directory.", 1);
}
}
// Make sure it's a directory.
if (!certDir.isDirectory()) {
exit("The directory " + certDir + " specified is not a directory.", 2);
}
// Make sure we can write to it.
if (!certDir.canWrite()) {
exit("Can't write to " + certDir, 3);
}
File certFile = new File(certDir, prefix + "cert.pem");
File keyFile = new File(certDir, prefix + "key.pem");
File certRequestFile = new File(certDir, prefix + "cert_request.pem");
// Check not to overwrite any of these files.
if (!force) {
boolean fileExists = false;
if (keyFile.exists()) {
System.err.println(keyFile + " exists");
fileExists = true;
}
if (certFile.exists()) {
System.err.println(certFile + " exists");
fileExists = true;
}
if (certRequestFile.exists()) {
System.err.println(certRequestFile + " exists");
fileExists = true;
}
if (fileExists) {
exit("If you wish to overwrite, run the script again with -force.", 4);
}
}
String password = null;
if (!noPswd) {
// Get password from user.
int attempts = 0;
boolean passOK = false;
System.out.println(MESSAGE);
while (attempts < 3) {
password = Util.getPrivateInput("Enter PEM pass phrase: ");
if (password.length() < 4) {
System.out.println("Phrase is too short, needs to be at least 4 chars");
attempts++;
continue;
}
String password2 =
Util.getPrivateInput("Verifying password - Enter PEM pass phrase: ");
if (password.compareTo(password2) == 0) {
passOK = true;
break;
} else {
System.out.println("Verify failure");
attempts++;
}
}
if (!passOK) {
exit("Too many attempts", 5);
}
}
// Generate cert request.
try {
genCertificateRequest(cn,
caEmail,
password,
keyFile,
certFile,
certRequestFile);
} catch (Exception e) {
System.err.println("Error generating cert request: " +
e.getMessage());
if (debug) {
e.printStackTrace();
}
System.exit(6);
}
}
private static void exit(String msg, int errorCode) {
System.err.println("Error: " + msg);
System.exit(errorCode);
}
private static void exit(String msg) {
exit(msg, 1);
}
protected static void parseCmdLine(String[] args) {
String hostName = null;
String service = null;
String orgBaseDN = null;
String name = System.getProperty("user.name");
for (int i = 0; i < args.length; i++) {
if (args[i].equalsIgnoreCase("-version")) {
System.err.println(Version.getVersion());
System.exit(1);
} else if (args[i].equalsIgnoreCase("-help")
|| args[i].equalsIgnoreCase("-h")
|| args[i].equalsIgnoreCase("-?")) {
exit(USAGE, 0);
} else if (args[i].equalsIgnoreCase("-cn")
|| args[i].equalsIgnoreCase("-commonname")) {
i++;
if (i == args.length) {
exit("-cn requires an argument");
} else {
// common name specified
name = args[i];
}
} else if (args[i].equalsIgnoreCase("-service")) {
i++;
if (i == args.length) {
exit("-service requires an argument");
} else {
// user certificate directory specified
service = args[i];
}
} else if (args[i].equalsIgnoreCase("-host")) {
i++;
if (i == args.length) {
exit("-host requires an argument");
} else {
// host name specified
hostName = args[i];
}
} else if (args[i].equalsIgnoreCase("-dir")) {
i++;
if (i == args.length) {
exit("-dir requires an argument");
} else {
// user certificate directory specified
dir = args[i];
}
} else if (args[i].equalsIgnoreCase("-prefix")) {
i++;
if (i == args.length) {
exit("-prefix requires an argument");
} else {
prefix = args[i];
}
} else if (args[i].equalsIgnoreCase("-nopw")
|| args[i].equalsIgnoreCase("-nodes")
|| args[i].equalsIgnoreCase("-nopassphrase")) {
// no password
noPswd = true;
} else if (args[i].equalsIgnoreCase("-verbose")) {
verbose = true;
} else if (args[i].equalsIgnoreCase("-int") ||
args[i].equalsIgnoreCase("-interactive")) {
// interactive mode
interactive = true;
} else if (args[i].equalsIgnoreCase("-force")) {
// overwrite existing credentials
force = true;
} else if (args[i].equalsIgnoreCase("-debug")) {
// overwrite existing credentials
debug = true;
} else if (args[i].equalsIgnoreCase("-caEmail")) {
i++;
if (i == args.length) {
exit("-caEmail requires an argument");
} else {
caEmail = args[i];
}
} else if (args[i].equalsIgnoreCase("-orgBaseDN")) {
i++;
if (i == args.length) {
exit("-orgBaseDN requires an argument");
} else {
orgBaseDN = args[i];
}
} else {
exit("argument #"
+ (i+1)
+ "("
+ args[i]
+ ") : unknown");
}
}
if (orgBaseDN == null) {
CoGProperties props = CoGProperties.getDefault();
orgBaseDN = props.getProperty("orgBaseDN");
if (orgBaseDN == null) {
if (interactive) {
orgBaseDN = getOrgName();
} else {
// just a default
orgBaseDN = "O=Grid";
}
}
}
if (service != null) {
if (hostName == null) {
exit("-host required");
} else {
cn = orgBaseDN + ", CN=" + service + "/" + hostName;
noPswd = true;
if (prefix == null) {
prefix = service;
}
if (dir == null && ConfigUtil.getOS() == ConfigUtil.UNIX_OS) {
dir = "/etc/grid-security/" + service;
}
}
} else if (hostName != null) {
cn = orgBaseDN + ", CN=host/" + hostName;
noPswd = true;
if (prefix == null) {
prefix = "host";
}
if (dir == null && ConfigUtil.getOS() == ConfigUtil.UNIX_OS) {
dir = "/etc/grid-security";
}
} else {
cn = orgBaseDN + ", CN=" + name;
if (prefix == null) {
prefix = "user";
}
}
if (dir == null) {
dir = System.getProperty("user.home") +
File.separator +
".globus";
}
}
/**
* Generates a encrypted private key and certificate request.
*/
static public void genCertificateRequest(String dname,
String emailAddressOfCA,
String password,
File keyFile,
File certFile,
File certReqFile)
throws Exception {
String sigAlgName = "MD5WithRSA";
String keyAlgName = "RSA";
CertUtil.init();
X509Name name = new X509Name(dname);
String certSubject = X509NameHelper.toString(name);
System.out.println("Generating a 1024 bit RSA private key");
// Generate a new key pair.
KeyPairGenerator keygen = KeyPairGenerator.getInstance(keyAlgName);
keygen.initialize(1024);
KeyPair keyPair = keygen.genKeyPair();
PrivateKey privKey = keyPair.getPrivate();
PublicKey pubKey = keyPair.getPublic();
// Generate the certificate request.
DERSet derSet = new DERSet();
PKCS10CertificationRequest request =
new PKCS10CertificationRequest(
sigAlgName,
name,
pubKey,
derSet,
privKey);
// Save the certificate request to a .pem file.
byte[] data = request.getEncoded();
byte[] encodedData = Base64.encode(data);
PrintStream ps = null;
try {
ps = new PrintStream(new FileOutputStream(certReqFile));
boolean caEmail = false;
if ((emailAddressOfCA != null) &&
(emailAddressOfCA.length() > 0)) {
caEmail = true;
ps.print("\n\n" + "Please mail the following certificate request to " + emailAddressOfCA);
} else {
ps.print("\n\n" + "Please send the following certificate request to the Certificate Authority (CA). Refer to CA instructions for details on to send the request.");
}
ps.print("\n\n"
+ "==================================================================\n"
+ "\n"
+ "Certificate Subject:\n"
+ "\n"
+ certSubject
+ "\n"
+ "\n"
+ "The above string is known as your user certificate subject, and it \n"
+ "uniquely identifies this user.\n"
+ "\n"
+ "To install this user certificate, please save this e-mail message\n"
+ "into the following file.\n"
+ "\n"
+ "\n"
+ certReqFile.getAbsolutePath()
+ "\n"
+ "\n"
+ "\n"
+ " You need not edit this message in any way. Simply \n"
+ " save this e-mail message to the file.\n"
+ "\n"
+ "\n"
+ "If you have any questions about the certificate contact\n"
+ "the Certificate Authority");
if (caEmail) {
ps.print("at " + emailAddressOfCA);
}
ps.print("\n\n");
PEMUtils.writeBase64(ps,
"-----BEGIN CERTIFICATE REQUEST-----",
encodedData,
"-----END CERTIFICATE REQUEST-----");
} finally {
if (ps != null) {
ps.close();
}
}
// Save private key to a .pem file.
OpenSSLKey key = new BouncyCastleOpenSSLKey(privKey);
if (password != null) {
key.encrypt(password);
}
// this will set the permissions correctly already
key.writeTo(keyFile.getAbsolutePath());
// Create an empty cert file.
certFile.createNewFile();
System.out.println("A private key and a certificate request has been generated with the subject:");
System.out.println();
System.out.println(certSubject);
System.out.println();
System.out.println("The private key is stored in " +
keyFile.getAbsolutePath());
System.out.println("The request is stored in " +
certReqFile.getAbsolutePath());
}
private static String getOrgName() {
System.out.println("-----");
System.out.println("You are about to be asked to enter information that will be incorporated");
System.out.println("into your certificate request.");
System.out.println("What you are about to enter is what is called a Distinguished Name or a DN.");
System.out.println("Enter organization DN by entering individual component names and their values.");
System.out.println("The component name can be one of: " + X509Name.DefaultLookUp.keySet());
System.out.println("-----");
StringBuffer orgName = new StringBuffer();
String component = null;
while ( (component = getComponent()) != null ) {
if (orgName.length() != 0) {
orgName.append(", ");
}
orgName.append(component);
}
if (orgName.length() == 0) {
exit("Invalid organization DN");
}
return orgName.toString();
}
private static String getComponent() {
String component = null;
while (true) {
component = Util.getInput("Enter name component: ");
if (component == null || component.trim().length() == 0) {
return null;
}
component = component.trim();
if (X509Name.DefaultLookUp.get(component.toLowerCase()) == null) {
System.out.println("Invalid component name");
} else {
break;
}
}
component = component.toUpperCase();
String value = Util.getInput("Enter '" + component + "' value: ");
if (value == null || value.trim().length() == 0) {
return null;
}
return component + "=" + value.trim();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy