Skip to content

Commit

Permalink
restructuring code for main and option parsing.
Browse files Browse the repository at this point in the history
  • Loading branch information
EskoDijk committed Jun 26, 2024
1 parent 96562f9 commit 466194c
Show file tree
Hide file tree
Showing 9 changed files with 183 additions and 147 deletions.
Binary file added credentials/default.p12
Binary file not shown.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<jackson.version>2.9.7</jackson.version>
<logback.version>1.2.3</logback.version>
<logback.version>1.2.13</logback.version>
<junit.version>4.13.2</junit.version>
</properties>

Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/google/openthread/LoggerInitializer.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public static void Init(boolean verbose) {
((Logger) LoggerFactory.getLogger(CALIFORNIUM)).setLevel(Level.DEBUG);
Configurator.setLevel(OPENTHREAD, org.apache.logging.log4j.Level.DEBUG);
} else {
((Logger) LoggerFactory.getLogger(CALIFORNIUM)).setLevel(Level.INFO);
((Logger) LoggerFactory.getLogger(CALIFORNIUM)).setLevel(Level.WARN);
Configurator.setLevel(OPENTHREAD, org.apache.logging.log4j.Level.INFO);
}
}
Expand Down
63 changes: 63 additions & 0 deletions src/main/java/com/google/openthread/main/OtRegistrarConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright (c) 2024, The OpenThread Registrar Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

package com.google.openthread.main;

public class OtRegistrarConfig {

public Role role;
public int serverPortCoaps;
public String domainName;
public String keyStoreFile;
public String masaUri;
public String registrarUri;
public boolean logVerbose;

static OtRegistrarConfig Default() {
OtRegistrarConfig config = new OtRegistrarConfig();
config.role = Role.None;
config.serverPortCoaps = 5684;
config.domainName = "DefaultDomain";
config.keyStoreFile = "./credentials/default.p12";
config.masaUri = null;
config.registrarUri = "localhost:5684";
config.logVerbose = false;
return config;
}

public String ToString() {
return
"Role : " + role.toString() + "\n" +
"Server port (CoapS) : " + this.serverPortCoaps + "\n" +
"Domain Name : " + this.domainName + "\n" +
"Keystore file : " + this.keyStoreFile + "\n" +
"MASA URI : " + (this.masaUri == null ? "(read from IDevID cert)" : this.masaUri + " (forced)") + "\n" +
"Registrar URI : " + this.registrarUri + "\n" +
"Log verbose : " + (this.logVerbose ? "yes" : "no" ) + "\n";
}
}
74 changes: 47 additions & 27 deletions src/main/java/com/google/openthread/main/OtRegistrarMain.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,9 @@

package com.google.openthread.main;

