// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package com.netscape.cms.servlet.csadmin; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.math.BigInteger; import java.util.Date; import javax.servlet.http.HttpServletResponse; import netscape.ldap.LDAPException; import netscape.security.pkcs.PKCS10; import netscape.security.x509.CertificateExtensions; import netscape.security.x509.X500Name; import netscape.security.x509.X509CertImpl; import netscape.security.x509.X509CertInfo; import netscape.security.x509.X509Key; import org.apache.velocity.context.Context; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.crypto.PrivateKey; import org.mozilla.jss.crypto.X509Certificate; import com.netscape.certsrv.apps.CMS; import com.netscape.certsrv.base.EBaseException; import com.netscape.certsrv.base.IConfigStore; import com.netscape.certsrv.base.MetaInfo; import com.netscape.certsrv.ca.ICertificateAuthority; import com.netscape.certsrv.dbs.certdb.ICertRecord; import com.netscape.certsrv.dbs.certdb.ICertificateRepository; import com.netscape.certsrv.profile.CertInfoProfile; import com.netscape.certsrv.profile.IEnrollProfile; import com.netscape.certsrv.request.IRequest; import com.netscape.certsrv.request.IRequestQueue; import com.netscape.certsrv.request.RequestId; import com.netscape.certsrv.request.RequestStatus; import com.netscape.certsrv.usrgrp.IGroup; import com.netscape.certsrv.usrgrp.IUGSubsystem; import com.netscape.certsrv.usrgrp.IUser; import com.netscape.cmsutil.crypto.CryptoUtil; import com.netscape.cmsutil.http.HttpClient; import com.netscape.cmsutil.http.HttpRequest; import com.netscape.cmsutil.http.HttpResponse; import com.netscape.cmsutil.http.JssSSLSocketFactory; import com.netscape.cmsutil.xml.XMLObject; public class CertUtil { static final int LINE_COUNT = 76; public static X509CertImpl createRemoteCert(String hostname, int port, String content, HttpServletResponse response, WizardPanelBase panel) throws IOException { HttpClient httpclient = new HttpClient(); String c = null; CMS.debug("CertUtil createRemoteCert: content " + content); try { JssSSLSocketFactory factory = new JssSSLSocketFactory(); httpclient = new HttpClient(factory); httpclient.connect(hostname, port); HttpRequest httprequest = new HttpRequest(); httprequest.setMethod(HttpRequest.POST); httprequest.setURI("/ca/ee/ca/profileSubmit"); httprequest.setHeader("user-agent", "HTTPTool/1.0"); httprequest.setHeader("content-length", "" + content.length()); httprequest.setHeader("content-type", "application/x-www-form-urlencoded"); httprequest.setContent(content); HttpResponse httpresponse = httpclient.send(httprequest); c = httpresponse.getContent(); } catch (Exception e) { CMS.debug("CertUtil createRemoteCert: " + e.toString()); throw new IOException(e.toString()); } if (c != null) { try { ByteArrayInputStream bis = new ByteArrayInputStream(c.getBytes()); XMLObject parser = null; try { parser = new XMLObject(bis); } catch (Exception e) { CMS.debug( "CertUtil::createRemoteCert() - " + "Exception="+e.toString() ); throw new IOException( e.toString() ); } String status = parser.getValue("Status"); CMS.debug("CertUtil createRemoteCert: status=" + status); if (status.equals("2")) { //relogin to the security domain panel.reloginSecurityDomain(response); return null; } else if (!status.equals("0")) { String error = parser.getValue("Error"); throw new IOException(error); } String b64 = parser.getValue("b64"); CMS.debug("CertUtil createRemoteCert: " + b64); b64 = CryptoUtil.normalizeCertAndReq(b64); byte[] b = CryptoUtil.base64Decode(b64); return new X509CertImpl(b); } catch (Exception e) { CMS.debug("CertUtil createRemoteCert: " + e.toString()); throw new IOException(e.toString()); } } return null; } public static String getPKCS10(IConfigStore config, String prefix, Cert certObj, Context context) throws IOException { String certTag = certObj.getCertTag(); X509Key pubk = null; try { String pubKeyType = config.getString( prefix + certTag + ".keytype"); String algorithm = config.getString( prefix + certTag + ".keyalgorithm"); if (pubKeyType.equals("rsa")) { String pubKeyModulus = config.getString( prefix + certTag + ".pubkey.modulus"); String pubKeyPublicExponent = config.getString( prefix + certTag + ".pubkey.exponent"); pubk = CryptoUtil.getPublicX509Key( CryptoUtil.string2byte(pubKeyModulus), CryptoUtil.string2byte(pubKeyPublicExponent)); } else if (pubKeyType.equals("ecc")) { String pubKeyEncoded = config.getString( prefix + certTag + ".pubkey.encoded"); pubk = CryptoUtil.getPublicX509ECCKey( CryptoUtil.string2byte(pubKeyEncoded)); } else { CMS.debug( "CertRequestPanel::getPKCS10() - " + "public key type is unsupported!" ); throw new IOException( "public key type is unsupported" ); } if (pubk != null) { CMS.debug("CertRequestPanel: got public key"); } else { CMS.debug("CertRequestPanel: error getting public key null"); throw new IOException( "public key is null" ); } // get private key String privKeyID = config.getString(prefix + certTag + ".privkey.id"); byte[] keyIDb = CryptoUtil.string2byte(privKeyID); PrivateKey privk = CryptoUtil.findPrivateKeyFromID(keyIDb); if (privk != null) { CMS.debug("CertRequestPanel: got private key"); } else { CMS.debug("CertRequestPanel: error getting private key null"); } // construct cert request String dn = config.getString(prefix + certTag + ".dn"); PKCS10 certReq = null; certReq = CryptoUtil.createCertificationRequest(dn, pubk, privk, algorithm); byte[] certReqb = certReq.toByteArray(); String certReqs = CryptoUtil.base64Encode(certReqb); return certReqs; } catch (Throwable e) { CMS.debug(e); context.put("errorString", e.toString()); CMS.debug("CertUtil getPKCS10: " + e.toString()); throw new IOException(e.toString()); } } /* * create requests so renewal can work on these initial certs */ public static IRequest createLocalRequest(IRequestQueue queue, String serialNum, X509CertInfo info) throws EBaseException { // RequestId rid = new RequestId(serialNum); // just need a request, no need to get into a queue // IRequest r = new EnrollmentRequest(rid); CMS.debug("CertUtil: createLocalRequest for serial: "+ serialNum); IRequest req = queue.newRequest("enrollment"); CMS.debug("certUtil: newRequest called"); req.setExtData("profile", "true"); req.setExtData("requestversion", "1.0.0"); req.setExtData("req_seq_num", "0"); req.setExtData(IEnrollProfile.REQUEST_CERTINFO, info); req.setExtData(IEnrollProfile.REQUEST_EXTENSIONS, new CertificateExtensions()); req.setExtData("requesttype", "enrollment"); req.setExtData("requestor_name", ""); req.setExtData("requestor_email", ""); req.setExtData("requestor_phone", ""); req.setExtData("profileRemoteHost", ""); req.setExtData("profileRemoteAddr", ""); req.setExtData("requestnotes",""); req.setExtData("isencryptioncert", "false"); req.setExtData("profileapprovedby", "system"); // mark request as complete CMS.debug("certUtil: calling setRequestStatus"); req.setRequestStatus(RequestStatus.COMPLETE); return req; } /** * update local cert request with the actual request * called from CertRequestPanel.java */ public static void updateLocalRequest(IConfigStore config, String certTag, String certReq, String reqType, String subjectName) { try { CMS.debug("Updating local request... certTag=" + certTag); RequestId rid = new RequestId(config.getString("preop.cert." + certTag + ".reqId")); ICertificateAuthority ca = (ICertificateAuthority) CMS.getSubsystem( ICertificateAuthority.ID); IRequestQueue queue = ca.getRequestQueue(); if (queue != null) { IRequest req = queue.findRequest(rid); if (req != null) { if (!certReq.equals("")) req.setExtData("cert_request", certReq); req.setExtData("cert_request_type", reqType); if (subjectName != null) { req.setExtData("subject", subjectName); X500Name x5Name = new X500Name(subjectName); } } queue.updateRequest(req); } else { CMS.debug("CertUtil:updateLocalRequest - request queue = null"); } } catch (Exception e) { CMS.debug("CertUtil:updateLocalRequest - Exception:" + e.toString()); } } /** * reads from the admin cert profile caAdminCert.profile and takes the first * entry in the list of allowed algorithms. Users that wish a different algorithm * can specify it in the profile using default.params.signingAlg */ public static String getAdminProfileAlgorithm(IConfigStore config) { String algorithm = "SHA256withRSA"; try { String caSigningKeyType = config.getString("preop.cert.signing.keytype","rsa"); String pfile = config.getString("profile.caAdminCert.config"); FileInputStream fis = new FileInputStream(pfile); DataInputStream in = new DataInputStream(fis); BufferedReader br = new BufferedReader(new InputStreamReader(in)); String strLine; while ((strLine = br.readLine()) != null) { String marker2 = "default.params.signingAlg="; int indx = strLine.indexOf(marker2); if (indx != -1) { String alg = strLine.substring(indx + marker2.length()); if ((alg.length() > 0) && (!alg.equals("-"))) { algorithm = alg; break; }; }; String marker = "signingAlgsAllowed="; indx = strLine.indexOf(marker); if (indx != -1) { String[] algs = strLine.substring(indx + marker.length()).split(","); for (int i=0; i= LINE_COUNT) { result.append(content.substring(0, LINE_COUNT)); result.append("\n"); content = content.substring(LINE_COUNT); } if (content.length() > 0) result.append(content); result.append("\n"); return result.toString(); } public static boolean privateKeyExistsOnToken(String certTag, String tokenname, String nickname) { IConfigStore cs = CMS.getConfigStore(); String givenid = ""; try { givenid = cs.getString("preop.cert."+certTag+".privkey.id"); } catch (Exception e) { CMS.debug("CertUtil privateKeyExistsOnToken: we did not generate private key yet."); return false; } String fullnickname = nickname; boolean hardware = false; if (!tokenname.equals("internal") && !tokenname.equals("Internal Key Storage Token")) { hardware = true; fullnickname = tokenname+":"+nickname; } X509Certificate cert = null; CryptoManager cm = null; try { cm = CryptoManager.getInstance(); cert = cm.findCertByNickname(fullnickname); } catch (Exception e) { CMS.debug("CertUtil privateKeyExistsOnToken: nickname="+fullnickname+" Exception:"+e.toString()); return false; } PrivateKey privKey = null; try { privKey = cm.findPrivKeyByCert(cert); } catch (Exception e) { CMS.debug("CertUtil privateKeyExistsOnToken: cant find private key ("+fullnickname+") exception: "+e.toString()); return false; } if (privKey == null) { CMS.debug("CertUtil privateKeyExistsOnToken: cant find private key ("+fullnickname+")"); return false; } else { String str = ""; try { str = CryptoUtil.byte2string(privKey.getUniqueID()); } catch (Exception e) { CMS.debug("CertUtil privateKeyExistsOnToken: encode string Exception: "+e.toString()); } if (str.equals(givenid)) { CMS.debug("CertUtil privateKeyExistsOnToken: find the private key on the token."); return true; } } return false; } }