How to connect Python COAP + DTLS client to a Eclipse Californium's CoAP Secure Server?

116 views Asked by At

I'm trying to connect a CoAP + DTLS client using Python's CoAPthon library to the CoAP Secure Server from one of the Eclipse Californium examples. Heres the server code:

    /*******************************************************************************
 * Copyright (c) 2015, 2017 Institute for Pervasive Computing, ETH Zurich and others.
 * 
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v2.0
 * and Eclipse Distribution License v1.0 which accompany this distribution.
 * 
 * The Eclipse Public License is available at
 *    http://www.eclipse.org/legal/epl-v20.html
 * and the Eclipse Distribution License is available at
 *    http://www.eclipse.org/org/documents/edl-v10.html.
 * 
 * Contributors:
 *    Matthias Kovatsch - creator and main architect
 *    Achim Kraus (Bosch Software Innovations GmbH) - use credentials util to setup
 *                                                    DtlsConnectorConfig.Builder.
 *    Bosch Software Innovations GmbH - migrate to SLF4J
 ******************************************************************************/
package org.eclipse.californium.examples;

import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.security.GeneralSecurityException;
import java.security.cert.Certificate;
import java.util.Arrays;
import java.util.List;

import org.eclipse.californium.core.CoapResource;
import org.eclipse.californium.core.CoapServer;
import org.eclipse.californium.core.coap.CoAP.ResponseCode;
import org.eclipse.californium.core.config.CoapConfig;
import org.eclipse.californium.core.network.CoapEndpoint;
import org.eclipse.californium.core.network.Endpoint;
import org.eclipse.californium.core.network.interceptors.MessageTracer;
import org.eclipse.californium.core.server.resources.CoapExchange;
import org.eclipse.californium.elements.config.Configuration;
import org.eclipse.californium.elements.config.Configuration.DefinitionsProvider;
import org.eclipse.californium.elements.util.SslContextUtil;
import org.eclipse.californium.examples.CredentialsUtil.Mode;
import org.eclipse.californium.scandium.DTLSConnector;
import org.eclipse.californium.scandium.MdcConnectionListener;
import org.eclipse.californium.scandium.config.DtlsConfig;
import org.eclipse.californium.scandium.config.DtlsConnectorConfig;
import org.eclipse.californium.scandium.config.DtlsConfig.DtlsRole;
import org.eclipse.californium.scandium.dtls.CertificateType;
import org.eclipse.californium.scandium.dtls.cipher.CipherSuite;
import org.eclipse.californium.scandium.dtls.x509.SingleCertificateProvider;
import org.eclipse.californium.scandium.dtls.x509.StaticNewAdvancedCertificateVerifier;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SecureServer2 {
    private static final char[] KEY_STORE_PASSWORD = "endPass".toCharArray();
    private static final String KEY_STORE_LOCATION = "certs/keyStore.jks";
    private static final char[] TRUST_STORE_PASSWORD = "rootPass".toCharArray();
    private static final String TRUST_STORE_LOCATION = "certs/trustStore.jks";
    private static final File CONFIG_FILE = new File("Californium3SecureServer.properties");
    private static final String CONFIG_HEADER = "Californium CoAP Properties file for Secure Server";
    private static final int DEFAULT_PORT = 5684;
    private static final Logger LOG = LoggerFactory
            .getLogger(SecureServer2.class.getName());
    static {
        CoapConfig.register();
        DtlsConfig.register();
    }

    private static DefinitionsProvider DEFAULTS = new DefinitionsProvider() {

        @Override
        public void applyDefinitions(Configuration config) {
            config.set(DtlsConfig.DTLS_ROLE, DtlsRole.SERVER_ONLY);
            config.set(DtlsConfig.DTLS_RECOMMENDED_CIPHER_SUITES_ONLY, false);
            config.set(DtlsConfig.DTLS_PRESELECTED_CIPHER_SUITES, CipherSuite.STRONG_ENCRYPTION_PREFERENCE);
        }
    };

    public static final List<Mode> SUPPORTED_MODES = Arrays.asList(Mode.PSK, Mode.ECDHE_PSK, Mode.RPK, Mode.X509,
            Mode.WANT_AUTH, Mode.NO_AUTH);

    public static void main(String[] args) throws IOException, GeneralSecurityException {

        System.out.println("Usage: java -jar ... [PSK] [ECDHE_PSK] [RPK] [X509] [WANT_AUTH|NO_AUTH]");
        System.out.println("Default :            [PSK] [ECDHE_PSK] [RPK] [X509]");

        Configuration configuration = Configuration.createWithFile(CONFIG_FILE, CONFIG_HEADER, DEFAULTS);
        Configuration.setStandard(configuration);
        int dtlsPort = configuration.get(CoapConfig.COAP_SECURE_PORT);

        CoapServer server = new CoapServer();
        server.add(new CoapResource("secure") {

            @Override
            public void handleGET(CoapExchange exchange) {
                exchange.respond(ResponseCode.CONTENT, "hello security23");
            }
        });
    
            // load the key store
            SslContextUtil.Credentials serverCredentials = SslContextUtil.loadCredentials(
                    SslContextUtil.CLASSPATH_SCHEME + KEY_STORE_LOCATION, "server", KEY_STORE_PASSWORD,
                    KEY_STORE_PASSWORD);
            
            Certificate[] trustedCertificates = SslContextUtil.loadTrustedCertificates(
                    SslContextUtil.CLASSPATH_SCHEME + TRUST_STORE_LOCATION, "root", TRUST_STORE_PASSWORD);

            DtlsConnectorConfig.Builder builder = DtlsConnectorConfig.builder(configuration)
                    .setAddress(new InetSocketAddress("127.0.0.1",dtlsPort))
                    .setCertificateIdentityProvider(
                            new SingleCertificateProvider(serverCredentials.getPrivateKey(), serverCredentials.getCertificateChain(), CertificateType.RAW_PUBLIC_KEY, CertificateType.X_509))
                    .setAdvancedCertificateVerifier(StaticNewAdvancedCertificateVerifier.builder()
                            .setTrustedCertificates(trustedCertificates).setTrustAllRPKs().build());

            

    
        DTLSConnector connector = new DTLSConnector(builder.build());
        CoapEndpoint.Builder coapBuilder = new CoapEndpoint.Builder()
                .setConfiguration(configuration)
                .setConnector(connector);
        
        server.addEndpoint(coapBuilder.build());
        server.start();

        // add special interceptor for message traces
        for (Endpoint ep : server.getEndpoints()) {
            ep.addInterceptor(new MessageTracer());
        }

        System.out.println("Secure CoAP server powered by Scandium (Sc) is listening on port " + dtlsPort);
    }

}

