feat(osint): create DNS result relations
This commit is contained in:
parent
f6f3e71002
commit
16a5d81e95
15 changed files with 340 additions and 75 deletions
2
Makefile
2
Makefile
|
|
@ -565,7 +565,9 @@ $(TEST_OSINT_DNS_INTEGRATION): \
|
||||||
src/models/osint_dns_proposal.c \
|
src/models/osint_dns_proposal.c \
|
||||||
src/models/osint_dns_query.c \
|
src/models/osint_dns_query.c \
|
||||||
src/models/entity_record.c \
|
src/models/entity_record.c \
|
||||||
|
src/models/relation_record.c \
|
||||||
src/dao/entity_dao.c \
|
src/dao/entity_dao.c \
|
||||||
|
src/dao/relation_dao.c \
|
||||||
src/database/database.c \
|
src/database/database.c \
|
||||||
src/database/schema.c \
|
src/database/schema.c \
|
||||||
src/database/statement.c \
|
src/database/statement.c \
|
||||||
|
|
|
||||||
|
|
@ -149,7 +149,9 @@ Le socle actuel comprend notamment :
|
||||||
- affichage sélectionnable des sorties standard et d’erreur, sans persistance ;
|
- affichage sélectionnable des sorties standard et d’erreur, sans persistance ;
|
||||||
- révision des réponses DNS sous forme de propositions avant intégration ;
|
- révision des réponses DNS sous forme de propositions avant intégration ;
|
||||||
- sélection explicite et intégration transactionnelle des propositions DNS
|
- sélection explicite et intégration transactionnelle des propositions DNS
|
||||||
compatibles, avec normalisation et détection des doublons.
|
compatibles, avec normalisation et détection des doublons ;
|
||||||
|
- création transactionnelle des relations DNS `resolves_to`, `aliases_to` et
|
||||||
|
`uses_name_server` depuis l'entité interrogée.
|
||||||
|
|
||||||
Les outils actuellement présents dans le catalogue initial sont :
|
Les outils actuellement présents dans le catalogue initial sont :
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1109,8 +1109,10 @@ enregistrées.
|
||||||
### Limite actuelle de la traçabilité OSINT
|
### Limite actuelle de la traçabilité OSINT
|
||||||
|
|
||||||
L'intégration DNS initiale peut créer des entités `domain_name` et
|
L'intégration DNS initiale peut créer des entités `domain_name` et
|
||||||
`ip_address`. La description de l'entité conserve une indication minimale :
|
`ip_address`, ainsi que les relations `resolves_to`, `aliases_to` et
|
||||||
outil `dns.dig`, cible interrogée et type d'enregistrement.
|
`uses_name_server`. La description de l'entité et la justification de la
|
||||||
|
relation conservent une indication minimale : outil `dns.dig`, cible
|
||||||
|
interrogée et type d'enregistrement.
|
||||||
|
|
||||||
Cette information ne remplace pas une provenance structurée. Une migration
|
Cette information ne remplace pas une provenance structurée. Une migration
|
||||||
future devra introduire un objet de résultat OSINT capable de conserver au
|
future devra introduire un objet de résultat OSINT capable de conserver au
|
||||||
|
|
|
||||||
|
|
@ -32,25 +32,31 @@ typedef enum
|
||||||
GQuark osint_dns_integration_error_quark(void);
|
GQuark osint_dns_integration_error_quark(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Intègre une sélection de propositions dans une transaction unique.
|
* @brief Intègre des propositions et leurs relations dans une transaction.
|
||||||
*
|
*
|
||||||
* Les propositions doivent être des OsintDnsProposal empruntées. Les valeurs
|
* Les propositions doivent être des OsintDnsProposal empruntées. Les valeurs
|
||||||
* incompatibles sont ignorées. Les couples type/valeur déjà présents sont
|
* incompatibles sont ignorées. Les couples type/valeur déjà présents sont
|
||||||
* comptés comme doublons et ne sont pas réinsérés.
|
* comptés comme doublons et ne sont pas réinsérés.
|
||||||
*
|
*
|
||||||
* @param database Connexion SQLite active.
|
* @param database Connexion SQLite active.
|
||||||
|
* @param source_entity_identifier UUID de l'entité interrogée.
|
||||||
* @param selected_proposals Propositions explicitement sélectionnées.
|
* @param selected_proposals Propositions explicitement sélectionnées.
|
||||||
* @param out_inserted_count Nombre d'entités créées.
|
* @param out_inserted_entity_count Nombre d'entités créées.
|
||||||
* @param out_skipped_count Nombre de propositions ignorées ou déjà présentes.
|
* @param out_skipped_entity_count Nombre d'entités ignorées ou réutilisées.
|
||||||
|
* @param out_inserted_relation_count Nombre de relations créées.
|
||||||
|
* @param out_skipped_relation_count Nombre de relations ignorées.
|
||||||
* @param error Emplacement facultatif recevant une erreur.
|
* @param error Emplacement facultatif recevant une erreur.
|
||||||
*
|
*
|
||||||
* @return TRUE lorsque la transaction est validée, sinon FALSE.
|
* @return TRUE lorsque la transaction est validée, sinon FALSE.
|
||||||
*/
|
*/
|
||||||
gboolean osint_dns_integration_apply(
|
gboolean osint_dns_integration_apply(
|
||||||
Database *database,
|
Database *database,
|
||||||
|
const char *source_entity_identifier,
|
||||||
GPtrArray *selected_proposals,
|
GPtrArray *selected_proposals,
|
||||||
guint *out_inserted_count,
|
guint *out_inserted_entity_count,
|
||||||
guint *out_skipped_count,
|
guint *out_skipped_entity_count,
|
||||||
|
guint *out_inserted_relation_count,
|
||||||
|
guint *out_skipped_relation_count,
|
||||||
GError **error
|
GError **error
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -104,6 +104,20 @@ char *osint_dns_proposal_dup_normalized_value(
|
||||||
const OsintDnsProposal *proposal
|
const OsintDnsProposal *proposal
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retourne le type de relation correspondant au type DNS.
|
||||||
|
*
|
||||||
|
* A, AAAA et PTR utilisent `resolves_to`, CNAME utilise `aliases_to` et NS
|
||||||
|
* utilise `uses_name_server`.
|
||||||
|
*
|
||||||
|
* @param proposal Proposition consultée.
|
||||||
|
*
|
||||||
|
* @return Identifiant statique de relation, ou NULL.
|
||||||
|
*/
|
||||||
|
const char *osint_dns_proposal_get_relation_type(
|
||||||
|
const OsintDnsProposal *proposal
|
||||||
|
);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -125,11 +125,13 @@ typedef void (*MainWindowAddRelationCallback)(
|
||||||
* @brief Callback appelé lors du déclenchement d'une action OSINT.
|
* @brief Callback appelé lors du déclenchement d'une action OSINT.
|
||||||
*
|
*
|
||||||
* @param action_identifier Identifiant stable de l'action.
|
* @param action_identifier Identifiant stable de l'action.
|
||||||
|
* @param target_identifier UUID de la sélection ciblée.
|
||||||
* @param target_value Valeur métier ciblée.
|
* @param target_value Valeur métier ciblée.
|
||||||
* @param user_data Données privées fournies par l'appelant.
|
* @param user_data Données privées fournies par l'appelant.
|
||||||
*/
|
*/
|
||||||
typedef void (*MainWindowOsintActionCallback)(
|
typedef void (*MainWindowOsintActionCallback)(
|
||||||
const char *action_identifier,
|
const char *action_identifier,
|
||||||
|
const char *target_identifier,
|
||||||
const char *target_value,
|
const char *target_value,
|
||||||
gpointer user_data
|
gpointer user_data
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -84,11 +84,13 @@ typedef void (*WorkspaceAddRelationCallback)(
|
||||||
* Les chaînes sont empruntées et uniquement valides pendant l'appel.
|
* Les chaînes sont empruntées et uniquement valides pendant l'appel.
|
||||||
*
|
*
|
||||||
* @param action_identifier Identifiant stable de l'action.
|
* @param action_identifier Identifiant stable de l'action.
|
||||||
|
* @param target_identifier UUID de la sélection ciblée.
|
||||||
* @param target_value Valeur métier ciblée par l'action.
|
* @param target_value Valeur métier ciblée par l'action.
|
||||||
* @param user_data Données empruntées fournies par l'appelant.
|
* @param user_data Données empruntées fournies par l'appelant.
|
||||||
*/
|
*/
|
||||||
typedef void (*WorkspaceOsintActionCallback)(
|
typedef void (*WorkspaceOsintActionCallback)(
|
||||||
const char *action_identifier,
|
const char *action_identifier,
|
||||||
|
const char *target_identifier,
|
||||||
const char *target_value,
|
const char *target_value,
|
||||||
gpointer user_data
|
gpointer user_data
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -162,6 +162,7 @@ typedef struct
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
Application *application;
|
Application *application;
|
||||||
|
char *target_identifier;
|
||||||
char *target_value;
|
char *target_value;
|
||||||
} ApplicationOsintActionContext;
|
} ApplicationOsintActionContext;
|
||||||
|
|
||||||
|
|
@ -169,6 +170,7 @@ typedef struct
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
Application *application;
|
Application *application;
|
||||||
|
char *source_entity_identifier;
|
||||||
GPtrArray *proposals;
|
GPtrArray *proposals;
|
||||||
} ApplicationOsintReviewContext;
|
} ApplicationOsintReviewContext;
|
||||||
|
|
||||||
|
|
@ -189,6 +191,7 @@ static void application_osint_review_context_free(gpointer user_data)
|
||||||
ApplicationOsintReviewContext *context = user_data;
|
ApplicationOsintReviewContext *context = user_data;
|
||||||
if (context == NULL) return;
|
if (context == NULL) return;
|
||||||
g_clear_pointer(&context->proposals, g_ptr_array_unref);
|
g_clear_pointer(&context->proposals, g_ptr_array_unref);
|
||||||
|
g_free(context->source_entity_identifier);
|
||||||
g_free(context);
|
g_free(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -198,16 +201,21 @@ static void application_on_osint_integration_confirmed(
|
||||||
gpointer user_data
|
gpointer user_data
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
Application *application = user_data;
|
ApplicationOsintReviewContext *review_context = user_data;
|
||||||
|
Application *application = review_context != NULL
|
||||||
|
? review_context->application : NULL;
|
||||||
const InvestigationProject *project = NULL;
|
const InvestigationProject *project = NULL;
|
||||||
Database *database = NULL;
|
Database *database = NULL;
|
||||||
const char *database_path = NULL;
|
const char *database_path = NULL;
|
||||||
guint inserted_count = 0U;
|
guint inserted_count = 0U;
|
||||||
guint skipped_count = 0U;
|
guint skipped_count = 0U;
|
||||||
|
guint inserted_relation_count = 0U;
|
||||||
|
guint skipped_relation_count = 0U;
|
||||||
char *message = NULL;
|
char *message = NULL;
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
|
|
||||||
if (application == NULL || application->session == NULL ||
|
if (application == NULL || review_context->source_entity_identifier == NULL ||
|
||||||
|
application->session == NULL ||
|
||||||
application->main_window == NULL)
|
application->main_window == NULL)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
|
@ -218,8 +226,9 @@ static void application_on_osint_integration_confirmed(
|
||||||
database_path = project != NULL
|
database_path = project != NULL
|
||||||
? investigation_project_get_database_path(project) : NULL;
|
? investigation_project_get_database_path(project) : NULL;
|
||||||
if (!osint_dns_integration_apply(
|
if (!osint_dns_integration_apply(
|
||||||
database, selected_proposals, &inserted_count, &skipped_count,
|
database, review_context->source_entity_identifier,
|
||||||
&error
|
selected_proposals, &inserted_count, &skipped_count,
|
||||||
|
&inserted_relation_count, &skipped_relation_count, &error
|
||||||
))
|
))
|
||||||
{
|
{
|
||||||
application_present_error(
|
application_present_error(
|
||||||
|
|
@ -233,10 +242,12 @@ static void application_on_osint_integration_confirmed(
|
||||||
}
|
}
|
||||||
|
|
||||||
message = g_strdup_printf(
|
message = g_strdup_printf(
|
||||||
"%u entité(s) créée(s), %u proposition(s) ignorée(s).\n\n"
|
"%u entité(s) créée(s), %u entité(s) réutilisée(s) ou ignorée(s).\n"
|
||||||
|
"%u relation(s) créée(s), %u relation(s) ignorée(s).\n\n"
|
||||||
"La provenance complète devra être ajoutée par une future migration "
|
"La provenance complète devra être ajoutée par une future migration "
|
||||||
"du schéma OSINT.",
|
"du schéma OSINT.",
|
||||||
inserted_count, skipped_count
|
inserted_count, skipped_count,
|
||||||
|
inserted_relation_count, skipped_relation_count
|
||||||
);
|
);
|
||||||
application_message_dialog_present(
|
application_message_dialog_present(
|
||||||
main_window_get_window(application->main_window),
|
main_window_get_window(application->main_window),
|
||||||
|
|
@ -260,7 +271,7 @@ static void application_on_osint_prepare_integration(gpointer user_data)
|
||||||
main_window_get_window(context->application->main_window),
|
main_window_get_window(context->application->main_window),
|
||||||
context->proposals,
|
context->proposals,
|
||||||
application_on_osint_integration_confirmed,
|
application_on_osint_integration_confirmed,
|
||||||
context->application
|
context
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -279,6 +290,7 @@ static void application_osint_action_context_free(
|
||||||
}
|
}
|
||||||
|
|
||||||
g_free(context->target_value);
|
g_free(context->target_value);
|
||||||
|
g_free(context->target_identifier);
|
||||||
g_free(context);
|
g_free(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1178,9 +1190,13 @@ static void application_on_dns_lookup_completed(
|
||||||
if (review_context != NULL)
|
if (review_context != NULL)
|
||||||
{
|
{
|
||||||
review_context->application = application;
|
review_context->application = application;
|
||||||
|
review_context->source_entity_identifier = g_strdup(
|
||||||
|
context->target_identifier
|
||||||
|
);
|
||||||
review_context->proposals = g_ptr_array_ref(proposals);
|
review_context->proposals = g_ptr_array_ref(proposals);
|
||||||
}
|
}
|
||||||
if (review_context == NULL || review_context->proposals == NULL)
|
if (review_context == NULL || review_context->proposals == NULL ||
|
||||||
|
review_context->source_entity_identifier == NULL)
|
||||||
{
|
{
|
||||||
application_osint_review_context_free(review_context);
|
application_osint_review_context_free(review_context);
|
||||||
review_context = NULL;
|
review_context = NULL;
|
||||||
|
|
@ -1224,6 +1240,7 @@ static void application_on_dns_lookup_completed(
|
||||||
*/
|
*/
|
||||||
static void application_start_dns_lookup(
|
static void application_start_dns_lookup(
|
||||||
Application *application,
|
Application *application,
|
||||||
|
const char *target_identifier,
|
||||||
const char *target_value
|
const char *target_value
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
|
@ -1236,6 +1253,7 @@ static void application_start_dns_lookup(
|
||||||
|
|
||||||
if (application == NULL || application->task_manager == NULL ||
|
if (application == NULL || application->task_manager == NULL ||
|
||||||
application->tool_initializer == NULL || target_value == NULL ||
|
application->tool_initializer == NULL || target_value == NULL ||
|
||||||
|
target_identifier == NULL || !g_uuid_string_is_valid(target_identifier) ||
|
||||||
!osint_dns_query_is_valid_target(target_value))
|
!osint_dns_query_is_valid_target(target_value))
|
||||||
{
|
{
|
||||||
if (application != NULL)
|
if (application != NULL)
|
||||||
|
|
@ -1274,10 +1292,12 @@ static void application_start_dns_lookup(
|
||||||
if (context != NULL)
|
if (context != NULL)
|
||||||
{
|
{
|
||||||
context->application = application;
|
context->application = application;
|
||||||
|
context->target_identifier = g_strdup(target_identifier);
|
||||||
context->target_value = g_strdup(target_value);
|
context->target_value = g_strdup(target_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context == NULL || context->target_value == NULL)
|
if (context == NULL || context->target_identifier == NULL ||
|
||||||
|
context->target_value == NULL)
|
||||||
{
|
{
|
||||||
application_osint_action_context_free(context);
|
application_osint_action_context_free(context);
|
||||||
tool_task_free(tool_task);
|
tool_task_free(tool_task);
|
||||||
|
|
@ -1319,6 +1339,7 @@ static void application_start_dns_lookup(
|
||||||
*/
|
*/
|
||||||
static void application_on_osint_action_requested(
|
static void application_on_osint_action_requested(
|
||||||
const char *action_identifier,
|
const char *action_identifier,
|
||||||
|
const char *target_identifier,
|
||||||
const char *target_value,
|
const char *target_value,
|
||||||
gpointer user_data
|
gpointer user_data
|
||||||
)
|
)
|
||||||
|
|
@ -1327,7 +1348,9 @@ static void application_on_osint_action_requested(
|
||||||
|
|
||||||
if (g_strcmp0(action_identifier, "dns-preview") == 0)
|
if (g_strcmp0(action_identifier, "dns-preview") == 0)
|
||||||
{
|
{
|
||||||
application_start_dns_lookup(application, target_value);
|
application_start_dns_lookup(
|
||||||
|
application, target_identifier, target_value
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,12 @@
|
||||||
#include "core/osint_dns_integration.h"
|
#include "core/osint_dns_integration.h"
|
||||||
|
|
||||||
#include "dao/entity_dao.h"
|
#include "dao/entity_dao.h"
|
||||||
|
#include "dao/relation_dao.h"
|
||||||
#include "database/error.h"
|
#include "database/error.h"
|
||||||
#include "database/transaction.h"
|
#include "database/transaction.h"
|
||||||
#include "models/entity_record.h"
|
#include "models/entity_record.h"
|
||||||
#include "models/osint_dns_proposal.h"
|
#include "models/osint_dns_proposal.h"
|
||||||
|
#include "models/relation_record.h"
|
||||||
|
|
||||||
#include <gio/gio.h>
|
#include <gio/gio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
@ -50,6 +52,18 @@ static char *osint_dns_integration_build_key(
|
||||||
return g_strdup_printf("%s\n%s", entity_type, value);
|
return g_strdup_printf("%s\n%s", entity_type, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @brief Construit la clé anti-doublon d'une relation orientée. */
|
||||||
|
static char *osint_dns_integration_build_relation_key(
|
||||||
|
const char *source_identifier,
|
||||||
|
const char *target_identifier,
|
||||||
|
const char *relation_type
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return g_strdup_printf(
|
||||||
|
"%s\n%s\n%s", source_identifier, target_identifier, relation_type
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/** @brief Renseigne une erreur littérale si possible. */
|
/** @brief Renseigne une erreur littérale si possible. */
|
||||||
static void osint_dns_integration_set_error(
|
static void osint_dns_integration_set_error(
|
||||||
GError **error,
|
GError **error,
|
||||||
|
|
@ -68,25 +82,38 @@ GQuark osint_dns_integration_error_quark(void)
|
||||||
|
|
||||||
gboolean osint_dns_integration_apply(
|
gboolean osint_dns_integration_apply(
|
||||||
Database *database,
|
Database *database,
|
||||||
|
const char *source_entity_identifier,
|
||||||
GPtrArray *selected_proposals,
|
GPtrArray *selected_proposals,
|
||||||
guint *out_inserted_count,
|
guint *out_inserted_entity_count,
|
||||||
guint *out_skipped_count,
|
guint *out_skipped_entity_count,
|
||||||
|
guint *out_inserted_relation_count,
|
||||||
|
guint *out_skipped_relation_count,
|
||||||
GError **error
|
GError **error
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
EntityDao *entity_dao = NULL;
|
EntityDao *entity_dao = NULL;
|
||||||
|
RelationDao *relation_dao = NULL;
|
||||||
GPtrArray *existing_entities = NULL;
|
GPtrArray *existing_entities = NULL;
|
||||||
|
GPtrArray *existing_relations = NULL;
|
||||||
GHashTable *known_entities = NULL;
|
GHashTable *known_entities = NULL;
|
||||||
|
GHashTable *known_relations = NULL;
|
||||||
|
EntityRecord *source_entity = NULL;
|
||||||
GDateTime *now = NULL;
|
GDateTime *now = NULL;
|
||||||
char *timestamp = NULL;
|
char *timestamp = NULL;
|
||||||
guint inserted_count = 0U;
|
guint inserted_entity_count = 0U;
|
||||||
guint skipped_count = 0U;
|
guint skipped_entity_count = 0U;
|
||||||
|
guint inserted_relation_count = 0U;
|
||||||
|
guint skipped_relation_count = 0U;
|
||||||
gboolean success = FALSE;
|
gboolean success = FALSE;
|
||||||
|
|
||||||
g_return_val_if_fail(error == NULL || *error == NULL, FALSE);
|
g_return_val_if_fail(error == NULL || *error == NULL, FALSE);
|
||||||
if (out_inserted_count != NULL) *out_inserted_count = 0U;
|
if (out_inserted_entity_count != NULL) *out_inserted_entity_count = 0U;
|
||||||
if (out_skipped_count != NULL) *out_skipped_count = 0U;
|
if (out_skipped_entity_count != NULL) *out_skipped_entity_count = 0U;
|
||||||
if (database == NULL || selected_proposals == NULL ||
|
if (out_inserted_relation_count != NULL) *out_inserted_relation_count = 0U;
|
||||||
|
if (out_skipped_relation_count != NULL) *out_skipped_relation_count = 0U;
|
||||||
|
if (database == NULL || source_entity_identifier == NULL ||
|
||||||
|
!g_uuid_string_is_valid(source_entity_identifier) ||
|
||||||
|
selected_proposals == NULL ||
|
||||||
selected_proposals->len == 0U)
|
selected_proposals->len == 0U)
|
||||||
{
|
{
|
||||||
osint_dns_integration_set_error(
|
osint_dns_integration_set_error(
|
||||||
|
|
@ -98,9 +125,27 @@ gboolean osint_dns_integration_apply(
|
||||||
|
|
||||||
entity_dao = entity_dao_new(database, error);
|
entity_dao = entity_dao_new(database, error);
|
||||||
if (entity_dao == NULL) return FALSE;
|
if (entity_dao == NULL) return FALSE;
|
||||||
|
relation_dao = relation_dao_new(database, error);
|
||||||
|
if (relation_dao == NULL) goto cleanup;
|
||||||
|
source_entity = entity_dao_find_by_identifier(
|
||||||
|
entity_dao, source_entity_identifier, error
|
||||||
|
);
|
||||||
|
if (source_entity == NULL)
|
||||||
|
{
|
||||||
|
if (error == NULL || *error == NULL)
|
||||||
|
osint_dns_integration_set_error(
|
||||||
|
error, OSINT_DNS_INTEGRATION_ERROR_INVALID_ARGUMENT,
|
||||||
|
"L'entité source de la résolution DNS est introuvable."
|
||||||
|
);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
existing_entities = entity_dao_list_all(entity_dao, error);
|
existing_entities = entity_dao_list_all(entity_dao, error);
|
||||||
if (existing_entities == NULL) goto cleanup;
|
if (existing_entities == NULL) goto cleanup;
|
||||||
known_entities = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
|
existing_relations = relation_dao_list_all(relation_dao, error);
|
||||||
|
if (existing_relations == NULL) goto cleanup;
|
||||||
|
known_entities = g_hash_table_new_full(
|
||||||
|
g_str_hash, g_str_equal, g_free, g_free
|
||||||
|
);
|
||||||
for (guint index = 0; index < existing_entities->len; index++)
|
for (guint index = 0; index < existing_entities->len; index++)
|
||||||
{
|
{
|
||||||
const EntityRecord *entity = g_ptr_array_index(existing_entities, index);
|
const EntityRecord *entity = g_ptr_array_index(existing_entities, index);
|
||||||
|
|
@ -108,15 +153,33 @@ gboolean osint_dns_integration_apply(
|
||||||
char *normalized_value = osint_dns_integration_normalize_existing_value(
|
char *normalized_value = osint_dns_integration_normalize_existing_value(
|
||||||
entity_type, entity_record_get_value(entity)
|
entity_type, entity_record_get_value(entity)
|
||||||
);
|
);
|
||||||
g_hash_table_add(
|
g_hash_table_insert(
|
||||||
known_entities,
|
known_entities,
|
||||||
osint_dns_integration_build_key(
|
osint_dns_integration_build_key(
|
||||||
entity_type,
|
entity_type,
|
||||||
normalized_value
|
normalized_value
|
||||||
)
|
),
|
||||||
|
g_strdup(entity_record_get_identifier(entity))
|
||||||
);
|
);
|
||||||
g_free(normalized_value);
|
g_free(normalized_value);
|
||||||
}
|
}
|
||||||
|
known_relations = g_hash_table_new_full(
|
||||||
|
g_str_hash, g_str_equal, g_free, NULL
|
||||||
|
);
|
||||||
|
for (guint index = 0; index < existing_relations->len; index++)
|
||||||
|
{
|
||||||
|
const RelationRecord *relation = g_ptr_array_index(
|
||||||
|
existing_relations, index
|
||||||
|
);
|
||||||
|
g_hash_table_add(
|
||||||
|
known_relations,
|
||||||
|
osint_dns_integration_build_relation_key(
|
||||||
|
relation_record_get_source_entity_identifier(relation),
|
||||||
|
relation_record_get_target_entity_identifier(relation),
|
||||||
|
relation_record_get_relation_type(relation)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
now = g_date_time_new_now_utc();
|
now = g_date_time_new_now_utc();
|
||||||
timestamp = now != NULL
|
timestamp = now != NULL
|
||||||
|
|
@ -146,60 +209,131 @@ gboolean osint_dns_integration_apply(
|
||||||
selected_proposals, index
|
selected_proposals, index
|
||||||
);
|
);
|
||||||
const char *entity_type = osint_dns_proposal_get_entity_type(proposal);
|
const char *entity_type = osint_dns_proposal_get_entity_type(proposal);
|
||||||
|
const char *relation_type =
|
||||||
|
osint_dns_proposal_get_relation_type(proposal);
|
||||||
char *normalized_value = osint_dns_proposal_dup_normalized_value(proposal);
|
char *normalized_value = osint_dns_proposal_dup_normalized_value(proposal);
|
||||||
char *entity_key = NULL;
|
char *entity_key = NULL;
|
||||||
char *identifier = NULL;
|
char *target_identifier = NULL;
|
||||||
char *description = NULL;
|
char *description = NULL;
|
||||||
EntityRecord *entity = NULL;
|
EntityRecord *entity = NULL;
|
||||||
|
RelationRecord *relation = NULL;
|
||||||
|
char *relation_identifier = NULL;
|
||||||
|
char *relation_key = NULL;
|
||||||
|
char *relation_label = NULL;
|
||||||
|
char *relation_justification = NULL;
|
||||||
GError *model_error = NULL;
|
GError *model_error = NULL;
|
||||||
|
|
||||||
if (entity_type == NULL || normalized_value == NULL)
|
if (entity_type == NULL || relation_type == NULL ||
|
||||||
|
normalized_value == NULL)
|
||||||
{
|
{
|
||||||
skipped_count++;
|
skipped_entity_count++;
|
||||||
|
skipped_relation_count++;
|
||||||
g_free(normalized_value);
|
g_free(normalized_value);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
entity_key = osint_dns_integration_build_key(entity_type, normalized_value);
|
entity_key = osint_dns_integration_build_key(entity_type, normalized_value);
|
||||||
if (g_hash_table_contains(known_entities, entity_key))
|
target_identifier = g_strdup(
|
||||||
|
g_hash_table_lookup(known_entities, entity_key)
|
||||||
|
);
|
||||||
|
if (target_identifier != NULL)
|
||||||
{
|
{
|
||||||
skipped_count++;
|
skipped_entity_count++;
|
||||||
g_free(entity_key);
|
|
||||||
g_free(normalized_value);
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
identifier = g_uuid_string_random();
|
|
||||||
description = g_strdup_printf(
|
|
||||||
"Proposition DNS %s obtenue avec dns.dig depuis %s. "
|
|
||||||
"Résultat OSINT à vérifier.",
|
|
||||||
osint_dns_proposal_get_record_type(proposal),
|
|
||||||
osint_dns_proposal_get_target(proposal)
|
|
||||||
);
|
|
||||||
entity = entity_record_new(
|
|
||||||
identifier, entity_type, normalized_value, normalized_value,
|
|
||||||
description, 50, timestamp, timestamp, ENTITY_STATUS_ACTIVE,
|
|
||||||
&model_error
|
|
||||||
);
|
|
||||||
if (entity == NULL || !entity_dao_insert(entity_dao, entity, error))
|
|
||||||
{
|
{
|
||||||
if (error != NULL && *error == NULL && model_error != NULL)
|
target_identifier = g_uuid_string_random();
|
||||||
g_propagate_error(error, g_steal_pointer(&model_error));
|
description = g_strdup_printf(
|
||||||
|
"Proposition DNS %s obtenue avec dns.dig depuis %s. "
|
||||||
|
"Résultat OSINT à vérifier.",
|
||||||
|
osint_dns_proposal_get_record_type(proposal),
|
||||||
|
osint_dns_proposal_get_target(proposal)
|
||||||
|
);
|
||||||
|
entity = entity_record_new(
|
||||||
|
target_identifier, entity_type, normalized_value,
|
||||||
|
normalized_value, description, 50, timestamp, timestamp,
|
||||||
|
ENTITY_STATUS_ACTIVE, &model_error
|
||||||
|
);
|
||||||
|
if (entity == NULL || !entity_dao_insert(entity_dao, entity, error))
|
||||||
|
{
|
||||||
|
if (error != NULL && *error == NULL && model_error != NULL)
|
||||||
|
g_propagate_error(error, g_steal_pointer(&model_error));
|
||||||
|
entity_record_free(entity);
|
||||||
|
g_clear_error(&model_error);
|
||||||
|
g_free(description);
|
||||||
|
g_free(target_identifier);
|
||||||
|
g_free(entity_key);
|
||||||
|
g_free(normalized_value);
|
||||||
|
database_transaction_rollback(database);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
g_hash_table_insert(
|
||||||
|
known_entities, entity_key, g_strdup(target_identifier)
|
||||||
|
);
|
||||||
|
entity_key = NULL;
|
||||||
|
inserted_entity_count++;
|
||||||
entity_record_free(entity);
|
entity_record_free(entity);
|
||||||
g_clear_error(&model_error);
|
g_clear_error(&model_error);
|
||||||
g_free(description);
|
g_free(description);
|
||||||
g_free(identifier);
|
|
||||||
g_free(entity_key);
|
|
||||||
g_free(normalized_value);
|
|
||||||
database_transaction_rollback(database);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
g_hash_table_add(known_entities, entity_key);
|
relation_key = osint_dns_integration_build_relation_key(
|
||||||
inserted_count++;
|
source_entity_identifier, target_identifier, relation_type
|
||||||
entity_record_free(entity);
|
);
|
||||||
g_clear_error(&model_error);
|
if (g_strcmp0(source_entity_identifier, target_identifier) == 0 ||
|
||||||
g_free(description);
|
g_hash_table_contains(known_relations, relation_key))
|
||||||
g_free(identifier);
|
{
|
||||||
|
skipped_relation_count++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
relation_identifier = g_uuid_string_random();
|
||||||
|
relation_label = g_strdup_printf(
|
||||||
|
"%s — %s → %s",
|
||||||
|
osint_dns_proposal_get_target(proposal), relation_type,
|
||||||
|
normalized_value
|
||||||
|
);
|
||||||
|
relation_justification = g_strdup_printf(
|
||||||
|
"Relation DNS %s obtenue avec dns.dig depuis %s. "
|
||||||
|
"Résultat OSINT à vérifier.",
|
||||||
|
osint_dns_proposal_get_record_type(proposal),
|
||||||
|
osint_dns_proposal_get_target(proposal)
|
||||||
|
);
|
||||||
|
relation = relation_record_new(
|
||||||
|
relation_identifier, source_entity_identifier,
|
||||||
|
target_identifier, relation_type, relation_label,
|
||||||
|
relation_justification, 50, timestamp, timestamp,
|
||||||
|
RELATION_STATUS_ACTIVE, &model_error
|
||||||
|
);
|
||||||
|
if (relation == NULL ||
|
||||||
|
!relation_dao_insert(relation_dao, relation, error))
|
||||||
|
{
|
||||||
|
if (error != NULL && *error == NULL && model_error != NULL)
|
||||||
|
g_propagate_error(error, g_steal_pointer(&model_error));
|
||||||
|
relation_record_free(relation);
|
||||||
|
g_clear_error(&model_error);
|
||||||
|
g_free(relation_identifier);
|
||||||
|
g_free(relation_label);
|
||||||
|
g_free(relation_justification);
|
||||||
|
g_free(relation_key);
|
||||||
|
g_free(target_identifier);
|
||||||
|
g_free(entity_key);
|
||||||
|
g_free(normalized_value);
|
||||||
|
database_transaction_rollback(database);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
g_hash_table_add(known_relations, relation_key);
|
||||||
|
relation_key = NULL;
|
||||||
|
inserted_relation_count++;
|
||||||
|
relation_record_free(relation);
|
||||||
|
g_clear_error(&model_error);
|
||||||
|
g_free(relation_identifier);
|
||||||
|
g_free(relation_label);
|
||||||
|
g_free(relation_justification);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free(relation_key);
|
||||||
|
g_free(target_identifier);
|
||||||
|
g_free(entity_key);
|
||||||
g_free(normalized_value);
|
g_free(normalized_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -215,14 +349,24 @@ gboolean osint_dns_integration_apply(
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
success = TRUE;
|
success = TRUE;
|
||||||
if (out_inserted_count != NULL) *out_inserted_count = inserted_count;
|
if (out_inserted_entity_count != NULL)
|
||||||
if (out_skipped_count != NULL) *out_skipped_count = skipped_count;
|
*out_inserted_entity_count = inserted_entity_count;
|
||||||
|
if (out_skipped_entity_count != NULL)
|
||||||
|
*out_skipped_entity_count = skipped_entity_count;
|
||||||
|
if (out_inserted_relation_count != NULL)
|
||||||
|
*out_inserted_relation_count = inserted_relation_count;
|
||||||
|
if (out_skipped_relation_count != NULL)
|
||||||
|
*out_skipped_relation_count = skipped_relation_count;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
g_free(timestamp);
|
g_free(timestamp);
|
||||||
g_clear_pointer(&now, g_date_time_unref);
|
g_clear_pointer(&now, g_date_time_unref);
|
||||||
g_clear_pointer(&known_entities, g_hash_table_unref);
|
g_clear_pointer(&known_entities, g_hash_table_unref);
|
||||||
|
g_clear_pointer(&known_relations, g_hash_table_unref);
|
||||||
g_clear_pointer(&existing_entities, g_ptr_array_unref);
|
g_clear_pointer(&existing_entities, g_ptr_array_unref);
|
||||||
|
g_clear_pointer(&existing_relations, g_ptr_array_unref);
|
||||||
|
entity_record_free(source_entity);
|
||||||
|
relation_dao_free(relation_dao);
|
||||||
entity_dao_free(entity_dao);
|
entity_dao_free(entity_dao);
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -210,3 +210,19 @@ char *osint_dns_proposal_dup_normalized_value(
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *osint_dns_proposal_get_relation_type(
|
||||||
|
const OsintDnsProposal *proposal
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const char *record_type = osint_dns_proposal_get_record_type(proposal);
|
||||||
|
if (g_strcmp0(record_type, "A") == 0 ||
|
||||||
|
g_strcmp0(record_type, "AAAA") == 0 ||
|
||||||
|
g_strcmp0(record_type, "PTR") == 0)
|
||||||
|
return "resolves_to";
|
||||||
|
if (g_strcmp0(record_type, "CNAME") == 0)
|
||||||
|
return "aliases_to";
|
||||||
|
if (g_strcmp0(record_type, "NS") == 0)
|
||||||
|
return "uses_name_server";
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -136,6 +136,7 @@ struct MainWindow
|
||||||
*/
|
*/
|
||||||
static void main_window_on_osint_action_requested(
|
static void main_window_on_osint_action_requested(
|
||||||
const char *action_identifier,
|
const char *action_identifier,
|
||||||
|
const char *target_identifier,
|
||||||
const char *target_value,
|
const char *target_value,
|
||||||
gpointer user_data
|
gpointer user_data
|
||||||
)
|
)
|
||||||
|
|
@ -149,6 +150,7 @@ static void main_window_on_osint_action_requested(
|
||||||
|
|
||||||
main_window->osint_action_callback(
|
main_window->osint_action_callback(
|
||||||
action_identifier,
|
action_identifier,
|
||||||
|
target_identifier,
|
||||||
target_value,
|
target_value,
|
||||||
main_window->osint_action_user_data
|
main_window->osint_action_user_data
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -142,18 +142,25 @@ static GtkWidget *osint_dns_review_dialog_create_row(
|
||||||
{
|
{
|
||||||
GtkWidget *row = gtk_box_new(GTK_ORIENTATION_VERTICAL, 4);
|
GtkWidget *row = gtk_box_new(GTK_ORIENTATION_VERTICAL, 4);
|
||||||
const char *entity_type = osint_dns_proposal_get_entity_type(proposal);
|
const char *entity_type = osint_dns_proposal_get_entity_type(proposal);
|
||||||
|
const char *relation_type = osint_dns_proposal_get_relation_type(proposal);
|
||||||
char *normalized_value = osint_dns_proposal_dup_normalized_value(proposal);
|
char *normalized_value = osint_dns_proposal_dup_normalized_value(proposal);
|
||||||
const gboolean compatible = entity_type != NULL && normalized_value != NULL;
|
const gboolean compatible = entity_type != NULL && relation_type != NULL &&
|
||||||
|
normalized_value != NULL;
|
||||||
char *title = g_strdup_printf(
|
char *title = g_strdup_printf(
|
||||||
"%s → %s",
|
"%s → %s",
|
||||||
osint_dns_proposal_get_record_type(proposal),
|
osint_dns_proposal_get_record_type(proposal),
|
||||||
osint_dns_proposal_get_value(proposal)
|
osint_dns_proposal_get_value(proposal)
|
||||||
);
|
);
|
||||||
char *details = g_strdup_printf(
|
char *details = g_strdup_printf(
|
||||||
"Cible : %s\nPropriétaire : %s\nType Labfy : %s",
|
"Cible : %s\nPropriétaire : %s\nType Labfy : %s\n"
|
||||||
|
"Relation prévue : %s — %s → %s",
|
||||||
osint_dns_proposal_get_target(proposal),
|
osint_dns_proposal_get_target(proposal),
|
||||||
osint_dns_proposal_get_owner(proposal),
|
osint_dns_proposal_get_owner(proposal),
|
||||||
compatible ? entity_type : "non pris en charge"
|
compatible ? entity_type : "non pris en charge",
|
||||||
|
osint_dns_proposal_get_target(proposal),
|
||||||
|
compatible ? relation_type : "non prise en charge",
|
||||||
|
normalized_value != NULL ? normalized_value
|
||||||
|
: osint_dns_proposal_get_value(proposal)
|
||||||
);
|
);
|
||||||
GtkWidget *selection_button = gtk_check_button_new_with_label(title);
|
GtkWidget *selection_button = gtk_check_button_new_with_label(title);
|
||||||
GtkWidget *details_label = gtk_label_new(details);
|
GtkWidget *details_label = gtk_label_new(details);
|
||||||
|
|
|
||||||
|
|
@ -147,6 +147,7 @@ static void workspace_on_osint_action_clicked(
|
||||||
"osint-action-identifier"
|
"osint-action-identifier"
|
||||||
);
|
);
|
||||||
const char *target_value = NULL;
|
const char *target_value = NULL;
|
||||||
|
const char *target_identifier = NULL;
|
||||||
|
|
||||||
if (workspace == NULL || workspace->osint_tools_status_label == NULL)
|
if (workspace == NULL || workspace->osint_tools_status_label == NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -165,9 +166,13 @@ static void workspace_on_osint_action_clicked(
|
||||||
target_value = osint_selection_context_get_value(
|
target_value = osint_selection_context_get_value(
|
||||||
workspace->osint_selection_context
|
workspace->osint_selection_context
|
||||||
);
|
);
|
||||||
|
target_identifier = osint_selection_context_get_identifier(
|
||||||
|
workspace->osint_selection_context
|
||||||
|
);
|
||||||
|
|
||||||
if (workspace->osint_action_callback == NULL ||
|
if (workspace->osint_action_callback == NULL ||
|
||||||
action_identifier == NULL || target_value == NULL)
|
action_identifier == NULL || target_identifier == NULL ||
|
||||||
|
target_value == NULL)
|
||||||
{
|
{
|
||||||
gtk_label_set_text(
|
gtk_label_set_text(
|
||||||
GTK_LABEL(workspace->osint_tools_status_label),
|
GTK_LABEL(workspace->osint_tools_status_label),
|
||||||
|
|
@ -187,6 +192,7 @@ static void workspace_on_osint_action_clicked(
|
||||||
|
|
||||||
workspace->osint_action_callback(
|
workspace->osint_action_callback(
|
||||||
action_identifier,
|
action_identifier,
|
||||||
|
target_identifier,
|
||||||
target_value,
|
target_value,
|
||||||
workspace->osint_action_user_data
|
workspace->osint_action_user_data
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,10 @@
|
||||||
#include "core/osint_dns_integration.h"
|
#include "core/osint_dns_integration.h"
|
||||||
|
|
||||||
#include "dao/entity_dao.h"
|
#include "dao/entity_dao.h"
|
||||||
|
#include "dao/relation_dao.h"
|
||||||
#include "database/database.h"
|
#include "database/database.h"
|
||||||
#include "models/osint_dns_proposal.h"
|
#include "models/osint_dns_proposal.h"
|
||||||
|
#include "models/relation_record.h"
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <glib/gstdio.h>
|
#include <glib/gstdio.h>
|
||||||
|
|
@ -19,14 +21,26 @@ static void test_integration_and_duplicates(void)
|
||||||
char *database_path = g_build_filename(directory, "Enquete.sqlite", NULL);
|
char *database_path = g_build_filename(directory, "Enquete.sqlite", NULL);
|
||||||
Database *database = NULL;
|
Database *database = NULL;
|
||||||
EntityDao *entity_dao = NULL;
|
EntityDao *entity_dao = NULL;
|
||||||
|
RelationDao *relation_dao = NULL;
|
||||||
|
EntityRecord *source = NULL;
|
||||||
GPtrArray *proposals = NULL;
|
GPtrArray *proposals = NULL;
|
||||||
GPtrArray *entities = NULL;
|
GPtrArray *entities = NULL;
|
||||||
|
GPtrArray *relations = NULL;
|
||||||
guint inserted = 0U;
|
guint inserted = 0U;
|
||||||
guint skipped = 0U;
|
guint skipped = 0U;
|
||||||
|
guint inserted_relations = 0U;
|
||||||
|
guint skipped_relations = 0U;
|
||||||
|
|
||||||
g_assert_no_error(error);
|
g_assert_no_error(error);
|
||||||
g_assert_true(database_initialize(database_path, "DNS", directory));
|
g_assert_true(database_initialize(database_path, "DNS", directory));
|
||||||
database = database_open(database_path);
|
database = database_open(database_path);
|
||||||
|
entity_dao = entity_dao_new(database, &error);
|
||||||
|
source = entity_record_new(
|
||||||
|
"11111111-1111-4111-8111-111111111111", "domain_name",
|
||||||
|
"example.org", NULL, NULL, 50, "2026-01-01T00:00:00Z",
|
||||||
|
"2026-01-01T00:00:00Z", ENTITY_STATUS_ACTIVE, &error
|
||||||
|
);
|
||||||
|
g_assert_true(entity_dao_insert(entity_dao, source, &error));
|
||||||
proposals = osint_dns_proposal_parse(
|
proposals = osint_dns_proposal_parse(
|
||||||
"example.org",
|
"example.org",
|
||||||
"example.org. 60 IN A 192.0.2.10\n"
|
"example.org. 60 IN A 192.0.2.10\n"
|
||||||
|
|
@ -34,22 +48,33 @@ static void test_integration_and_duplicates(void)
|
||||||
"example.org. 60 IN MX 10 mail.example.org.\n"
|
"example.org. 60 IN MX 10 mail.example.org.\n"
|
||||||
);
|
);
|
||||||
g_assert_true(osint_dns_integration_apply(
|
g_assert_true(osint_dns_integration_apply(
|
||||||
database, proposals, &inserted, &skipped, &error
|
database, "11111111-1111-4111-8111-111111111111", proposals,
|
||||||
|
&inserted, &skipped, &inserted_relations, &skipped_relations, &error
|
||||||
));
|
));
|
||||||
g_assert_no_error(error);
|
g_assert_no_error(error);
|
||||||
g_assert_cmpuint(inserted, ==, 2);
|
g_assert_cmpuint(inserted, ==, 2);
|
||||||
g_assert_cmpuint(skipped, ==, 1);
|
g_assert_cmpuint(skipped, ==, 1);
|
||||||
|
g_assert_cmpuint(inserted_relations, ==, 2);
|
||||||
|
g_assert_cmpuint(skipped_relations, ==, 1);
|
||||||
|
|
||||||
g_assert_true(osint_dns_integration_apply(
|
g_assert_true(osint_dns_integration_apply(
|
||||||
database, proposals, &inserted, &skipped, &error
|
database, "11111111-1111-4111-8111-111111111111", proposals,
|
||||||
|
&inserted, &skipped, &inserted_relations, &skipped_relations, &error
|
||||||
));
|
));
|
||||||
g_assert_cmpuint(inserted, ==, 0);
|
g_assert_cmpuint(inserted, ==, 0);
|
||||||
g_assert_cmpuint(skipped, ==, 3);
|
g_assert_cmpuint(skipped, ==, 3);
|
||||||
entity_dao = entity_dao_new(database, &error);
|
g_assert_cmpuint(inserted_relations, ==, 0);
|
||||||
|
g_assert_cmpuint(skipped_relations, ==, 3);
|
||||||
entities = entity_dao_list_all(entity_dao, &error);
|
entities = entity_dao_list_all(entity_dao, &error);
|
||||||
g_assert_cmpuint(entities->len, ==, 2);
|
g_assert_cmpuint(entities->len, ==, 3);
|
||||||
|
relation_dao = relation_dao_new(database, &error);
|
||||||
|
relations = relation_dao_list_all(relation_dao, &error);
|
||||||
|
g_assert_cmpuint(relations->len, ==, 2);
|
||||||
|
|
||||||
|
g_ptr_array_unref(relations);
|
||||||
|
relation_dao_free(relation_dao);
|
||||||
g_ptr_array_unref(entities);
|
g_ptr_array_unref(entities);
|
||||||
|
entity_record_free(source);
|
||||||
entity_dao_free(entity_dao);
|
entity_dao_free(entity_dao);
|
||||||
g_ptr_array_unref(proposals);
|
g_ptr_array_unref(proposals);
|
||||||
database_close(database);
|
database_close(database);
|
||||||
|
|
@ -63,7 +88,7 @@ static void test_invalid_arguments(void)
|
||||||
{
|
{
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
g_assert_false(osint_dns_integration_apply(
|
g_assert_false(osint_dns_integration_apply(
|
||||||
NULL, NULL, NULL, NULL, &error
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, &error
|
||||||
));
|
));
|
||||||
g_assert_error(
|
g_assert_error(
|
||||||
error, OSINT_DNS_INTEGRATION_ERROR,
|
error, OSINT_DNS_INTEGRATION_ERROR,
|
||||||
|
|
@ -83,6 +108,8 @@ static void test_normalized_existing_domain_is_skipped(void)
|
||||||
GPtrArray *proposals = NULL;
|
GPtrArray *proposals = NULL;
|
||||||
guint inserted = 0U;
|
guint inserted = 0U;
|
||||||
guint skipped = 0U;
|
guint skipped = 0U;
|
||||||
|
guint inserted_relations = 0U;
|
||||||
|
guint skipped_relations = 0U;
|
||||||
|
|
||||||
g_assert_true(database_initialize(database_path, "DNS", directory));
|
g_assert_true(database_initialize(database_path, "DNS", directory));
|
||||||
database = database_open(database_path);
|
database = database_open(database_path);
|
||||||
|
|
@ -97,10 +124,13 @@ static void test_normalized_existing_domain_is_skipped(void)
|
||||||
"example.org", "example.org. 60 IN CNAME www.example.org.\n"
|
"example.org", "example.org. 60 IN CNAME www.example.org.\n"
|
||||||
);
|
);
|
||||||
g_assert_true(osint_dns_integration_apply(
|
g_assert_true(osint_dns_integration_apply(
|
||||||
database, proposals, &inserted, &skipped, &error
|
database, "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa", proposals,
|
||||||
|
&inserted, &skipped, &inserted_relations, &skipped_relations, &error
|
||||||
));
|
));
|
||||||
g_assert_cmpuint(inserted, ==, 0);
|
g_assert_cmpuint(inserted, ==, 0);
|
||||||
g_assert_cmpuint(skipped, ==, 1);
|
g_assert_cmpuint(skipped, ==, 1);
|
||||||
|
g_assert_cmpuint(inserted_relations, ==, 0);
|
||||||
|
g_assert_cmpuint(skipped_relations, ==, 1);
|
||||||
|
|
||||||
g_ptr_array_unref(proposals);
|
g_ptr_array_unref(proposals);
|
||||||
entity_record_free(existing);
|
entity_record_free(existing);
|
||||||
|
|
|
||||||
|
|
@ -67,10 +67,17 @@ static void test_entity_mapping_and_normalization(void)
|
||||||
|
|
||||||
g_assert_cmpstr(osint_dns_proposal_get_entity_type(ipv4), ==, "ip_address");
|
g_assert_cmpstr(osint_dns_proposal_get_entity_type(ipv4), ==, "ip_address");
|
||||||
g_assert_cmpstr(ipv4_value, ==, "192.0.2.10");
|
g_assert_cmpstr(ipv4_value, ==, "192.0.2.10");
|
||||||
|
g_assert_cmpstr(
|
||||||
|
osint_dns_proposal_get_relation_type(ipv4), ==, "resolves_to"
|
||||||
|
);
|
||||||
g_assert_cmpstr(ipv6_value, ==, "2001:db8::1");
|
g_assert_cmpstr(ipv6_value, ==, "2001:db8::1");
|
||||||
g_assert_cmpstr(osint_dns_proposal_get_entity_type(domain), ==, "domain_name");
|
g_assert_cmpstr(osint_dns_proposal_get_entity_type(domain), ==, "domain_name");
|
||||||
g_assert_cmpstr(domain_value, ==, "www.example.org");
|
g_assert_cmpstr(domain_value, ==, "www.example.org");
|
||||||
|
g_assert_cmpstr(
|
||||||
|
osint_dns_proposal_get_relation_type(domain), ==, "aliases_to"
|
||||||
|
);
|
||||||
g_assert_null(osint_dns_proposal_get_entity_type(unsupported));
|
g_assert_null(osint_dns_proposal_get_entity_type(unsupported));
|
||||||
|
g_assert_null(osint_dns_proposal_get_relation_type(unsupported));
|
||||||
g_assert_null(osint_dns_proposal_dup_normalized_value(unsupported));
|
g_assert_null(osint_dns_proposal_dup_normalized_value(unsupported));
|
||||||
|
|
||||||
g_free(ipv4_value);
|
g_free(ipv4_value);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue