org.opcfoundation.ua.examples.BigCertificateExample.java Source code

Java tutorial

Introduction

Here is the source code for org.opcfoundation.ua.examples.BigCertificateExample.java

Source

/* ========================================================================
* Copyright (c) 2005-2015 The OPC Foundation, Inc. All rights reserved.
*
* OPC Foundation MIT License 1.00
* 
* 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, sublicense, 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 and this permission notice shall be
* included in all copies or substantial portions of the Software.
* 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. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* The complete license agreement can be found here:
* http://opcfoundation.org/License/MIT/1.00/
* ======================================================================*/
package org.opcfoundation.ua.examples;

import java.io.IOException;
import java.net.URISyntaxException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.InvalidParameterSpecException;
import java.util.Random;

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

import org.apache.http.conn.ssl.SSLSocketFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.opcfoundation.ua.application.Application;
import org.opcfoundation.ua.application.Client;
import org.opcfoundation.ua.application.Server;
import org.opcfoundation.ua.application.SessionChannel;
import org.opcfoundation.ua.builtintypes.NodeId;
import org.opcfoundation.ua.builtintypes.StatusCode;
import org.opcfoundation.ua.builtintypes.UnsignedInteger;
import org.opcfoundation.ua.builtintypes.Variant;
import org.opcfoundation.ua.common.DebugLogger;
import org.opcfoundation.ua.common.ServiceFaultException;
import org.opcfoundation.ua.common.ServiceResultException;
import org.opcfoundation.ua.core.ActivateSessionRequest;
import org.opcfoundation.ua.core.ActivateSessionResponse;
import org.opcfoundation.ua.core.CallMethodRequest;
import org.opcfoundation.ua.core.CallMethodResult;
import org.opcfoundation.ua.core.CallRequest;
import org.opcfoundation.ua.core.CallResponse;
import org.opcfoundation.ua.core.CancelRequest;
import org.opcfoundation.ua.core.CancelResponse;
import org.opcfoundation.ua.core.CloseSessionRequest;
import org.opcfoundation.ua.core.CloseSessionResponse;
import org.opcfoundation.ua.core.CreateSessionRequest;
import org.opcfoundation.ua.core.CreateSessionResponse;
import org.opcfoundation.ua.core.EndpointConfiguration;
import org.opcfoundation.ua.core.EndpointDescription;
import org.opcfoundation.ua.core.GetEndpointsRequest;
import org.opcfoundation.ua.core.GetEndpointsResponse;
import org.opcfoundation.ua.core.MessageSecurityMode;
import org.opcfoundation.ua.core.MethodServiceSetHandler;
import org.opcfoundation.ua.core.SessionServiceSetHandler;
import org.opcfoundation.ua.core.SignatureData;
import org.opcfoundation.ua.core.StatusCodes;
import org.opcfoundation.ua.core.UserTokenPolicy;
import org.opcfoundation.ua.examples.certs.ExampleKeys;
import org.opcfoundation.ua.transport.ChannelService;
import org.opcfoundation.ua.transport.EndpointServer;
import org.opcfoundation.ua.transport.SecureChannel;
import org.opcfoundation.ua.transport.UriUtil;
import org.opcfoundation.ua.transport.endpoint.EndpointServiceRequest;
import org.opcfoundation.ua.transport.security.Cert;
import org.opcfoundation.ua.transport.security.CertificateValidator;
import org.opcfoundation.ua.transport.security.HttpsSecurityPolicy;
import org.opcfoundation.ua.transport.security.KeyPair;
import org.opcfoundation.ua.transport.security.SecurityMode;
import org.opcfoundation.ua.utils.EndpointUtil;

public class BigCertificateExample {

    //// Initial parameters ////

    // Select key size: 1024, 2048, 4096
    public static final int CLIENT_KEY_SIZE = 4096;

    // Choose protocol: https or opc.tcp
    public static final String URL_HTTPS = "https://localhost:8443/UAExample";
    public static final String URL_OPCTCP = "opc.tcp://localhost:8666/UAExample";

