Java tutorial
/* Copyright (C) 2007 Flix Garca Borrego (borrego at gmail.com) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ package org.viafirma.nucleo.X509; import java.security.cert.X509Certificate; import java.util.Date; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.regex.Pattern; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.viafirma.excepciones.ExcepcionErrorInterno; import org.viafirma.plugin.AuthoritySupportPlugin; import org.viafirma.plugin.PluginLocator; import org.viafirma.util.RegExpTokenizer; import org.viafirma.vo.CertificadoGenerico; /** * Parsea un certificado X509 extrayendo la informacin del usuario. * * @author Felix Garcia Borrego (borrego at gmail.com) */ public class CertificadoGenericoFactory { /** * Oid del tipo email */ private static final String OID_EMAIL = "2.5.29.17"; private static Log log = LogFactory.getLog(CertificadoGenericoFactory.class); /** * Expresin regular para el troceado de la Signature. * * Notas: * \p{InLatin-1_Supplement}: U+0080..U+00FF * \p{InLatin_Extended-A}: U+0100..U+017F * \p{InLatin_Extended-B}: U+0180..U+024F */ private Pattern patternSignature = Pattern .compile("([A-Z0-9\\.]*=)|((\".*\")?([\\.\\w\\s0-9\\u0080-\\u00FF])*\\s?)[\\,]"); private static CertificadoGenericoFactory singleton; public static CertificadoGenericoFactory getInstance() { if (singleton == null) { singleton = new CertificadoGenericoFactory(); } return singleton; } /** * Retorna un certificado generico parseando los datos de un certificado X509 * @param certificadoX509 * @return */ public CertificadoGenerico generar(X509Certificate certificadoX509) { CertificadoGenerico certificado = new CertificadoGenerico(); // recuperamos el conjunto de oids Map<String, String> propiedadesOid = X509Handler.getCurrentInstance().readPropertiesOid(certificadoX509); String subject = certificadoX509.getSubjectDN().toString(); // parseo el subject //StringTokenizer tokenizer=new StringTokenizer(subject,",\""); //String [] tokens=subject.split(","); //for (int i = 0; i < tokens.length; i++) { // String parIdValor = tokens[i].trim(); // String id= parIdValor.split("=")[0]; // String valor= parIdValor.split("=")[1]; // propiedadesOid.put(id,valor); //} loadPropiedadesOid(subject, propiedadesOid); // guardo todas las propiedades(pintables) Set<String> keys = propiedadesOid.keySet(); for (Iterator<String> iter = keys.iterator(); iter.hasNext();) { String key = iter.next(); String valor = propiedadesOid.get(key); // FIX: Problema con el encondig utf-8 en openid. String newValue = StringUtils.replaceChars(valor, "??", "aeiounuAEIOU"); if (!StringUtils.isAsciiPrintable(newValue)) { // omitimos el campo iter.remove(); } else { // remplazamos el valor propiedadesOid.put(key, newValue); } } certificado.setPropiedades(propiedadesOid); // identifico el nombre de la CA propietaria del certificado certificado.setCa(certificadoX509.getIssuerDN().getName()); certificado.setNombre(certificado.getPropiedades().get("1.3.6.1.4.1.5734.1.1")); certificado.setApellido1(certificado.getPropiedades().get("1.3.6.1.4.1.5734.1.2")); certificado.setApellido2(certificado.getPropiedades().get("1.3.6.1.4.1.5734.1.3")); certificado.setNumberUserId(certificado.getPropiedades().get("1.3.6.1.4.1.5734.1.4")); certificado.setCn(propiedadesOid.get("CN")); // si no hemos recuperado el nombre en la extensin lo intento recuperar del GIVENNAME. if (StringUtils.isEmpty(certificado.getNombre())) { certificado.setNombre(propiedadesOid.get("GIVENNAME")); } // si no hemos recuperado el nombre APELLIDO. if (StringUtils.isEmpty(certificado.getApellido1())) { certificado.setApellido1(propiedadesOid.get("SURNAME")); } // si no tenemos apelligos, los intentamos recuperar del CN ( cado del edni) // CN="Apelido1 apellido2, nombre (AUTENTICACIN)", if (StringUtils.isEmpty(certificado.getApellido1())) { // TODO, no se recupera correctamente el CN, pero el resultado es el correcto. // Debera de ser StringUtils.substringAfterLast(propiedadesOid.get("CN").replaceAll("\"", ""),",") // pero nos vale con propiedadesOid.get("CN") certificado.setApellido1(propiedadesOid.get("CN")); } // si no hemos recuperado el nombre NIF. if (StringUtils.isEmpty(certificado.getNumberUserId())) { certificado.setNumberUserId(propiedadesOid.get("SERIALNUMBER")); } // si no hemos recuperado el nombre email. if (StringUtils.isEmpty(certificado.getEmail())) { certificado.setEmail(certificado.getPropiedades().get(OID_EMAIL)); } // si sige siendo null lo recupero del oid if (StringUtils.isEmpty(certificado.getEmail())) { certificado.setEmail(propiedadesOid.get("EMAILADDRESS")); } // si no hemos recuperado el pais if (StringUtils.isEmpty(certificado.getPais())) { certificado.setPais(certificado.getPropiedades().get("C")); } // filtrado para que ningun campo sea null if (certificado.getApellido1() == null) { certificado.setApellido1(""); } if (certificado.getApellido2() == null) { certificado.setApellido2(""); } if (certificado.getCa() == null) { certificado.setCa(""); } if (certificado.getEmail() == null) { certificado.setEmail(""); } if (certificado.getNombre() == null) { certificado.setNombre(""); } if (certificado.getPais() == null) { certificado.setPais(""); } if (certificado.getNumberUserId() == null) { certificado.setNumberUserId(""); } // recupero el cargo. String cargo = propiedadesOid.get("T"); if (cargo != null) { certificado.setCargo(cargo); } // recupero el nombre de la organizacin. String organizacion = propiedadesOid.get("O"); if (organizacion != null) { certificado.setOrganizacion(organizacion); } // Detectamos si el certificado est caducado Date hoy = new Date(); if (certificadoX509.getNotAfter().before(hoy)) { // el certificado est caducado. certificado.setCaducado(true); } // recuperar el tpo de certificado loadTipoCertificado(certificado, propiedadesOid, certificado.getCa()); return certificado; } /** * Parsea el subject para obtener la informacin. * * Ejemplo de algunos subject soportados: <br/> * CN=AC DNIE 001, OU=DNIE, O=DIRECCION GENERAL DE LA POLICIA, C=ES <br/> * CN="Apellido1 Apellido2, Nombre (AUTENTICACIN)", GIVENNAME=NOMBRE, SURNAME=APELLIDO1, SERIALNUMBER=000000J, C=ES <br/> * CN=NOMBRE APELLIDO1 APELLIDO2 NOMBRE - NIF 000000K,OU=703002483,OU=FNMT Clase 2 CA,O=FNMT,C=ES <br/> * EMAILADDRESS=email, CN=NOMBRE APELLIDO, GIVENNAME=NOMBRE, SURNAME=APELLIDO, SERIALNUMBER=00000J, OU=1-11-11111-1, O=AVANSI CXA Certificados Firma Republica Dominicana, C=DO * @param subject * @param propiedadesOid */ public void loadPropiedadesOid(String subject, Map<String, String> propiedadesOid) { // parseo el subject String nombreVariable = null; String value = null; // Aadimos el mismo separador al final, para detectar fin de subject subject = subject + ","; RegExpTokenizer tokenizer = new RegExpTokenizer(subject, patternSignature, false); while (tokenizer.hasNext()) { nombreVariable = tokenizer.next(); if (nombreVariable.contains("=")) { nombreVariable = nombreVariable.replaceAll("=", ""); tokenizer.hasNext();// comprueba y avanza value = tokenizer.next().replaceAll("\"", ""); value = StringUtils.substringBeforeLast(value, ","); propiedadesOid.put(nombreVariable, value); } } } /** * Reconoce de que tipo es un certificado dentro de la ca actual y recupera parametros especficos segun el tpo. * Intica el tipo juridico del certificado. * @param certificado * @param propiedadesOid * @param ca */ private void loadTipoCertificado(CertificadoGenerico certificado, Map<String, String> propiedadesOid, String ca) { // Recupero el plugin asociado a este tipo de certificados AuthoritySupportPlugin support; try { support = PluginLocator.getAuthoritySupport(certificado); // Recupero el tipo de certificado String tipoCertificado = support.getTipoCertificado(certificado); if (tipoCertificado != null) { certificado.setTipoCertificado(tipoCertificado); } // Recupero el tipo juridico del certificado TipoJuridicoCertificado tipoJuridico = support.getJuridicoCertificado(certificado); if (tipoJuridico != null) { certificado.setTipoJuridico(tipoJuridico); } } catch (ExcepcionErrorInterno e) { log.fatal("Tipo de certificado no reconocido", e); } } }