feat(osint): execute DNS lookup action

This commit is contained in:
grayTerminal-sh 2026-07-22 11:54:01 +02:00
parent b1b2320469
commit 6c8113dfea
13 changed files with 720 additions and 18 deletions

View file

@ -115,6 +115,7 @@ TEST_INVESTIGATION_GRAPH_LOAD_TASK := tests/test_investigation_graph_load_task
TEST_GRAPH_NODE_POSITION_DAO := tests/test_graph_node_position_dao
TEST_OSINT_SELECTION_CONTEXT := tests/test_osint_selection_context
TEST_OSINT_ACTION_CATALOG := tests/test_osint_action_catalog
TEST_OSINT_DNS_QUERY := tests/test_osint_dns_query
all: $(TARGET)
@ -545,6 +546,11 @@ $(TEST_OSINT_ACTION_CATALOG): \
src/models/relation_record.c
$(CC) $(TEST_CFLAGS) $^ -o $@ $(TEST_LDFLAGS)
$(TEST_OSINT_DNS_QUERY): \
tests/test_osint_dns_query.c \
src/models/osint_dns_query.c
$(CC) $(TEST_CFLAGS) $^ -o $@ $(TEST_LDFLAGS)
$(TEST_INVESTIGATION_GRAPH_LOAD_TASK): \
tests/test_investigation_graph_load_task.c \
src/core/investigation_graph_load_task.c \
@ -614,7 +620,8 @@ test: \
$(TEST_INVESTIGATION_GRAPH_LOAD_TASK) \
$(TEST_GRAPH_NODE_POSITION_DAO) \
$(TEST_OSINT_SELECTION_CONTEXT) \
$(TEST_OSINT_ACTION_CATALOG)
$(TEST_OSINT_ACTION_CATALOG) \
$(TEST_OSINT_DNS_QUERY)
@echo "Exécution des tests..."
@./$(TEST_NODE)
@./$(TEST_TREE_MODEL)
@ -664,6 +671,7 @@ test: \
@$(TEST_GRAPH_NODE_POSITION_DAO)
@$(TEST_OSINT_SELECTION_CONTEXT)
@$(TEST_OSINT_ACTION_CATALOG)
@$(TEST_OSINT_DNS_QUERY)
@echo "Tous les tests sont valides."
%.o: %.c
@ -719,7 +727,8 @@ clean:
$(TEST_INVESTIGATION_GRAPH_LOAD_TASK) \
$(TEST_GRAPH_NODE_POSITION_DAO) \
$(TEST_OSINT_SELECTION_CONTEXT) \
$(TEST_OSINT_ACTION_CATALOG)
$(TEST_OSINT_ACTION_CATALOG) \
$(TEST_OSINT_DNS_QUERY)
-include $(DEP)

View file

@ -144,7 +144,9 @@ Le socle actuel comprend notamment :
- menu OSINT contextuel préparé pour les entités et relations du graphe ;
- contexte de sélection OSINT indépendant de GTK et validé par des tests ;
- catalogue déterministe des actions compatibles avec la sélection OSINT ;
- disponibilité des actions OSINT synchronisée avec le registre doutils.
- disponibilité des actions OSINT synchronisée avec le registre doutils ;
- résolution DNS asynchrone avec `dig` depuis une entité domaine ;
- affichage sélectionnable des sorties standard et derreur, sans persistance.
Les outils actuellement présents dans le catalogue initial sont :

View file

@ -0,0 +1,30 @@
/******************************************************************************
* @file osint_dns_query.h
* @brief Validation des cibles utilisées pour une résolution DNS OSINT.
******************************************************************************/
#ifndef LABFY_INVESTIGATION_OSINT_DNS_QUERY_H
#define LABFY_INVESTIGATION_OSINT_DNS_QUERY_H
#include <glib.h>
G_BEGIN_DECLS
/**
* @brief Vérifie qu'une cible est un nom de domaine DNS exploitable.
*
* La fonction accepte les lettres ASCII sans distinction de casse, les
* chiffres, les tirets internes et les points séparant les labels. Un point
* final représentant la racine DNS est également accepté.
*
* @param target_value Valeur à vérifier.
*
* @return TRUE lorsque la cible peut être transmise à dig.
*/
gboolean osint_dns_query_is_valid_target(
const char *target_value
);
G_END_DECLS
#endif

View file