    public static final String URL = URL_OPCTCP;

    // Defines the client side selection of HTTPS Security Policies. The server is always initialized with HttpsSecurityPolicy.ALL
    public static final HttpsSecurityPolicy[] TLS_1_0_ONLY = new HttpsSecurityPolicy[] {
            HttpsSecurityPolicy.TLS_1_0 };
    public static final HttpsSecurityPolicy[] TLS_1_1_ONLY = new HttpsSecurityPolicy[] {
            HttpsSecurityPolicy.TLS_1_1 };
    public static final HttpsSecurityPolicy[] httpsSecurityPolicies = HttpsSecurityPolicy.ALL;

    public static void main(String[] args) throws Exception {
        // Create Logger
        Logger myLogger = LoggerFactory.getLogger(BigCertificateExample.class);

        ///// Server Application /////////////      
        Application serverApplication = new Application();
        MyServerExample2 myServer = new MyServerExample2(serverApplication);

        // Attach listener (debug logger) to each binding
        DebugLogger debugLogger = new DebugLogger(myLogger);
        for (EndpointServer b : myServer.getEndpointBindings().getEndpointServers())
            b.addConnectionListener(debugLogger);
        //////////////////////////////////////      

        //////////////  CLIENT  //////////////
        // Load Client's Application Instance Certificate from file
        KeyPair myClientOpcTcpKeyPair = ExampleKeys.getKeyPair("client", CLIENT_KEY_SIZE);
        KeyPair myClientHttpsKeyPair = ExampleKeys.getKeyPair("https_client", CLIENT_KEY_SIZE);
        // Create Client Application
        Application myClientApplication = new Application();
        myClientApplication.getHttpsSettings().setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
        myClientApplication.getHttpsSettings().setCertificateValidator(CertificateValidator.ALLOW_ALL);
        myClientApplication.getHttpsSettings().setKeyPair(myClientHttpsKeyPair);
        myClientApplication.addApplicationInstanceCertificate(myClientOpcTcpKeyPair);
        // Create Client
        Client myClient = new Client(myClientApplication);
        //////////////////////////////////////      

        // Get Endpoints like this
        SecureChannel secureChannel = myClient.createSecureChannel(URL, URL, SecurityMode.NONE, null);
        ChannelService chan = new ChannelService(secureChannel);
        EndpointDescription[] endpoints;
        try {
            GetEndpointsRequest req = new GetEndpointsRequest(null, URL, new String[0], new String[0]);
            GetEndpointsResponse res = chan.GetEndpoints(req);
            endpoints = res.getEndpoints();
        } finally {
            secureChannel.close();
            secureChannel.dispose();
        }

        SessionChannel myChannel = null;
        try {
            // Select policy according to initial parameters
            String proto = UriUtil.getTransportProtocol(URL);
            endpoints = EndpointUtil.select(endpoints, CLIENT_KEY_SIZE, CLIENT_KEY_SIZE);
            endpoints = EndpointUtil.select(endpoints, null, proto, null, null, null);
            if (proto.equals("https")) {
                endpoints = EndpointUtil.selectByMessageSecurityMode(endpoints, MessageSecurityMode.None);
                myClient.getApplicationHttpsSettings().setHttpsSecurityPolicies(httpsSecurityPolicies);
            } else
                endpoints = EndpointUtil.selectByMessageSecurityMode(endpoints, MessageSecurityMode.SignAndEncrypt);
            if (endpoints.length == 0) {
                throw new IllegalArgumentException("No suitable endpoint found from " + URL);
            }

            /////////  DISCOVER SERVERS  /////////
            // Discover server applications
            //         ApplicationDescription[] servers = myClient.discoverApplications( new URI("https://localhost:6001/") );
            //         // Choose one application
            //         ApplicationDescription server = servers[0];
            // Connect the application         
            myChannel = myClient.createSessionChannel(endpoints[0]);
            //         myChannel = myClient.createSessionChannel( server );
            // Activate session
            myChannel.activate();
            //////////////////////////////////////

            /////////////  EXECUTE  //////////////      
            CallRequest callRequest = new CallRequest();
            CallMethodRequest methodRequest = new CallMethodRequest();
            callRequest.setMethodsToCall(new CallMethodRequest[] { methodRequest });
            methodRequest.setMethodId(MyServerExample2.LIST_SOLVERS);
            CallResponse res = myChannel.Call(callRequest);
            System.out.println(res);
            //////////////////////////////////////
        }

        finally {
            /////////////  SHUTDOWN  /////////////
            // Close client's channel
            if (myChannel != null)
                myChannel.close();
            // Close the server by unbinding all endpoints 
            myServer.getApplication().close();
            //////////////////////////////////////      
        }

    }

}

