/*
* eID Applet Project.
* Copyright (C) 2014-2015 e-Contract.be BVBA.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License version
* 3.0 as published by the Free Software Foundation.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, see
* http://www.gnu.org/licenses/.
*/
package test.be.fedict.eid.applet;
import java.io.IOException;
import java.io.Serializable;
import java.security.MessageDigest;
import java.security.cert.X509Certificate;
import javax.enterprise.context.SessionScoped;
import javax.enterprise.event.Observes;
import javax.faces.application.FacesMessage;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.inject.Named;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import be.fedict.eid.applet.service.Address;
import be.fedict.eid.applet.service.Identity;
import be.fedict.eid.applet.service.cdi.AuthenticatedEvent;
import be.fedict.eid.applet.service.cdi.AuthenticationEvent;
import be.fedict.eid.applet.service.cdi.BeIDContext;
import be.fedict.eid.applet.service.cdi.IdentificationEvent;
import be.fedict.eid.applet.service.cdi.IdentityEvent;
import be.fedict.eid.applet.service.cdi.SecureChannelBindingEvent;
import be.fedict.eid.applet.service.cdi.SignatureDigestEvent;
import be.fedict.eid.applet.service.cdi.SignatureEvent;
import be.fedict.eid.applet.service.cdi.StartEvent;
import be.fedict.eid.applet.service.cdi.StartEvent.AuthenticationRequest;
import be.fedict.eid.applet.service.cdi.StartEvent.IdentificationRequest;
import be.fedict.eid.applet.service.cdi.StartEvent.SigningRequest;
import be.fedict.eid.applet.service.spi.AuthorizationException;
import be.fedict.eid.applet.service.spi.CertificateSecurityException;
import be.fedict.eid.applet.service.spi.ExpiredCertificateSecurityException;
import be.fedict.eid.applet.service.spi.RevokedCertificateSecurityException;
import be.fedict.eid.applet.service.spi.TrustCertificateSecurityException;
@Named("cdiTest")
@SessionScoped
public class Controller implements Serializable {
private static final long serialVersionUID = 1L;
private static final Log LOG = LogFactory.getLog(Controller.class);
public static enum Operation {
IDENTIFICATION, AUTHENTICATION, SIGNING
}
public static enum PKIValidation {
OK, CERTIFICATE_ERROR, CERTIFICATE_EXPIRED, CERTIFICATE_REVOKED, CERTIFICATE_NOT_TRUSTED, AUTHORIZATION
}
private Operation operation;
private PKIValidation pkiValidation;
private Identity identity;
private String userIdentifier;
private Address address;
private boolean includeIdentity;
private boolean includeAddress;
private boolean includePhoto;
private boolean includeCertificates;
private boolean logoff;
private boolean removeCard;
private boolean secureChannelBinding;
private X509Certificate serverCertificate;
private String message;
public String getMessage() {
return this.message;
}
public void setMessage(String message) {
this.message = message;
}
public void loadAction() {
if (null != this.message) {
FacesContext facesContext = FacesContext.getCurrentInstance();
facesContext.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, this.message, null));
this.message = null;
}
}
public void setOperation(Operation operation) {
this.operation = operation;
}
public Operation getOperation() {
return this.operation;
}
public Operation[] getOperations() {
return Operation.values();
}
public PKIValidation getPkiValidation() {
return this.pkiValidation;
}
public void setPkiValidation(PKIValidation pkiValidation) {
this.pkiValidation = pkiValidation;
}
public PKIValidation[] getPkiValidations() {
return PKIValidation.values();
}
public Identity getIdentity() {
return this.identity;
}
public String getUserIdentifier() {
return this.userIdentifier;
}
public Address getAddress() {
return this.address;
}
public boolean isIncludeIdentity() {
return this.includeIdentity;
}
public void setIncludeIdentity(boolean includeIdentity) {
this.includeIdentity = includeIdentity;
}
public boolean isIncludeAddress() {
return this.includeAddress;
}
public void setIncludeAddress(boolean includeAddress) {
this.includeAddress = includeAddress;
}
public boolean isIncludePhoto() {
return this.includePhoto;
}
public void setIncludePhoto(boolean includePhoto) {
this.includePhoto = includePhoto;
}
public boolean isIncludeCertificates() {
return this.includeCertificates;
}
public void setIncludeCertificates(boolean includeCertificates) {
this.includeCertificates = includeCertificates;
}
public boolean isLogoff() {
return this.logoff;
}
public void setLogoff(boolean logoff) {
this.logoff = logoff;
}
public boolean isRemoveCard() {
return this.removeCard;
}
public void setRemoveCard(boolean removeCard) {
this.removeCard = removeCard;
}
public boolean isSecureChannelBinding() {
return this.secureChannelBinding;
}
public void setSecureChannelBinding(boolean secureChannelBinding) {
this.secureChannelBinding = secureChannelBinding;
}
public X509Certificate getServerCertificate() {
return this.serverCertificate;
}
public void reset() {
this.identity = null;
this.address = null;
this.userIdentifier = null;
this.serverCertificate = null;
}
public void perform() throws IOException {
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
externalContext.redirect(externalContext.getRequestContextPath() + "/cdi.html");
}
public void handleStart(@Observes @BeIDContext(IdentifyCDIServlet.CONTEXT) StartEvent startEvent) {
LOG.debug("start event");
switch (this.operation) {
case IDENTIFICATION: {
IdentificationRequest identificationRequest = startEvent.performIdentification();
if (this.includeAddress) {
identificationRequest.includeAddress();
}
if (this.includePhoto) {
identificationRequest.includePhoto();
}
if (this.removeCard) {
identificationRequest.removeCard();
}
if (this.includeCertificates) {
identificationRequest.includeCertificates();
}
break;
}
case AUTHENTICATION: {
AuthenticationRequest authenticationRequest = startEvent.performAuthentication();
if (this.includeIdentity) {
authenticationRequest.includeIdentity();
}
if (this.includeAddress) {
authenticationRequest.includeAddress();
}
if (this.includePhoto) {
authenticationRequest.includePhoto();
}
if (this.removeCard) {
authenticationRequest.removeCard();
}
if (this.logoff) {
authenticationRequest.logoff();
}
if (this.secureChannelBinding) {
authenticationRequest.enableSecureChannelBinding();
}
break;
}
case SIGNING: {
SigningRequest signingRequest = startEvent.performSigning();
if (this.includeIdentity) {
signingRequest.includeIdentity();
}
if (this.includeAddress) {
signingRequest.includeAddress();
}
if (this.includePhoto) {
signingRequest.includePhoto();
}
if (this.includeCertificates) {
signingRequest.includeCertificates();
}
break;
}
default:
throw new IllegalStateException("unsupported operation: " + this.operation);
}
}
public void handleReset(@Observes @BeIDContext(IdentifyCDIServlet.CONTEXT) StartEvent startEvent) {
reset();
}
public void handleIdentification(
@Observes @BeIDContext(IdentifyCDIServlet.CONTEXT) IdentificationEvent identificationEvent)
throws Exception {
emulatePkiValidation();
identificationEvent.valid();
}
public void handleIdentity(@Observes @BeIDContext(IdentifyCDIServlet.CONTEXT) IdentityEvent identityEvent) {
LOG.debug("handle identity");
LOG.debug("hello: " + identityEvent.getIdentity().getFirstName());
this.identity = identityEvent.getIdentity();
this.address = identityEvent.getAddress();
}
public void handleAuthCertValidation(
@Observes @BeIDContext(IdentifyCDIServlet.CONTEXT) AuthenticationEvent authenticationEvent)
throws Exception {
emulatePkiValidation();
authenticationEvent.valid();
}
public void handleAuthenticatedUser(
@Observes @BeIDContext(IdentifyCDIServlet.CONTEXT) AuthenticatedEvent authenticatedEvent) {
this.userIdentifier = authenticatedEvent.getUserIdentifier();
}
public void handleSignatureDigest(
@Observes @BeIDContext(IdentifyCDIServlet.CONTEXT) SignatureDigestEvent signatureDigestEvent)
throws Exception {
if (this.includeCertificates && null == signatureDigestEvent.getSigningCertificateChain()) {
throw new RuntimeException("signing certificates not included");
}
if (this.includeCertificates) {
if (this.pkiValidation != null && this.pkiValidation == PKIValidation.AUTHORIZATION) {
throw new AuthorizationException();
}
}
byte[] data = "hello world".getBytes();
MessageDigest messageDigest = MessageDigest.getInstance("SHA1");
messageDigest.update(data);
byte[] digestValue = messageDigest.digest();
String digestAlgo = "SHA1";
signatureDigestEvent.sign(digestValue, digestAlgo, "test");
if (this.removeCard) {
signatureDigestEvent.removeCard();
}
if (this.logoff) {
signatureDigestEvent.logoff();
}
}
public void handleSignature(@Observes @BeIDContext(IdentifyCDIServlet.CONTEXT) SignatureEvent signatureEvent)
throws Exception {
LOG.debug("signature event");
emulatePkiValidation();
}
private void emulatePkiValidation() throws Exception {
if (null == this.pkiValidation) {
return;
}
switch (this.pkiValidation) {
case OK:
case AUTHORIZATION:
break;
case CERTIFICATE_ERROR:
throw new CertificateSecurityException();
case CERTIFICATE_EXPIRED:
throw new ExpiredCertificateSecurityException();
case CERTIFICATE_REVOKED:
throw new RevokedCertificateSecurityException();
case CERTIFICATE_NOT_TRUSTED:
throw new TrustCertificateSecurityException();
}
}
public void handleSecureChannelBinding(
@Observes @BeIDContext(IdentifyCDIServlet.CONTEXT) SecureChannelBindingEvent secureChannelBindingEvent) {
LOG.debug("secure channel identity: "
+ secureChannelBindingEvent.getServerCertificate().getSubjectX500Principal());
this.serverCertificate = secureChannelBindingEvent.getServerCertificate();
secureChannelBindingEvent.valid();
}
}