Here's the correspondent Client on java that is able to connect to this server:

/*******************************************************************************
 * Copyright (c) 2015, 2017 Institute for Pervasive Computing, ETH Zurich and others.
 * 
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v2.0
 * and Eclipse Distribution License v1.0 which accompany this distribution.
 * 
 * The Eclipse Public License is available at
 *    http://www.eclipse.org/legal/epl-v20.html
 * and the Eclipse Distribution License is available at
 *    http://www.eclipse.org/org/documents/edl-v10.html.
 * 
 * Contributors:
 *    Matthias Kovatsch - creator and main architect
 *    Achim Kraus (Bosch Software Innovations GmbH) - use credentials util to setup
 *                                                    DtlsConnectorConfig.Builder.
 *    Bosch Software Innovations GmbH - migrate to SLF4J
 ******************************************************************************/
package org.eclipse.californium.examples;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.security.Principal;
import java.util.Arrays;
import java.util.List;

import org.eclipse.californium.core.CoapClient;
import org.eclipse.californium.core.CoapResponse;
import org.eclipse.californium.core.Utils;
import org.eclipse.californium.core.config.CoapConfig;
import org.eclipse.californium.core.network.CoapEndpoint;
import org.eclipse.californium.elements.DtlsEndpointContext;
import org.eclipse.californium.elements.EndpointContext;
import org.eclipse.californium.elements.config.Configuration;
import org.eclipse.californium.elements.config.Configuration.DefinitionsProvider;
import org.eclipse.californium.elements.exception.ConnectorException;
import org.eclipse.californium.examples.CredentialsUtil.Mode;
import org.eclipse.californium.scandium.DTLSConnector;
import org.eclipse.californium.scandium.config.DtlsConfig;
import org.eclipse.californium.scandium.config.DtlsConnectorConfig;
import org.eclipse.californium.scandium.config.DtlsConfig.DtlsRole;
import org.eclipse.californium.scandium.dtls.cipher.CipherSuite;
import org.eclipse.californium.scandium.dtls.pskstore.AdvancedSinglePskStore;

public class SecureClient2 {
    private static final File CONFIG_FILE = new File("Californium3SecureClient.properties");
    private static final String CONFIG_HEADER = "Californium CoAP Properties file for Secure Client";

    static {
        CoapConfig.register();
        DtlsConfig.register();
    }

    private static DefinitionsProvider DEFAULTS = new DefinitionsProvider() {

        @Override
        public void applyDefinitions(Configuration config) {
            config.set(CoapConfig.MAX_ACTIVE_PEERS, 10);
            config.set(DtlsConfig.DTLS_ROLE, DtlsRole.CLIENT_ONLY);
            config.set(DtlsConfig.DTLS_USE_SERVER_NAME_INDICATION, false);
            config.set(DtlsConfig.DTLS_RECOMMENDED_CIPHER_SUITES_ONLY, false);
            config.set(DtlsConfig.DTLS_PRESELECTED_CIPHER_SUITES, CipherSuite.STRONG_ENCRYPTION_PREFERENCE);
            config.setTransient(DtlsConfig.DTLS_CIPHER_SUITES);
        }
    };

