/*
 * copyfail_check.c
 *
 * Détection des préconditions de la vulnérabilité "Copy Fail"
 * (AF_ALG + splice)
 *
 * Compilation:
 *   gcc -O2 -Wall -o copyfail_check copyfail_check.c
 *
 * Usage:
 *   ./copyfail_check
 */

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <linux/if_alg.h>
#include <sys/types.h>

int main(void)
{
    int sockfd = -1, opfd = -1;
    struct sockaddr_alg sa;
    int pipefd[2];

    printf("[*] CopyFail detection tool\n");

    /* 1. Création socket AF_ALG */
    sockfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
    if (sockfd < 0) {
        perror("[-] AF_ALG non disponible");
        printf("[!] Système probablement NON vulnérable (ou feature désactivée)\n");
        return 0;
    }

    printf("[+] AF_ALG supporté\n");

    memset(&sa, 0, sizeof(sa));
    sa.salg_family = AF_ALG;
    strcpy((char *)sa.salg_type, "aead");
    strcpy((char *)sa.salg_name, "authencesn");

    if (bind(sockfd, (struct sockaddr *)&sa, sizeof(sa)) != 0) {
        perror("[-] bind authencesn échoué");
        printf("[!] Algo non disponible → vulnérabilité peu probable\n");
        close(sockfd);
        return 0;
    }

    printf("[+] authencesn disponible\n");

    opfd = accept(sockfd, NULL, 0);
    if (opfd < 0) {
        perror("[-] accept échoué");
        close(sockfd);
        return 1;
    }

    printf("[+] Socket opérationnel créé\n");

    /* 2. Création pipe pour splice */
    if (pipe(pipefd) != 0) {
        perror("[-] pipe");
        close(opfd);
        close(sockfd);
        return 1;
    }

    printf("[+] Pipe créé\n");

    /* 3. Écriture dans pipe */
    const char *data = "TESTDATA";
    if (write(pipefd[1], data, strlen(data)) < 0) {
        perror("[-] write pipe");
        return 1;
    }

    printf("[+] Données injectées dans pipe\n");

    /* 4. Test splice vers AF_ALG */
    ssize_t spliced = splice(pipefd[0], NULL, opfd, NULL, strlen(data), 0);

    if (spliced < 0) {
        perror("[-] splice échoué");
        printf("[!] splice vers AF_ALG non fonctionnel\n");
        printf("[+] Système probablement NON vulnérable\n");
    } else {
        printf("[+] splice fonctionne (%ld bytes)\n", spliced);
        printf("[!!!] SYSTÈME POTENTIELLEMENT VULNÉRABLE à Copy Fail\n");
    }

    close(pipefd[0]);
    close(pipefd[1]);
    close(opfd);
    close(sockfd);

    return 0;
}