class MyServerExample2 extends Server implements MethodServiceSetHandler, SessionServiceSetHandler {

    public static final NodeId LIST_SOLVERS = new NodeId(2, "ListSolvers");

    public MyServerExample2(Application application)
            throws CertificateException, IOException, UnrecoverableKeyException, NoSuchAlgorithmException,
            KeyStoreException, URISyntaxException, ServiceResultException, InvalidKeyException,
            InvalidKeySpecException, NoSuchPaddingException, InvalidAlgorithmParameterException,
            IllegalBlockSizeException, BadPaddingException, InvalidParameterSpecException {
        super(application);
        // Add method service set
        addServiceHandler(this);

        // Load keys to the server application
        KeyPair myServerOpcTcpKeyPair_1024 = ExampleKeys.getKeyPair("server", 1024);
        KeyPair myServerOpcTcpKeyPair_2048 = ExampleKeys.getKeyPair("server", 2048);
        KeyPair myServerOpcTcpKeyPair_4096 = ExampleKeys.getKeyPair("server", 4096);
        application.addApplicationInstanceCertificate(myServerOpcTcpKeyPair_1024);
        application.addApplicationInstanceCertificate(myServerOpcTcpKeyPair_2048);
        application.addApplicationInstanceCertificate(myServerOpcTcpKeyPair_4096);

        KeyPair myServerHttpsKeyPair_1024 = ExampleKeys.getKeyPair("https_server", 1024);
        KeyPair myServerHttpsKeyPair_2048 = ExampleKeys.getKeyPair("https_server", 2048);
        KeyPair myServerHttpsKeyPair_4096 = ExampleKeys.getKeyPair("https_server", 4096);
        KeyPair myServerHttpsKeyPair_8192 = ExampleKeys.getKeyPair("https_server", 8192);

        Cert[] caCerts = new Cert[0]; // No CA certificates in this example
        application.getHttpsSettings().setKeyPairs(new KeyPair[] { myServerHttpsKeyPair_1024,
                myServerHttpsKeyPair_2048, myServerHttpsKeyPair_4096, myServerHttpsKeyPair_8192, }, caCerts);

        // Add Client Application Instance Certificate validator - Accept them all (for now)
        application.getOpctcpSettings().setCertificateValidator(CertificateValidator.ALLOW_ALL);
        application.getHttpsSettings().setCertificateValidator(CertificateValidator.ALLOW_ALL);

        // The HTTPS SecurityPolicies are defined separate from the endpoint securities
        application.getHttpsSettings().setHttpsSecurityPolicies(HttpsSecurityPolicy.ALL);

        // Peer verifier
        application.getHttpsSettings().setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

        // Add User Token Policies (opc.tcp)
        addUserTokenPolicy(UserTokenPolicy.ANONYMOUS);
        addUserTokenPolicy(UserTokenPolicy.SECURE_USERNAME_PASSWORD);

        // Bind two endpoints to every network interface using all security policies
        String hostname = EndpointUtil.getHostname();
        String bindAddress, endpointAddress;
        for (String addr : EndpointUtil.getInetAddressNames()) {
            bindAddress = "https://" + addr + ":8443/UAExample";
            endpointAddress = "https://" + hostname + ":8443/UAExample";
            System.out.println(endpointAddress + " bound at " + bindAddress);
            // The HTTPS ports are using NONE OPC security 
            bind(bindAddress, endpointAddress, SecurityMode.NONE);

            bindAddress = "opc.tcp://" + addr + ":8666/UAExample";
            endpointAddress = "opc.tcp://" + hostname + ":8666/UAExample";
            System.out.println(endpointAddress + " bound at " + bindAddress);

            // ALL_102 includes BASIC256SHA256 as well
            bind(bindAddress, endpointAddress, SecurityMode.ALL_102);
        }

        //////////////////////////////////////

    }