    public static final List<Mode> SUPPORTED_MODES = Arrays.asList(Mode.PSK, Mode.ECDHE_PSK, Mode.RPK, Mode.X509,
            Mode.RPK_TRUST, Mode.X509_TRUST);
    private static final String SERVER_URI = "coaps://192.168.1.14:5684/secure";

    private final DTLSConnector dtlsConnector;
    private final Configuration configuration;

    public SecureClient2(DTLSConnector dtlsConnector, Configuration configuration) {
        this.dtlsConnector = dtlsConnector;
        this.configuration = configuration;
    }

    public void test() {
        CoapResponse response = null;
        try {
            URI uri = new URI(SERVER_URI);
            CoapClient client = new CoapClient(uri);
            CoapEndpoint.Builder builder = new CoapEndpoint.Builder()
                    .setConfiguration(configuration)
                    .setConnector(dtlsConnector);

            client.setEndpoint(builder.build());
            response = client.get();
            client.shutdown();
        } catch (URISyntaxException e) {
            System.err.println("Invalid URI: " + e.getMessage());
            System.exit(-1);
        } catch (ConnectorException | IOException e) {
            System.err.println("Error occurred while sending request: " + e);
            System.exit(-1);
        }

        if (response != null) {

            System.out.println(response.getCode() + " - " + response.getCode().name());
            System.out.println(response.getOptions());
            System.out.println(response.getResponseText());
            System.out.println();
            System.out.println("ADVANCED:");
            EndpointContext context = response.advanced().getSourceContext();
            Principal identity = context.getPeerIdentity();
            if (identity != null) { 
                System.out.println(context.getPeerIdentity());
            } else {
                System.out.println("anonymous");
            }
            System.out.println("CIPHER - " + context.get(DtlsEndpointContext.KEY_CIPHER));
            System.out.println(Utils.prettyPrint(response));
        } else {
            System.out.println("No response received.");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        System.out.println("Usage: java -cp ... org.eclipse.californium.examples.SecureClient [PSK|ECDHE_PSK] [RPK|RPK_TRUST] [X509|X509_TRUST]");
        System.out.println("Default:            [PSK] [RPK] [X509]");

        Configuration configuration = Configuration.createWithFile(CONFIG_FILE, CONFIG_HEADER, DEFAULTS);
        Configuration.setStandard(configuration);

        DtlsConnectorConfig.Builder builder = DtlsConnectorConfig.builder(configuration);
        CredentialsUtil.setupCid(args, builder);
        List<Mode> modes = CredentialsUtil.parse(args, CredentialsUtil.DEFAULT_CLIENT_MODES, SUPPORTED_MODES);
//      if (modes.contains(CredentialsUtil.Mode.PSK) || modes.contains(CredentialsUtil.Mode.ECDHE_PSK)) {
//          builder.setAdvancedPskStore(new AdvancedSinglePskStore(CredentialsUtil.OPEN_PSK_IDENTITY, CredentialsUtil.OPEN_PSK_SECRET));
//      }
        System.out.println("pass- " +  CredentialsUtil.OPEN_PSK_IDENTITY + " - " + new String(CredentialsUtil.OPEN_PSK_SECRET, StandardCharsets.UTF_8));

        CredentialsUtil.setupCredentials(builder, CredentialsUtil.CLIENT_NAME, modes);
        // uncomment next line to load pem file for the example
        // CredentialsUtil.loadCredentials(builder, "client.pem");
        DTLSConnector dtlsConnector = new DTLSConnector(builder.build());

        SecureClient2 client = new SecureClient2(dtlsConnector, configuration);
        client.test();
    }
}

Now I'm trying to connect to the server using this Python code that is based on CoAPton's test_secure.py, more specifically the test_ok_with_handshake_on_connect() function:

#setup a client side DTLS socket
_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
_sock.setsockopt(socket.SOL SOCKET, socket.so REUSEADDR, 1)
_sock.wrap_client( sock,cert_reqs=ssl.CERT_REQUIRED, ca_certs="./certificate.pem",do_handshake_on_connect=True,ciphers="SHA256")
client = HelperCIient(server=(host, port), sock=_sock)
request = Request()
request.destination = (host, port)
request.code = defines. Codes.GET.number
request.uri path = path
response = client. request)
response = client.get(path)
print(response.pretty_print())
client.stop()

I generated the .pem file used on the python script from a keystone file provided on the Eclipse Californium repository (demo_certs)

I'm rather new to this, I only need the python client and the eclipse server to share a certificate so that the connection is secure. When I run the Python code I get this info on the server side (13:11:51.704 INFO [] [ServerHandshaker]: Start certificate identity.) but nothing else. Can you help me? Thanks in advance.

0

There are 0 answers