diff --git a/.github/actions/install-rti/install.sh b/.github/actions/install-rti/install.sh index 6b522c3453..05ef9474b7 100755 --- a/.github/actions/install-rti/install.sh +++ b/.github/actions/install-rti/install.sh @@ -2,6 +2,9 @@ cd org.lflang/src/lib/c/reactor-c/core/federated/RTI mkdir build cd build -cmake ../ +if [[ "$OSTYPE" == "darwin"* ]]; then + export OPENSSL_ROOT_DIR="/usr/local/opt/openssl" +fi +cmake -DAUTH=ON ../ make sudo make install diff --git a/.github/workflows/c-tests.yml b/.github/workflows/c-tests.yml index b4485fe459..60bcf18b90 100644 --- a/.github/workflows/c-tests.yml +++ b/.github/workflows/c-tests.yml @@ -43,6 +43,8 @@ jobs: - name: Install dependencies OS X run: | brew install coreutils + brew install openssl + brew link openssl --force if: ${{ runner.os == 'macOS' }} - name: Install RTI uses: ./.github/actions/install-rti diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 094cb0f1db..b173542739 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -60,12 +60,12 @@ jobs: # Run the C integration tests. c-tests: - uses: lf-lang/lingua-franca/.github/workflows/c-tests.yml@master + uses: lf-lang/lingua-franca/.github/workflows/c-tests.yml@auth needs: cancel # Run the CCpp integration tests. ccpp-tests: - uses: lf-lang/lingua-franca/.github/workflows/c-tests.yml@master + uses: lf-lang/lingua-franca/.github/workflows/c-tests.yml@auth with: use-cpp: true needs: cancel diff --git a/org.lflang/src/lib/c/reactor-c b/org.lflang/src/lib/c/reactor-c index 5b772a5322..0cfbcd7e77 160000 --- a/org.lflang/src/lib/c/reactor-c +++ b/org.lflang/src/lib/c/reactor-c @@ -1 +1 @@ -Subproject commit 5b772a5322b46b0738fcbd31e33f1175fde3c236 +Subproject commit 0cfbcd7e7716116ff5bdf2daaafa6a4d504130df diff --git a/org.lflang/src/org/lflang/TargetConfig.java b/org.lflang/src/org/lflang/TargetConfig.java index 7409cd4b27..b16dfadd19 100644 --- a/org.lflang/src/org/lflang/TargetConfig.java +++ b/org.lflang/src/org/lflang/TargetConfig.java @@ -227,6 +227,11 @@ public class TargetConfig { */ public int workers = 0; + /** + * Indicate whether HMAC authentication is used. + */ + public boolean auth = false; + /** * Indicate whether the runtime should use multithreaded execution. */ diff --git a/org.lflang/src/org/lflang/TargetProperty.java b/org.lflang/src/org/lflang/TargetProperty.java index 71f6060c19..6b8977d11d 100644 --- a/org.lflang/src/org/lflang/TargetProperty.java +++ b/org.lflang/src/org/lflang/TargetProperty.java @@ -58,7 +58,13 @@ * @author{Marten Lohstroh } */ public enum TargetProperty { - + /** + * Directive to allow including OpenSSL libraries and process HMAC authentication. + */ + AUTH("auth", PrimitiveType.BOOLEAN, + Arrays.asList(Target.C, Target.CCPP), (config, value, err) -> { + config.auth = ASTUtils.toBoolean(value); + }), /** * Directive to let the generator use the custom build command. diff --git a/org.lflang/src/org/lflang/federated/launcher/FedLauncher.java b/org.lflang/src/org/lflang/federated/launcher/FedLauncher.java index b99b343d1e..30593e8a26 100644 --- a/org.lflang/src/org/lflang/federated/launcher/FedLauncher.java +++ b/org.lflang/src/org/lflang/federated/launcher/FedLauncher.java @@ -319,6 +319,9 @@ private String getRtiCommand(List federates, boolean isRemote) } else { commands.add("RTI -i ${FEDERATION_ID} \\"); } + if (targetConfig.auth) { + commands.add(" -a \\"); + } commands.addAll(List.of( " -n "+federates.size()+" \\", " -c "+targetConfig.clockSync.toString()+" \\" diff --git a/org.lflang/src/org/lflang/generator/c/CCmakeGenerator.java b/org.lflang/src/org/lflang/generator/c/CCmakeGenerator.java index ef3c5352eb..2461ec46d1 100644 --- a/org.lflang/src/org/lflang/generator/c/CCmakeGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CCmakeGenerator.java @@ -189,6 +189,22 @@ CodeBuilder generateCMakeCode( cMakeCode.pr("target_include_directories(${LF_MAIN_TARGET} PUBLIC include/core/modal_models)"); cMakeCode.pr("target_include_directories(${LF_MAIN_TARGET} PUBLIC include/core/utils)"); + if(targetConfig.auth) { + // If security is requested, add the auth option. + var osName = System.getProperty("os.name").toLowerCase(); + // if platform target was set, use given platform instead + if (targetConfig.platformOptions.platform != Platform.AUTO) { + osName = targetConfig.platformOptions.platform.toString(); + } + if (osName.contains("mac")) { + cMakeCode.pr("set(OPENSSL_ROOT_DIR /usr/local/opt/openssl)"); + } + cMakeCode.pr("# Find OpenSSL and link to it"); + cMakeCode.pr("find_package(OpenSSL REQUIRED)"); + cMakeCode.pr("target_link_libraries( ${LF_MAIN_TARGET} PRIVATE OpenSSL::SSL)"); + cMakeCode.newLine(); + } + if (targetConfig.threading || targetConfig.tracing != null) { // If threaded computation is requested, add the threads option. cMakeCode.pr("# Find threads and link to it"); diff --git a/org.lflang/src/org/lflang/generator/c/CGenerator.java b/org.lflang/src/org/lflang/generator/c/CGenerator.java index 92d167805b..9c9590b1e0 100644 --- a/org.lflang/src/org/lflang/generator/c/CGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CGenerator.java @@ -427,6 +427,10 @@ public void setCSpecificDefaults() { if (isFederated) { // Add compile definitions for federated execution targetConfig.compileDefinitions.put("FEDERATED", ""); + if(targetConfig.auth) { + // The federates are authenticated before joining federation. + targetConfig.compileDefinitions.put("FEDERATED_AUTHENTICATED", ""); + } if (targetConfig.coordination == CoordinationType.CENTRALIZED) { // The coordination is centralized. targetConfig.compileDefinitions.put("FEDERATED_CENTRALIZED", ""); diff --git a/test/C/src/federated/SimpleFederatedAuthenticated.lf b/test/C/src/federated/SimpleFederatedAuthenticated.lf new file mode 100644 index 0000000000..f6ce5edcc1 --- /dev/null +++ b/test/C/src/federated/SimpleFederatedAuthenticated.lf @@ -0,0 +1,23 @@ +/** + * This simple test checks if federate authentication works by adding `auth` + * target property. + */ +target C { + timeout: 2 secs, + build-type: RelWithDebInfo, + auth: true, + logging: DEBUG +} + +reactor Fed { + input in: int + output out: int +} + +federated reactor { + fed1 = new Fed() + fed2 = new Fed() + + fed1.out -> fed2.in + fed2.out -> fed1.in +}