@ -49,6 +49,26 @@ void application_message_dialog_present(
const char *message
);
/**
* @brief Affiche un message accompagné d'un contenu textuel défilable.
*
* Le contenu détaillé est affiché dans une zone monospace sélectionnable.
* Les chaînes sont copiées par les widgets GTK.
*
* @param parent_window Fenêtre parente, ou NULL.
* @param message_type Type de message.
* @param title Titre de la fenêtre, ou NULL.
* @param message Message principal, ou NULL.
* @param details Contenu détaillé, ou NULL.
*/
void application_message_dialog_present_details(
GtkWindow *parent_window,
ApplicationMessageDialogType message_type,
const char *title,
const char *message,
const char *details
);
/**
* @brief Affiche un dialogue modal demandant une confirmation.
*

View file

@ -121,6 +121,19 @@ typedef void (*MainWindowAddRelationCallback)(
gpointer user_data
);
/**
* @brief Callback appelé lors du déclenchement d'une action OSINT.
*
* @param action_identifier Identifiant stable de l'action.
* @param target_value Valeur métier ciblée.
* @param user_data Données privées fournies par l'appelant.
*/
typedef void (*MainWindowOsintActionCallback)(
const char *action_identifier,
const char *target_value,
gpointer user_data
);
/**
* @brief Définit le callback de vérification d'une preuve.
*
@ -181,6 +194,21 @@ void main_window_set_add_relation_callback(
gpointer user_data
);
/**
* @brief Définit le callback de déclenchement des actions OSINT.
*
* MainWindow relaie uniquement la demande provenant du Workspace.
*
* @param main_window Fenêtre principale.
* @param callback Callback facultatif.
* @param user_data Données privées transmises au callback.
*/
void main_window_set_osint_action_callback(
MainWindow *main_window,
MainWindowOsintActionCallback callback,
gpointer user_data
);
/**
* @brief Définit le callback du bouton « Nouvelle enquête ».
*

View file

@ -78,6 +78,21 @@ typedef void (*WorkspaceAddRelationCallback)(
gpointer user_data
);
/**
* @brief Callback appelé lors du déclenchement d'une action OSINT.
*
* Les chaînes sont empruntées et uniquement valides pendant l'appel.
*
* @param action_identifier Identifiant stable de l'action.
* @param target_value Valeur métier ciblée par l'action.
* @param user_data Données empruntées fournies par l'appelant.
*/
typedef void (*WorkspaceOsintActionCallback)(
const char *action_identifier,
const char *target_value,
gpointer user_data
);
/**
* @brief Crée une nouvelle zone de travail.
*
@ -171,6 +186,22 @@ void workspace_set_osint_tool_state(
const char *version
);
/**
* @brief Définit le callback de déclenchement des actions OSINT.
*
* Le Workspace ne lance aucun outil externe. Il relaie uniquement l'action
* et la valeur du contexte courant vers la couche applicative.
*
* @param workspace Zone de travail.
* @param callback Callback facultatif.
* @param user_data Données empruntées transmises au callback.
*/
void workspace_set_osint_action_callback(
Workspace *workspace,
WorkspaceOsintActionCallback callback,
gpointer user_data
);
/**
* @brief Définit le callback de vérification de la preuve affichée.
*

View file

@ -13,6 +13,7 @@
#include "models/investigation_graph_layout.h"
#include "models/investigation_graph_model.h"
#include "models/investigation_record.h"
#include "models/osint_dns_query.h"
#include "core/investigation_tree_builder.h"
#include "views/create_investigation_dialog.h"
#include "views/folder_dialog.h"
@ -21,6 +22,7 @@
#include "core/task_manager.h"
#include "core/background_task.h"
#include "core/tool_initializer.h"
#include "core/tool_task.h"
#include "views/file_dialog.h"
#include "core/evidence_import_task.h"
#include "models/evidence_record.h"
@ -151,6 +153,33 @@ typedef struct
char *original_name;
} ApplicationEvidenceIntegrityContext;
/**
* @brief Contexte conservé jusqu'à la fin d'une action OSINT.
*/
typedef struct
{
Application *application;
char *target_value;
} ApplicationOsintActionContext;
/**
* @brief Libère le contexte d'une action OSINT.
*/
static void application_osint_action_context_free(
gpointer user_data
)
{
ApplicationOsintActionContext *context = user_data;
if (context == NULL)
{
return;
}
g_free(context->target_value);
g_free(context);
}
/**
* @brief Libère le contexte du dialogue de métadonnées.
*/
@ -914,6 +943,261 @@ static void application_start_tool_initialization(
}
}
/**
* @brief Convertit une sortie binaire d'outil en texte UTF-8 affichable.
*
* @param bytes Octets empruntés, ou NULL.
*
* @return Nouvelle chaîne UTF-8, jamais NULL.
*/
static char *application_osint_output_to_utf8(
GBytes *bytes
)
{
gconstpointer data = NULL;
gsize data_size = 0;
if (bytes == NULL)
{
return g_strdup("");
}
data = g_bytes_get_data(bytes, &data_size);
if (data == NULL || data_size == 0U)
{
return g_strdup("");
}
return g_utf8_make_valid(data, (gssize) data_size);
}
/**
* @brief Présente le résultat final d'une résolution DNS.
*/
static void application_on_dns_lookup_completed(
BackgroundTask *task,
gpointer user_data
)
{
ApplicationOsintActionContext *context = user_data;
Application *application = NULL;
const ToolTaskResult *task_result = NULL;
const ToolProcessResult *process_result = NULL;
GBytes *stdout_bytes = NULL;
GBytes *stderr_bytes = NULL;
char *stdout_text = NULL;
char *stderr_text = NULL;
char *details = NULL;
char *message = NULL;
GError *error = NULL;
if (task == NULL || context == NULL || context->application == NULL)
{
return;
}
application = context->application;
if (application->main_window == NULL)
{
return;
}
if (background_task_get_state(task) != BACKGROUND_TASK_STATE_COMPLETED)
{
error = background_task_dup_error(task);
application_present_error(
application,
"Résolution DNS impossible",
error != NULL
? error->message
: "L'exécution de dig a été annulée ou a échoué."
);
g_clear_error(&error);
return;
}
task_result = tool_task_result_from_background_task(task);
process_result = tool_task_result_get_process_result(task_result);
if (process_result == NULL)
{
application_present_error(
application,
"Résolution DNS incomplète",
"La tâche s'est terminée sans résultat exploitable."
);
return;
}
stdout_bytes = tool_process_result_ref_stdout(process_result);
stderr_bytes = tool_process_result_ref_stderr(process_result);
stdout_text = application_osint_output_to_utf8(stdout_bytes);
stderr_text = application_osint_output_to_utf8(stderr_bytes);
if (stdout_text != NULL && stdout_text[0] != '\0' &&
stderr_text != NULL && stderr_text[0] != '\0')
{
details = g_strdup_printf(
"Sortie standard :\n%s\n\nSortie d'erreur :\n%s",
stdout_text,
stderr_text
);
}
else if (stdout_text != NULL && stdout_text[0] != '\0')
{
details = g_strdup(stdout_text);
}
else if (stderr_text != NULL && stderr_text[0] != '\0')
{
details = g_strdup(stderr_text);
}
else
{
details = g_strdup("Aucun enregistrement DNS retourné.");
}
message = g_strdup_printf(
"Cible : %s — code de sortie : %d",
context->target_value,
tool_process_result_get_exit_status(process_result)
);
application_message_dialog_present_details(
main_window_get_window(application->main_window),
tool_process_result_is_success(process_result)
? APPLICATION_MESSAGE_DIALOG_INFORMATION
: APPLICATION_MESSAGE_DIALOG_WARNING,
"Résultat de la résolution DNS",
message,
details
);
g_clear_pointer(&stdout_bytes, g_bytes_unref);
g_clear_pointer(&stderr_bytes, g_bytes_unref);
g_free(stdout_text);
g_free(stderr_text);
g_free(details);
g_free(message);
}
/**
* @brief Prépare et démarre une résolution DNS avec dig.
*/
static void application_start_dns_lookup(
Application *application,
const char *target_value
)
{
ToolRegistry *tool_registry = NULL;
ToolTask *tool_task = NULL;
BackgroundTask *background_task = NULL;
ApplicationOsintActionContext *context = NULL;
const char *arguments[] = {"+noall", "+answer", target_value, NULL};
GError *error = NULL;
if (application == NULL || application->task_manager == NULL ||
application->tool_initializer == NULL || target_value == NULL ||
!osint_dns_query_is_valid_target(target_value))
{
if (application != NULL)
{
application_present_error(
application,
"Résolution DNS impossible",
"Le nom de domaine sélectionné est invalide."
);
}
return;
}
tool_registry = tool_initializer_get_registry(application->tool_initializer);
tool_task = tool_task_new(
tool_registry,
"dns.dig",
"Résolution DNS",
arguments,
NULL,
&error
);
if (tool_task == NULL)
{
application_present_error(
application,
"Résolution DNS impossible",
error != NULL ? error->message : "Impossible de préparer dig."
);
g_clear_error(&error);
return;
}
context = g_try_new0(ApplicationOsintActionContext, 1);
if (context != NULL)
{
context->application = application;
context->target_value = g_strdup(target_value);
}
if (context == NULL || context->target_value == NULL)
{
application_osint_action_context_free(context);
tool_task_free(tool_task);
application_present_error(
application,
"Résolution DNS impossible",
"Impossible de conserver le contexte de l'action."
);
return;
}
background_task = tool_task_get_background_task(tool_task);
if (!task_manager_add(application->task_manager, background_task, &error) ||
!tool_task_start(
tool_task,
application_on_dns_lookup_completed,
context,
application_osint_action_context_free,
&error
))
{
task_manager_remove(application->task_manager, background_task);
application_osint_action_context_free(context);
application_present_error(
application,
"Résolution DNS impossible",
error != NULL ? error->message : "Impossible de démarrer dig."
);
g_clear_error(&error);
tool_task_free(tool_task);
return;
}
tool_task_free(tool_task);
}
/**
* @brief Traite une action OSINT relayée par la fenêtre principale.
*/
static void application_on_osint_action_requested(
const char *action_identifier,
const char *target_value,
gpointer user_data
)
{
Application *application = user_data;
if (g_strcmp0(action_identifier, "dns-preview") == 0)
{
application_start_dns_lookup(application, target_value);
return;
}
application_present_error(
application,
"Action OSINT inconnue",
"Cette action n'est pas encore prise en charge."
);
}
/**
* @brief Affiche une erreur dans une fenêtre GTK.
*
@ -5102,6 +5386,12 @@ static void application_on_activate(
application
);
main_window_set_osint_action_callback(
application->main_window,
application_on_osint_action_requested,
application
);
main_window_set_new_investigation_callback(
application->main_window,
application_on_new_investigation_requested,

View file

@ -84,7 +84,7 @@ OsintActionCatalog *osint_action_catalog_new_defaults(void)
);
dns_action = osint_action_new(
"dns-preview", "Résolution DNS",
"Préfiguration de l'adaptateur DNS.",
"Exécute dig sur le nom de domaine sélectionné.",
OSINT_SELECTION_CONTEXT_KIND_ENTITY, "domain_name", "dns.dig", FALSE,
"L'outil requis n'a pas encore été vérifié."
);

View file

@ -0,0 +1,70 @@
/******************************************************************************
* @file osint_dns_query.c
* @brief Validation des cibles utilisées pour une résolution DNS OSINT.
******************************************************************************/
#include "models/osint_dns_query.h"
#include <string.h>
gboolean osint_dns_query_is_valid_target(
const char *target_value
)
{
gsize target_length = 0;
gsize label_length = 0;
if (target_value == NULL || target_value[0] == '\0')
{
return FALSE;
}
target_length = strlen(target_value);
if (target_length > 253U)
{
return FALSE;
}
for (gsize character_index = 0;
character_index < target_length;
character_index++)
{
const char character = target_value[character_index];
if (character == '.')
{
if (label_length == 0U)
{
return character_index == target_length - 1U &&
character_index > 0U;
}
if (target_value[character_index - 1U] == '-')
{
return FALSE;
}
if (character_index == target_length - 1U)
{
return TRUE;
}
label_length = 0U;
continue;
}
if (!(g_ascii_isalnum(character) || character == '-'))
{
return FALSE;
}
if ((label_length == 0U && character == '-') || label_length >= 63U)
{
return FALSE;
}
label_length++;
}
return label_length > 0U && target_value[target_length - 1U] != '-';
}