    @Override
    public void onCall(EndpointServiceRequest<CallRequest, CallResponse> callRequest) throws ServiceFaultException {

        CallResponse response = new CallResponse();
        CallMethodRequest[] reqs = callRequest.getRequest().getMethodsToCall();
        CallMethodResult[] results = new CallMethodResult[reqs.length];
        response.setResults(results);

        // Iterate all calls
        for (int i = 0; i < reqs.length; i++) {
            CallMethodRequest req = reqs[i];
            CallMethodResult result = results[i] = new CallMethodResult();

            NodeId methodId = req.getMethodId();
            if (LIST_SOLVERS.equals(methodId)) {
                String[] solvers = { "sovler1", "solver2", "solver3" };
                Variant solversInVariant = new Variant(solvers);
                result.setOutputArguments(new Variant[] { solversInVariant });
                result.setStatusCode(StatusCode.GOOD);
            }

            else {
                // Unknown method
                result.setStatusCode(new StatusCode(StatusCodes.Bad_MethodInvalid));
            }

        }

        callRequest.sendResponse(response);

    }

    @Override
    public void onCreateSession(EndpointServiceRequest<CreateSessionRequest, CreateSessionResponse> msgExchange)
            throws ServiceFaultException {
        CreateSessionRequest req = msgExchange.getRequest();
        CreateSessionResponse res = new CreateSessionResponse();
        byte[] token = new byte[32];
        byte[] nonce = new byte[32];
        Random r = new Random();
        r.nextBytes(nonce);
        r.nextBytes(token);
        SignatureData signatureData = new SignatureData();
        //signatureData.setAlgorithm(Algorithm)
        res.setAuthenticationToken(new NodeId(0, token));
        EndpointConfiguration endpointConfiguration = EndpointConfiguration.defaults();
        res.setMaxRequestMessageSize(UnsignedInteger.valueOf(
                Math.max(endpointConfiguration.getMaxMessageSize(), req.getMaxResponseMessageSize().longValue())));
        res.setRevisedSessionTimeout(Math.max(req.getRequestedSessionTimeout(), 60 * 1000));
        res.setServerCertificate(
                getApplication().getApplicationInstanceCertificates()[0].getCertificate().encodedCertificate);
        res.setServerEndpoints(this.getEndpointDescriptions());
        res.setServerNonce(nonce);
        res.setServerSignature(signatureData);
        res.setServerSoftwareCertificates(getApplication().getSoftwareCertificates());
        res.setSessionId(new NodeId(0, "Client"));
        msgExchange.sendResponse(res);
    }

    @Override
    public void onActivateSession(
            EndpointServiceRequest<ActivateSessionRequest, ActivateSessionResponse> msgExchange)
            throws ServiceFaultException {
        ActivateSessionResponse res = new ActivateSessionResponse();
        byte[] nonce = new byte[32];
        Random r = new Random();
        r.nextBytes(nonce);
        res.setServerNonce(nonce);
        res.setResults(new StatusCode[] { StatusCode.GOOD });
        msgExchange.sendResponse(res);
    }

    @Override
    public void onCloseSession(EndpointServiceRequest<CloseSessionRequest, CloseSessionResponse> msgExchange)
            throws ServiceFaultException {
        CloseSessionResponse res = new CloseSessionResponse();
        msgExchange.sendResponse(res);
    }

    @Override
    public void onCancel(EndpointServiceRequest<CancelRequest, CancelResponse> msgExchange)
            throws ServiceFaultException {
        // TODO Auto-generated method stub

    }

}