import com.google.openthread.Credentials;
import com.google.openthread.LoggerInitializer;
import com.google.openthread.domainca.DomainCA;
import com.google.openthread.registrar.Registrar;
import com.google.openthread.registrar.RegistrarBuilder;
import com.google.openthread.registrar.RegistrarMain;
import com.google.openthread.tools.CredentialGenerator;
import java.security.KeyStoreException;
import com.google.openthread.pledge.PledgeMain;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser;
Expand All @@ -45,6 +40,9 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Main entry point of the OT Registrar JAR. Based on arguments, it will decide what entity to start: a Registrar, a MASA or a Pledge.
*/
public final class OtRegistrarMain {

private static Logger logger = LoggerFactory.getLogger(OtRegistrarMain.class);
Expand Down Expand Up @@ -109,6 +107,14 @@ public static void main(String args[]) {
.desc("force the given MASA URI instead of the default one")
.build();

Option optRegistrarUri =
Option.builder("r")
.longOpt("registrar")
.hasArg()
.argName("registrar-uri")
.desc("for a Pledge, the Registrar to connect to")
.build();

Option helpOpt =
Option.builder("h").longOpt("help").hasArg(false).desc("print this message").build();

Expand All @@ -121,45 +127,45 @@ public static void main(String args[]) {
.addOption(optPort)
.addOption(optVerbose)
.addOption(optForceMasaUri)
.addOption(optRegistrarUri)
.addOption(helpOpt);

OtRegistrarConfig config = OtRegistrarConfig.Default();

try {
String forcedMasaUri = null;
CommandLineParser parser = new DefaultParser();
CommandLine cmd = parser.parse(options, args);

LoggerInitializer.Init(cmd.hasOption('v'));

if (cmd.hasOption('h')) {
helper.printHelp(HELP_FORMAT, options);
return;
}

String keyStoreFile = cmd.getOptionValue('f');
if (keyStoreFile == null) {
keyStoreFile = "credentials/default.p12";
}
config.logVerbose = cmd.hasOption("v");
LoggerInitializer.Init(config.logVerbose);

String port = cmd.getOptionValue('p');
if (port == null) {
port = "5683";
if (cmd.hasOption('f')) {
config.keyStoreFile = cmd.getOptionValue('f');
}

String domainName = cmd.getOptionValue('d');
if (domainName == null) {
domainName = "DefaultDomain";
if (cmd.hasOption('p')) {
config.serverPortCoaps = Integer.parseInt(cmd.getOptionValue('p'));
}
if (cmd.hasOption('d')) {
config.domainName = cmd.getOptionValue('d');
}

if (cmd.hasOption('m')) {
forcedMasaUri = cmd.getOptionValue('m');
config.masaUri = cmd.getOptionValue('m');
}

logger.info("using keystore: {}", keyStoreFile);

if (cmd.hasOption("registrar")) {
RegistrarMain.main(keyStoreFile, Integer.parseInt(port), domainName, forcedMasaUri);
}else{
throw new Exception("not yet impl");
config.role = Role.Registrar;
} else if (cmd.hasOption("masa")) {
config.role = Role.Masa;
} else if (cmd.hasOption("pledge")) {
config.role = Role.Pledge;
} else {
helper.printHelp(HELP_FORMAT, options);
return;
}

} catch (Exception e) {
Expand All @@ -168,5 +174,19 @@ public static void main(String args[]) {
return;
}

logger.info("Configuration:\n{}", config.ToString());

switch (config.role) {
case Registrar:
RegistrarMain.main(config);
break;
case Masa:
break;
case Pledge:
PledgeMain.main(config);
break;
case None:
break;
}
}
}
5 changes: 5 additions & 0 deletions src/main/java/com/google/openthread/main/Role.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.google.openthread.main;

public enum Role {
None, Registrar, Masa, Pledge
}
74 changes: 36 additions & 38 deletions src/main/java/com/google/openthread/pledge/Pledge.java
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,7 @@
import org.slf4j.LoggerFactory;

/**
* The Pledge (i.e., CCM Joiner) is the new device which is to securely bootstrap into the network
* domain using the Constrained BRSKI protocol.
* The Pledge (i.e., CCM Joiner) is the new device which is to securely bootstrap into the network domain using the Constrained BRSKI protocol.
*/
public class Pledge extends CoapClient {

Expand All @@ -119,10 +118,9 @@ public enum CertState {
/**
* Constructing pledge with credentials and uri of the registrar
*
* @param privateKey the manufacturer private key
* @param certificateChain the manufacturer certificate chain leading to the masa and including
* masa certificate
* @param hostURI uri of host (registrar)
* @param privateKey the manufacturer private key
* @param certificateChain the manufacturer certificate chain leading to the masa and including masa certificate
* @param hostURI uri of host (registrar)
* @throws PledgeException
*/
public Pledge(Credentials creds, String hostURI) throws PledgeException {
Expand Down Expand Up @@ -165,16 +163,19 @@ public X509Certificate getOperationalCert() {
/**
* Get the Thread Domain Name as encoded in the operational certificate of the Pledge.
*
* @return the Thread Domain Name, encoded in the SubjectAltName/Othername field as per Thread
* spec. Or "DefaultDomain" if not encoded in there. Null if no operational cert present or if
* it couldn't be parsed.
* @return the Thread Domain Name, encoded in the SubjectAltName/Othername field as per Thread spec. Or "DefaultDomain" if not encoded in there. Null if no operational cert present or if it couldn't
* be parsed.
*/
public String getDomainName() {
if (operationalCertificate == null) return null;
if (operationalCertificate == null) {
return null;
}

try {
Collection<List<?>> cSubjAltNames = operationalCertificate.getSubjectAlternativeNames();
if (cSubjAltNames == null) return Constants.THREAD_DOMAIN_NAME_DEFAULT;
if (cSubjAltNames == null) {
return Constants.THREAD_DOMAIN_NAME_DEFAULT;
}
// loop all subject-alt-names to find a matching 'otherName' item.
for (List<?> l : cSubjAltNames) {
if (l.size() == 2 && l.get(0).equals(Constants.ASN1_TAG_GENERALNAME_OTHERNAME)) {
Expand All @@ -184,8 +185,9 @@ public String getDomainName() {
ASN1TaggedObject ato = ASN1TaggedObject.getInstance(ds.getObjectAt(1));
if (ato.getTagNo() == 0) {
// get to the deepest embedded tagged object.
while (ato.getObject() instanceof ASN1TaggedObject)
while (ato.getObject() instanceof ASN1TaggedObject) {
ato = (ASN1TaggedObject) ato.getObject();
}
// must be stored as IA5String
return DERIA5String.getInstance(ato.getObject()).toString();
}
Expand Down Expand Up @@ -288,9 +290,9 @@ public Voucher requestVoucher(VoucherRequest req)

if (!voucher.serialNumber.equals(req.serialNumber)
|| (voucher.idevidIssuer != null
&& !Arrays.equals(
voucher.idevidIssuer,
SecurityUtils.getAuthorityKeyIdentifier(getIdevidCertificate())))) {
&& !Arrays.equals(
voucher.idevidIssuer,
SecurityUtils.getAuthorityKeyIdentifier(getIdevidCertificate())))) {
throw new PledgeException("serial number or idevid-issuer not matched");
}
if (req.nonce != null
Expand Down Expand Up @@ -339,10 +341,8 @@ public void requestCACertificate() {
/**
* Send Voucher Status telemetry message
*
* @param isSuccess true if success voucher-status is to be reported, false if error is to be
* reported.
* @param failureReason human-readable failure reason string to be reported, usually only if
* isSuccess==false.
* @param isSuccess true if success voucher-status is to be reported, false if error is to be reported.
* @param failureReason human-readable failure reason string to be reported, usually only if isSuccess==false.
* @throws Exception
*/
public ResponseCode sendVoucherStatusTelemetry(boolean isSuccess, String failureReason)
Expand All @@ -357,10 +357,8 @@ public ResponseCode sendVoucherStatusTelemetry(boolean isSuccess, String failure
/**
* Send Enroll Status telemetry message
*
* @param isSuccess true if success enroll-status is to be reported, false if error is to be
* reported.
* @param failureReason human-readable failure reason string to be reported, usually only if
* isSuccess==false.
* @param isSuccess true if success enroll-status is to be reported, false if error is to be reported.
* @param failureReason human-readable failure reason string to be reported, usually only if isSuccess==false.
* @throws Exception
*/
public ResponseCode sendEnrollStatusTelemetry(boolean isSuccess, String failureReason)
Expand Down Expand Up @@ -497,8 +495,7 @@ public X509Certificate getMASACaCertificate() {
}

/**
* Set the checking of the CMC-RA (Registration Authority) flag in the Registrar's certificate to
* on (true) or off (false).
* Set the checking of the CMC-RA (Registration Authority) flag in the Registrar's certificate to on (true) or off (false).
*
* @param doCheckCmcRa
*/
Expand All @@ -507,11 +504,9 @@ public void setCmcRaCheck(boolean doCheckCmcRa) {
}

/**
* Set the use of 'lightweight' client certificates in the DTLS handshake for this Pledge. If
* 'lightweight', then the MASA CA root certificate will be omitted from the client's Certificate
* message in the DTLS handshake to reduce network load. The Registrar will anyhow have means to
* obtain MASA CA certificates (e.g. by contacting the MASA via the MASA URI, or a sales
* integration process, etc.
* Set the use of 'lightweight' client certificates in the DTLS handshake for this Pledge. If 'lightweight', then the MASA CA root certificate will be omitted from the client's Certificate message
* in the DTLS handshake to reduce network load. The Registrar will anyhow have means to obtain MASA CA certificates (e.g. by contacting the MASA via the MASA URI, or a sales integration process,
* etc.
*
* @param isSetLightweight whether to use 'lightweight' (true) client certificates or not (false)
* @throws PledgeException in case reconfiguration of the Pledge failed for some reason
Expand Down Expand Up @@ -551,7 +546,9 @@ private void init(Credentials creds, String hostURI, boolean isLightweightClient

// remove trailing slash from hostURI - avoid host//path situations leading to a leading, empty
// CoAP Uri-Path Option. (=bug)
while (hostURI.endsWith("/")) hostURI = hostURI.substring(0, hostURI.length() - 1);
while (hostURI.endsWith("/")) {
hostURI = hostURI.substring(0, hostURI.length() - 1);
}
this.hostURI = hostURI;

try {
Expand All @@ -578,8 +575,9 @@ private void init(Credentials creds, String hostURI, boolean isLightweightClient
certState = CertState.NO_CONTACT;

X509Certificate[] clientCertChain = this.certificateChain;
if (isLightweightClientCerts)
clientCertChain = new X509Certificate[] {this.certificateChain[0]};
if (isLightweightClientCerts) {
clientCertChain = new X509Certificate[]{this.certificateChain[0]};
}
initEndpoint(this.privateKey, clientCertChain, this.certVerifier);
}

Expand All @@ -589,9 +587,7 @@ private CoapResponse sendRequestVoucher(VoucherRequest voucherRequest)
byte[] vrEncoded = new CBORSerializer().serialize(voucherRequest);

// COSE_Sign1 signing of the CBOR
byte[] payload =
SecurityUtils.genCoseSign1Message(
privateKey, SecurityUtils.COSE_SIGNATURE_ALGORITHM, vrEncoded);
byte[] payload = SecurityUtils.genCoseSign1Message(privateKey, SecurityUtils.COSE_SIGNATURE_ALGORITHM, vrEncoded);
// store the transmitted PVR
this.lastPvr = voucherRequest;
this.lastPvrCoseSigned = payload;
Expand Down Expand Up @@ -664,7 +660,7 @@ private void initEndpoint(
PrivateKey privateKey, X509Certificate[] certificateChain, CertificateVerifier verifier) {
CoapEndpoint endpoint =
SecurityUtils.genCoapClientEndPoint(
new X509Certificate[] {}, privateKey, certificateChain, verifier, false);
new X509Certificate[]{}, privateKey, certificateChain, verifier, false);
setEndpoint(endpoint);
}

Expand Down Expand Up @@ -722,7 +718,9 @@ private String getBRSKIPath() {

private CertPath registrarCertPath;

/** the Content Format to use for a CSR request */
/**
* the Content Format to use for a CSR request
*/
public int csrContentFormat = ExtendedMediaTypeRegistry.APPLICATION_PKCS10;

private PublicKey domainPublicKey;
Expand Down
Loading

0 comments on commit 466194c

Please sign in to comment.