Skip to content

Commit a5f56cb

Browse files
committed
move json ersistence into cpg-core
1 parent 3c93f63 commit a5f56cb

File tree

6 files changed

+232
-92
lines changed

6 files changed

+232
-92
lines changed

cpg-core/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ dependencies {
5353
implementation(libs.jacksonyml)
5454

5555
testImplementation(libs.junit.params)
56+
integrationTestImplementation(libs.kotlin.reflect)
5657

5758
testFixturesApi(
5859
libs.kotlin.test.junit5

cpg-neo4j/src/integrationTest/kotlin/de/fraunhofer/aisec/neo4j/IntegrationTest.kt renamed to cpg-core/src/integrationTest/kotlin/de/fraunhofer/aisec/cpg/IntegrationTest.kt

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,37 +23,39 @@
2323
* \______/ \__| \______/
2424
*
2525
*/
26-
package de.fraunhofer.aisec.neo4j
26+
package de.fraunhofer.aisec.cpg
2727

28-
import de.fraunhofer.aisec.cpg.TranslationManager
29-
import de.fraunhofer.aisec.cpg.TranslationResult
3028
import de.fraunhofer.aisec.cpg.graph.declarations.FunctionDeclaration
3129
import de.fraunhofer.aisec.cpg.graph.functions
3230
import de.fraunhofer.aisec.cpg.graph.statements.expressions.CallExpression
3331
import de.fraunhofer.aisec.cpg.persistence.createJsonGraph
3432
import de.fraunhofer.aisec.cpg.persistence.persistJson
35-
import de.fraunhofer.aisec.cpg_vis_neo4j.Application
3633
import java.nio.file.Paths
3734
import kotlin.io.path.createTempFile
38-
import kotlin.reflect.jvm.javaField
3935
import kotlin.test.assertEquals
4036
import kotlin.test.assertNotNull
4137
import org.junit.jupiter.api.Test
42-
import org.neo4j.ogm.annotation.Relationship
43-
import picocli.CommandLine
4438

45-
fun createTranslationResult(file: String = "client.cpp"): Pair<Application, TranslationResult> {
39+
fun createTranslationResult(file: String = "client.cpp"): TranslationResult {
4640
val topLevel = Paths.get("src").resolve("integrationTest").resolve("resources").toAbsolutePath()
4741
val path = topLevel.resolve(file).toAbsolutePath()
4842

49-
val cmd = CommandLine(Application::class.java)
50-
cmd.parseArgs(path.toString())
51-
val application = cmd.getCommand<Application>()
43+
val result =
44+
TranslationManager.builder()
45+
.config(
46+
TranslationConfiguration.builder()
47+
.topLevel(path.toFile())
48+
.optionalLanguage("de.fraunhofer.aisec.cpg.frontends.cxx.CLanguage")
49+
.optionalLanguage("de.fraunhofer.aisec.cpg.frontends.cxx.CPPLanguage")
50+
.sourceLocations(path.toFile())
51+
.defaultPasses()
52+
.build()
53+
)
54+
.build()
55+
.analyze()
56+
.get()
5257

53-
val translationConfiguration = application.setupTranslationConfiguration()
54-
val translationResult =
55-
TranslationManager.builder().config(translationConfiguration).build().analyze().get()
56-
return application to translationResult
58+
return result
5759
}
5860

5961
/**
@@ -64,7 +66,7 @@ class IntegrationTest {
6466

6567
@Test
6668
fun testBuildJsonGraph() {
67-
val (application, translationResult) = createTranslationResult()
69+
val translationResult = createTranslationResult()
6870

6971
// 22 inferred functions, 1 inferred method, 2 inferred constructors, 11 regular functions
7072
assertEquals(36, translationResult.functions.size)
@@ -86,9 +88,7 @@ class IntegrationTest {
8688

8789
val invokesEdge =
8890
graph.edges.firstOrNull {
89-
it.type ==
90-
(CallExpression::invokeEdges.javaField?.getAnnotation(Relationship::class.java))
91-
?.value &&
91+
it.type == "INVOKES" &&
9292
it.startNode == connectToCallExpr.id &&
9393
it.endNode == connectToFuncDel.id
9494
}
@@ -97,7 +97,7 @@ class IntegrationTest {
9797

9898
@Test
9999
fun testExportToJson() {
100-
val (application, translationResult) = createTranslationResult()
100+
val translationResult = createTranslationResult()
101101
// 22 inferred functions, 1 inferred method, 2 inferred constructors, 11 regular functions
102102
assertEquals(36, translationResult.functions.size)
103103
val path = createTempFile().toFile()
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
#include <iostream>
2+
#include <sys/socket.h>
3+
#include <netinet/in.h>
4+
#include <arpa/inet.h>
5+
#include <openssl/ssl.h>
6+
#include <openssl/err.h>
7+
8+
SSL *ssl;
9+
std::string bad_ciphers = "MD5";
10+
11+
int callMeBack(int preverify_ok, X509_STORE_CTX *x509_ctx);
12+
13+
int connectTo(std::string ip, int test) {
14+
int s = socket(AF_INET, SOCK_STREAM, 0);
15+
16+
if(!s) {
17+
printf("Error creating socket.\n");
18+
return -1;
19+
}
20+
21+
std::cerr << "Connecting to " << ip << "..." << std::endl;
22+
23+
struct sockaddr_in sa;
24+
memset(&sa, 0, sizeof(sa));
25+
sa.sin_family = AF_INET;
26+
sa.sin_addr.s_addr = inet_addr(ip.c_str());
27+
sa.sin_port = htons(443);
28+
socklen_t socklen = sizeof(sa);
29+
30+
if(connect(s, (struct sockaddr*)&sa, sizeof(sa))) {
31+
std::cerr << "Error connecting to server." << std::endl;
32+
return -1;
33+
}
34+
35+
return s;
36+
}
37+
38+
void failDisableVerification(SSL_CTX* ctx) {
39+
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, callMeBack);
40+
}
41+
42+
void failSetInsecureCiphers(SSL_CTX* ctx) {
43+
char ciphers[] = "ALL:!ADH";
44+
45+
SSL_CTX_set_cipher_list(ctx, ciphers);
46+
}
47+
48+
void failSetInsecureCiphersLiteral(SSL_CTX* ctx) {
49+
SSL_CTX_set_cipher_list(ctx, "ALL:!ADH");
50+
}
51+
52+
void failSetInsecureCiphersSTL(SSL_CTX* ctx) {
53+
std::string ciphers = "ALL:!ADH";
54+
55+
SSL_CTX_set_cipher_list(ctx, ciphers.c_str());
56+
}
57+
58+
void failSetInsecureCiphersGlobal(SSL_CTX* ctx) {
59+
SSL_CTX_set_cipher_list(ctx, bad_ciphers.c_str());
60+
}
61+
62+
void failDisableVerificationLambda(SSL_CTX* ctx) {
63+
// lambdas do not work yet
64+
/*SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, [](int preverify_ok, X509_STORE_CTX *x509_ctx) {
65+
return 1;
66+
});*/
67+
}
68+
69+
SSL_CTX* initTLSContext() {
70+
SSL_library_init();
71+
SSL_load_error_strings();
72+
SSL_CTX* ctx = SSL_CTX_new(TLSv1_2_client_method());
73+
74+
// set insecure cipher
75+
failSetInsecureCiphers(ctx);
76+
failSetInsecureCiphersLiteral(ctx);
77+
failSetInsecureCiphersSTL(ctx);
78+
failSetInsecureCiphersGlobal(ctx);
79+
80+
// enable verification
81+
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, nullptr);
82+
83+
// disable verification
84+
failDisableVerification(ctx);
85+
86+
return ctx;
87+
}
88+
89+
int main(int argc, char** argv) {
90+
int s = connectTo("172.217.18.99", 2);
91+
if(s < 0) {
92+
return -1;
93+
}
94+
95+
SSL_CTX* ctx = initTLSContext();
96+
97+
ssl = SSL_new(ctx);
98+
99+
if(!ssl) {
100+
std::cerr << "Error creating SSL." << std::endl;
101+
return -1;
102+
}
103+
104+
SSL_set_fd(ssl, s);
105+
106+
int err = SSL_connect(ssl);
107+
// this one confuses neo4j ogm
108+
if(err <= 0) {
109+
int sslerr = ERR_get_error();
110+
111+
std::cerr << "Error creating SSL connection. Error Code: " << ERR_error_string(sslerr, nullptr) << std::endl;
112+
return -1;
113+
}
114+
115+
if(err <= 0) {
116+
std::cerr << "Error creating SSL connection. Error Code: " << ERR_error_string(ERR_get_error(), nullptr) << std::endl;
117+
return -1;
118+
}
119+
120+
if (SSL_get_verify_result(ssl) == X509_V_OK) {
121+
std::cout << "Call to SSL_get_verify_result is ok" << std::endl;
122+
}
123+
124+
std::cout << "SSL communication established using " << SSL_get_cipher(ssl) << std::endl;
125+
126+
return 0;
127+
}
128+
129+
int callMeBack(int preverify_ok, X509_STORE_CTX *x509_ctx) {
130+
return 1;
131+
}

cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/persistence/Common.kt

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ import de.fraunhofer.aisec.cpg.graph.Node
3030
import de.fraunhofer.aisec.cpg.graph.Persistable
3131
import de.fraunhofer.aisec.cpg.graph.edges.collections.EdgeCollection
3232
import de.fraunhofer.aisec.cpg.graph.edges.collections.EdgeList
33+
import de.fraunhofer.aisec.cpg.helpers.IdentitySet
34+
import de.fraunhofer.aisec.cpg.helpers.identitySetOf
3335
import de.fraunhofer.aisec.cpg.helpers.neo4j.NameConverter
36+
import kotlin.collections.plusAssign
3437
import kotlin.reflect.KClass
3538
import kotlin.reflect.KProperty1
3639
import kotlin.reflect.KTypeProjection
@@ -349,3 +352,74 @@ fun String.toUpperSnakeCase(): String {
349352
val pattern = "(?<=.)[A-Z]".toRegex()
350353
return this.replace(pattern, "_$0").uppercase()
351354
}
355+
356+
internal typealias CpgRelationship = Map<String, Any?>
357+
358+
/**
359+
* Returns all [Node] objects that are connected with this node with some kind of relationship
360+
* defined in [schemaRelationships].
361+
*/
362+
val Persistable.connectedNodes: IdentitySet<Node>
363+
get() {
364+
val nodes = identitySetOf<Node>()
365+
366+
for (entry in this::class.schemaRelationships) {
367+
val value = entry.value.call(this)
368+
if (value is EdgeCollection<*, *>) {
369+
nodes += value.toNodeCollection()
370+
} else if (value is List<*>) {
371+
nodes += value.filterIsInstance<Node>()
372+
} else if (value is Node) {
373+
nodes += value
374+
}
375+
}
376+
377+
return nodes
378+
}
379+
380+
fun List<Node>.collectRelationships(): List<CpgRelationship> {
381+
val relationships = mutableListOf<CpgRelationship>()
382+
383+
for (node in this) {
384+
for (entry in node::class.schemaRelationships) {
385+
val value = entry.value.call(node)
386+
if (value is EdgeCollection<*, *>) {
387+
relationships +=
388+
value.map { edge ->
389+
mapOf(
390+
"startId" to edge.start.id.toString(),
391+
"endId" to edge.end.id.toString(),
392+
"type" to entry.key,
393+
) + edge.properties()
394+
}
395+
} else if (value is List<*>) {
396+
relationships +=
397+
value.filterIsInstance<Node>().map { end ->
398+
mapOf(
399+
"startId" to node.id.toString(),
400+
"endId" to end.id.toString(),
401+
"type" to entry.key,
402+
)
403+
}
404+
} else if (value is Node) {
405+
relationships +=
406+
mapOf(
407+
"startId" to node.id.toString(),
408+
"endId" to value.id.toString(),
409+
"type" to entry.key,
410+
)
411+
}
412+
}
413+
}
414+
415+
// Since Neo4J does not support multiple labels on edges, but we do internally, we
416+
// duplicate the edge for each label
417+
/*edge.labels.map { label ->
418+
mapOf(
419+
"startId" to edge.start.id.toString(),
420+
"endId" to edge.end.id.toString(),
421+
"type" to label
422+
) + edge.properties()
423+
}*/
424+
return relationships
425+
}

cpg-neo4j/src/main/kotlin/de/fraunhofer/aisec/cpg/persistence/Json.kt renamed to cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/persistence/Json.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,14 @@ import de.fraunhofer.aisec.cpg.graph.Persistable
3232
import de.fraunhofer.aisec.cpg.graph.nodes
3333
import de.fraunhofer.aisec.cpg.helpers.Benchmark
3434
import java.io.File
35+
import org.slf4j.LoggerFactory
3536

37+
internal val log = LoggerFactory.getLogger("Persistence")
38+
39+
/** Serialized cpg [Node] to be exported with jackson */
3640
data class JsonNode(val id: String, val labels: Set<String>, val properties: Map<String, Any?>)
3741

42+
/** Serialized cpg Relation to be exported with jackson */
3843
data class JsonEdge(
3944
val id: Long,
4045
val type: String,
@@ -43,6 +48,7 @@ data class JsonEdge(
4348
val properties: Map<String, Any?>,
4449
)
4550

51+
/** Container to hold serialized Nodes and Edge list of a cpg to be exported with jackson */
4652
data class JsonGraph(val nodes: List<JsonNode>, val edges: List<JsonEdge>)
4753

4854
/** Serialise the cpg using the OGM as nodes and edge list. */

0 commit comments

Comments
 (0)