Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
#162:Remove DTLSConnection when corresponding SecurityInfo is removed
Browse files Browse the repository at this point in the history
sbernard31 committed Mar 12, 2020

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
1 parent 36938b0 commit d726574
Showing 6 changed files with 156 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*******************************************************************************
* Copyright (c) 2020 Sierra Wireless and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.html.
*
* Contributors:
* Sierra Wireless - initial API and implementation
*******************************************************************************/
package org.eclipse.leshan.server.californium;

import java.security.Principal;
import java.security.PublicKey;

import javax.security.auth.x500.X500Principal;

import org.eclipse.californium.elements.auth.PreSharedKeyIdentity;
import org.eclipse.californium.elements.auth.RawPublicKeyIdentity;
import org.eclipse.californium.elements.auth.X509CertPath;
import org.eclipse.californium.elements.util.LeastRecentlyUsedCache.Predicate;
import org.eclipse.californium.scandium.DTLSConnector;
import org.eclipse.leshan.core.californium.EndpointContextUtil;
import org.eclipse.leshan.server.security.SecurityInfo;

/**
* This class is responsible to remove DTLS connection for a given SecurityInfo.
*/
public class ConnectionCleaner {

private DTLSConnector connector;

public ConnectionCleaner(DTLSConnector connector) {
this.connector = connector;
}

public void cleanConnectionFor(final SecurityInfo... infos) {
connector.startTerminateConnectionsForPrincipal(new Predicate<Principal>() {
@Override
public boolean accept(Principal principal) {
if (principal != null) {
for (SecurityInfo info : infos) {
if (info != null) {
// PSK
if (info.usePSK() && principal instanceof PreSharedKeyIdentity) {
String identity = ((PreSharedKeyIdentity) principal).getIdentity();
if (info.getIdentity().equals(identity)) {
return true;
}
}
// RPK
else if (info.useRPK() && principal instanceof RawPublicKeyIdentity) {
PublicKey publicKey = ((RawPublicKeyIdentity) principal).getKey();
if (info.getRawPublicKey().equals(publicKey)) {
return true;
}
}
// x509
else if (info.useX509Cert() && principal instanceof X500Principal
|| principal instanceof X509CertPath) {
// Extract common name
String x509CommonName = EndpointContextUtil.extractCN(principal.getName());
if (x509CommonName.equals(info.getEndpoint())) {
return true;
}
}
}
}
}
return false;
}
});
}
}
Original file line number Diff line number Diff line change
@@ -27,6 +27,7 @@
import org.eclipse.californium.core.network.Endpoint;
import org.eclipse.californium.core.network.config.NetworkConfig;
import org.eclipse.californium.core.server.resources.Resource;
import org.eclipse.californium.scandium.DTLSConnector;
import org.eclipse.leshan.core.californium.CoapResponseCallback;
import org.eclipse.leshan.core.node.codec.CodecException;
import org.eclipse.leshan.core.node.codec.LwM2mNodeDecoder;
@@ -68,8 +69,10 @@
import org.eclipse.leshan.server.registration.RegistrationUpdate;
import org.eclipse.leshan.server.request.LwM2mRequestSender;
import org.eclipse.leshan.server.security.Authorizer;
import org.eclipse.leshan.server.security.EditableSecurityStore;
import org.eclipse.leshan.server.security.SecurityInfo;
import org.eclipse.leshan.server.security.SecurityStore;
import org.eclipse.leshan.server.security.SecurityStoreListener;
import org.eclipse.leshan.util.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -175,6 +178,9 @@ public LeshanServer(CoapEndpoint unsecuredEndpoint, CoapEndpoint securedEndpoint
requestSender = createRequestSender(securedEndpoint, unsecuredEndpoint, registrationService, observationService,
this.modelProvider, encoder, decoder, presenceService);

// connection cleaner
createConnectionCleaner(securityStore, securedEndpoint);

coapApi = new CoapAPI();
}

@@ -262,6 +268,22 @@ public void registered(Registration registration, Registration previousReg,
return requestSender;
}

protected void createConnectionCleaner(SecurityStore securityStore, CoapEndpoint securedEndpoint) {
if (securedEndpoint != null && securedEndpoint.getConnector() instanceof DTLSConnector
&& securityStore instanceof EditableSecurityStore) {

final ConnectionCleaner connectionCleaner = new ConnectionCleaner(
(DTLSConnector) securedEndpoint.getConnector());

((EditableSecurityStore) securityStore).setListener(new SecurityStoreListener() {
@Override
public void securityInfoRemoved(SecurityInfo... infos) {
connectionCleaner.cleanConnectionFor(infos);
}
});
}
}

/**
* Starts the server and binds it to the specified port.
*/
Original file line number Diff line number Diff line change
@@ -44,4 +44,11 @@ public interface EditableSecurityStore extends SecurityStore {
* @return the removed {@link SecurityInfo} or <code>null</code> if no info for the end-point.
*/
SecurityInfo remove(String endpoint);

/**
* Set a Listener for this store.
*
* @param listener the security store listener
*/
void setListener(SecurityStoreListener listener);
}
Original file line number Diff line number Diff line change
@@ -40,6 +40,8 @@ public class InMemorySecurityStore implements EditableSecurityStore {
// by PSK identity
protected Map<String, SecurityInfo> securityByIdentity = new HashMap<>();

private SecurityStoreListener listener;

public InMemorySecurityStore() {
}

@@ -115,10 +117,18 @@ public SecurityInfo remove(String endpoint) {
securityByIdentity.remove(info.getIdentity());
}
securityByEp.remove(endpoint);
if (listener != null) {
listener.securityInfoRemoved(info);
}
}
return info;
} finally {
writeLock.unlock();
}
}

@Override
public void setListener(SecurityStoreListener listener) {
this.listener = listener;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*******************************************************************************
* Copyright (c) 2020 Sierra Wireless and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.html.
*
* Contributors:
* Sierra Wireless - initial API and implementation
*******************************************************************************/
package org.eclipse.leshan.server.security;

/**
* A Listener for {@link SecurityStore}
*/
public interface SecurityStoreListener {
/**
* Called when {@link SecurityInfo} are removed.
*
* @param infos Array of removed {@link SecurityInfo}
*/
void securityInfoRemoved(SecurityInfo... infos);
}
Original file line number Diff line number Diff line change
@@ -23,6 +23,7 @@
import org.eclipse.leshan.server.security.NonUniqueSecurityInfoException;
import org.eclipse.leshan.server.security.SecurityInfo;
import org.eclipse.leshan.server.security.SecurityStore;
import org.eclipse.leshan.server.security.SecurityStoreListener;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.ScanParams;
@@ -41,6 +42,7 @@ public class RedisSecurityStore implements EditableSecurityStore {
private static final String PSKID_SEC = "PSKID#SEC";

private final Pool<Jedis> pool;
private SecurityStoreListener listener;

public RedisSecurityStore(Pool<Jedis> pool) {
this.pool = pool;
@@ -128,6 +130,9 @@ public SecurityInfo remove(String endpoint) {
j.hdel(PSKID_SEC.getBytes(), info.getIdentity().getBytes());
}
j.del((SEC_EP + endpoint).getBytes());
if (listener != null) {
listener.securityInfoRemoved(info);
}
return info;
}
}
@@ -141,4 +146,9 @@ private byte[] serialize(SecurityInfo secInfo) {
private SecurityInfo deserialize(byte[] data) {
return SecurityInfoSerDes.deserialize(data);
}

@Override
public void setListener(SecurityStoreListener listener) {
this.listener = listener;
}
}

0 comments on commit d726574

Please sign in to comment.