View file

@ -355,6 +355,93 @@ void application_message_dialog_present(
);
}
void application_message_dialog_present_details(
GtkWindow *parent_window,
ApplicationMessageDialogType message_type,
const char *title,
const char *message,
const char *details
)
{
GtkWindow *dialog_window = GTK_WINDOW(gtk_window_new());
GtkWidget *main_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 12);
GtkWidget *title_label = gtk_label_new(
application_message_dialog_get_safe_title(message_type, title)
);
GtkWidget *message_label = gtk_label_new(
application_message_dialog_get_safe_message(message)
);
GtkWidget *scrolled_window = gtk_scrolled_window_new();
GtkWidget *details_view = gtk_text_view_new();
GtkWidget *close_button = gtk_button_new_with_label("Fermer");
GtkTextBuffer *details_buffer = gtk_text_view_get_buffer(
GTK_TEXT_VIEW(details_view)
);
gtk_window_set_title(
dialog_window,
application_message_dialog_get_safe_title(message_type, title)
);
gtk_window_set_default_size(dialog_window, 760, 520);
gtk_window_set_modal(dialog_window, TRUE);
gtk_window_set_destroy_with_parent(dialog_window, TRUE);
if (parent_window != NULL)
{
gtk_window_set_transient_for(dialog_window, parent_window);
}
gtk_widget_set_margin_start(main_box, 20);
gtk_widget_set_margin_end(main_box, 20);
gtk_widget_set_margin_top(main_box, 20);
gtk_widget_set_margin_bottom(main_box, 20);
gtk_widget_set_halign(title_label, GTK_ALIGN_START);
gtk_label_set_xalign(GTK_LABEL(title_label), 0.0F);
gtk_widget_add_css_class(title_label, "title-2");
gtk_widget_set_halign(message_label, GTK_ALIGN_FILL);
gtk_label_set_xalign(GTK_LABEL(message_label), 0.0F);
gtk_label_set_wrap(GTK_LABEL(message_label), TRUE);
gtk_text_view_set_editable(GTK_TEXT_VIEW(details_view), FALSE);
gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(details_view), TRUE);
gtk_text_view_set_monospace(GTK_TEXT_VIEW(details_view), TRUE);
gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(details_view), GTK_WRAP_NONE);
gtk_text_buffer_set_text(
details_buffer,
details != NULL && details[0] != '\0'
? details
: APPLICATION_MESSAGE_DIALOG_DEFAULT_MESSAGE,
-1
);
gtk_scrolled_window_set_policy(
GTK_SCROLLED_WINDOW(scrolled_window),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC
);
gtk_widget_set_vexpand(scrolled_window, TRUE);
gtk_scrolled_window_set_child(
GTK_SCROLLED_WINDOW(scrolled_window),
details_view
);
gtk_widget_set_halign(close_button, GTK_ALIGN_END);
g_signal_connect(
close_button,
"clicked",
G_CALLBACK(application_message_dialog_on_close_clicked),
dialog_window
);
gtk_box_append(GTK_BOX(main_box), title_label);
gtk_box_append(GTK_BOX(main_box), message_label);
gtk_box_append(GTK_BOX(main_box), scrolled_window);
gtk_box_append(GTK_BOX(main_box), close_button);
gtk_window_set_child(dialog_window, main_box);
gtk_window_present(dialog_window);
}
/**
* @brief Libère le contexte associé à une fenêtre de confirmation.
*/

