org.viafirma.nucleo.X509.CertificadoGenericoFactory.java Source code

Java tutorial

Introduction

Here is the source code for org.viafirma.nucleo.X509.CertificadoGenericoFactory.java

Source

/* 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);
        }

    }

}