View file

@ -117,6 +117,12 @@ struct MainWindow
gpointer
add_relation_user_data;
MainWindowOsintActionCallback
osint_action_callback;
gpointer
osint_action_user_data;
MainWindowQuitCallback
quit_callback;
@ -125,6 +131,29 @@ struct MainWindow
};
/**
* @brief Relaie une action OSINT vers le contrôleur applicatif.
*/
static void main_window_on_osint_action_requested(
const char *action_identifier,
const char *target_value,
gpointer user_data
)
{
MainWindow *main_window = user_data;
if (main_window == NULL || main_window->osint_action_callback == NULL)
{
return;
}
main_window->osint_action_callback(
action_identifier,
target_value,
main_window->osint_action_user_data
);
}
/**
* @brief Ouvre dans le workspace l'entité choisie dans la sidebar.
*/
@ -745,6 +774,12 @@ MainWindow *main_window_new(
main_window
);
workspace_set_osint_action_callback(
main_window->workspace,
main_window_on_osint_action_requested,
main_window
);
workspace_widget = workspace_get_widget(
main_window->workspace
);
@ -1245,6 +1280,21 @@ void main_window_set_osint_tool_state(
);
}
void main_window_set_osint_action_callback(
MainWindow *main_window,
MainWindowOsintActionCallback callback,
gpointer user_data
)
{
if (main_window == NULL)
{
return;
}
main_window->osint_action_callback = callback;
main_window->osint_action_user_data = user_data;
}
void main_window_set_tree_selection_callback(
MainWindow *main_window,
InvestigationTreeViewSelectionCallback callback,

View file

@ -112,6 +112,12 @@ struct Workspace
gpointer
add_relation_user_data;
WorkspaceOsintActionCallback
osint_action_callback;
gpointer
osint_action_user_data;
GtkWidget *node_name_label;
GtkWidget *node_path_label;
GtkWidget *node_type_label;
@ -128,34 +134,62 @@ struct Workspace
};
/**
* @brief Confirme localement le déclenchement de l'action de démonstration.
* @brief Traite localement l'aperçu ou relaie une action OSINT exécutable.
*/
static void workspace_on_osint_demo_action_clicked(
static void workspace_on_osint_action_clicked(
GtkButton *button,
gpointer user_data
)
{
Workspace *workspace = user_data;
const char *action_label = g_object_get_data(
const char *action_identifier = g_object_get_data(
G_OBJECT(button),
"osint-action-label"
"osint-action-identifier"
);
char *status_text = NULL;
const char *target_value = NULL;
if (workspace == NULL || workspace->osint_tools_status_label == NULL)
{
return;
}
status_text = g_strdup_printf(
"%s : démonstration locale, aucun outil exécuté.",
action_label != NULL ? action_label : "Action OSINT"
if (g_strcmp0(action_identifier, "selection-preview") == 0)
{
gtk_label_set_text(
GTK_LABEL(workspace->osint_tools_status_label),
"Aperçu local : aucun outil externe exécuté."
);
return;
}
target_value = osint_selection_context_get_value(
workspace->osint_selection_context
);
if (workspace->osint_action_callback == NULL ||
action_identifier == NULL || target_value == NULL)
{
gtk_label_set_text(
GTK_LABEL(workspace->osint_tools_status_label),
"Impossible de transmettre cette action OSINT."
);
return;
}
gtk_label_set_text(
GTK_LABEL(workspace->osint_tools_status_label),
status_text != NULL ? status_text : "Aucun outil exécuté."
"Exécution lancée ; suivez sa progression dans les tâches."
);
gtk_popover_popdown(
GTK_POPOVER(workspace->osint_tools_popover)
);
workspace->osint_action_callback(
action_identifier,
target_value,
workspace->osint_action_user_data
);
g_free(status_text);
}
/**
@ -282,15 +316,16 @@ static void workspace_update_osint_tools_menu(
? osint_action_get_description(action)
: osint_action_get_unavailable_reason(action)
);
g_object_set_data(
g_object_set_data_full(
G_OBJECT(action_button),
"osint-action-label",
(gpointer) osint_action_get_label(action)
"osint-action-identifier",
g_strdup(osint_action_get_identifier(action)),
g_free
);
g_signal_connect(
action_button,
"clicked",
G_CALLBACK(workspace_on_osint_demo_action_clicked),
G_CALLBACK(workspace_on_osint_action_clicked),
workspace
);
gtk_box_append(
@ -2352,6 +2387,21 @@ void workspace_set_osint_tool_state(
);
}
void workspace_set_osint_action_callback(
Workspace *workspace,
WorkspaceOsintActionCallback callback,
gpointer user_data
)
{
if (workspace == NULL)
{
return;
}
workspace->osint_action_callback = callback;
workspace->osint_action_user_data = user_data;
}
void workspace_set_graph_loading(
Workspace *workspace
)

View file

@ -0,0 +1,35 @@
/******************************************************************************
* @file test_osint_dns_query.c
* @brief Tests de validation des cibles de résolution DNS OSINT.
******************************************************************************/
#include "models/osint_dns_query.h"
#include <glib.h>
static void test_valid_targets(void)
{
g_assert_true(osint_dns_query_is_valid_target("example.org"));
g_assert_true(osint_dns_query_is_valid_target("WWW.Example.ORG"));
g_assert_true(osint_dns_query_is_valid_target("sub-domain.example.org"));
g_assert_true(osint_dns_query_is_valid_target("example.org."));
}
static void test_invalid_targets(void)
{
g_assert_false(osint_dns_query_is_valid_target(NULL));
g_assert_false(osint_dns_query_is_valid_target(""));
g_assert_false(osint_dns_query_is_valid_target("-x.example.org"));
g_assert_false(osint_dns_query_is_valid_target("example..org"));
g_assert_false(osint_dns_query_is_valid_target("example.org +trace"));
g_assert_false(osint_dns_query_is_valid_target("example_.org"));
g_assert_false(osint_dns_query_is_valid_target("example-.org"));
}
int main(int argc, char **argv)
{
g_test_init(&argc, &argv, NULL);
g_test_add_func("/osint-dns-query/valid", test_valid_targets);
g_test_add_func("/osint-dns-query/invalid", test_invalid_targets);
return g_test_run();
}