вторник, 1 февраля 2011 г.

Integrity

В качестве темы для курсовой работы я выбрал "проверку целостности информации". Программе в качестве аргументов передаются директория и файл. Она работает в двух режимах, регулируемых ключами. В первом программа вычисляет хэш-коды для всех файлов директории и записывает их в заданный файл, во втором — открывает заданный файл на чтение и сверяет записанные в нём хэш-коды с заново вычисленными для файлов директории. Программу следует в будущем доработать — она слишком жестко действует. При добавлении, удалении, либо изменении любого файла она сообщает пользователю о нарушении целостности и завершает работу. Нужно будет прикрутить к ней запись в файл имен файлов и проверку по ним, чтобы сообщалось подробно о каждом изменении. Когда писал, не мог найти нужную функцию. А преподаватель подсказал потом её название — strtoken.
В остальном же программа работает довольно мудро.Тщательно проверяет входные данные, сообщает об ошибках в ходе работы, не вычисляет хэш-код для заданного файла, файлов "." и "..". Хэш-код вычисляется с помощью исходных кодов функции MD5 (взято с сайта нашей кафедры). Вот. Вроде всё.
Код:
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <sys/types.h>
#include "md5.h"
#define GENERATE 1
#define CHECK 0
#define ERR_OPENING 4
#define ERR_ARG 5

int usage(char *msg);

int main(int argc, char *argv[]) {
        DIR *dp;
        struct dirent *dirlist;
        MD5_CTX mdContext;
        FILE *filep;
        FILE *fp;
        char dir[220];                      
        char file[220];                    
        char chkfile[256];  
        char hash[34];      
        char part_hash[2];    
        int mode = 2;       
        int bytes, i;
        unsigned char data[1024];
        
        if (argc < 6) {
                return usage("Too few arguments.\n");
        } else if (argc > 6) {
                return usage("Too many arguments.\n");
        }
        
        for (i = 1; i < argc; i++) {
                if (*argv[i]++ == '-') {
                        switch(*(argv[i])) {
                        case 'g':
                                if (mode == CHECK) {
                                        return usage("You already set option -c\n");
                                }
                                mode = GENERATE;
                                printf("Generate integrity mode activated.\n");
                        break;
                        case 'c':
                                if (mode == GENERATE) {
                                        return usage("You already set option -g\n");
                                }
                                        mode = CHECK;
                                printf("Check integrity mode activated.\n");
                        break;
                        case 'd':
                                if (argc == i + 1) {
                                        return usage("You don't specified directory.\n");
                                }
                                strcpy(dir, argv[i + 1]);
                                strcat(dir, dir[strlen(dir) - 1] == '/' ? "" : "/");
                        break;
                        case 'f':
                                if (argc == i + 1) {
                                        return usage("You don't specified file.\n");
                                }
                                strcpy(file, argv[i + 1]);
                        break;
                        default:
                                return usage("Error! Unknown argument.\n");
                        break;
                        }
                }
        }
        
        filep = fopen(file, mode == GENERATE ? "wt" : "rt");
                
        if (filep == NULL) {
                printf("Couldn't open file specified file!\n");
                return ERR_OPENING;
        }
        
        dp = opendir(dir);
        
        if (dp != NULL) {
                while ((dirlist = readdir(dp)) != 0) {
                        if (!strcmp(dirlist-> d_name, ".") || !strcmp(dirlist-> d_name, "..")) {
                                continue;
                        }
                        
                        if (!strcmp(dirlist-> d_name, file)) {
                                continue;
                        }
                        
                        strcpy(chkfile, "");
                        strcat(chkfile, dir);
                        strcat(chkfile, dirlist-> d_name);
                        //printf("Checked file: %s\n", chkfile);
                        fp = fopen(chkfile, "rb");
                        strcpy(chkfile, "");
                        
                        if (fp == NULL) {
                                printf("Error opening file %s\n", dir);
                                return ERR_OPENING;
                        }
                        
                        MD5Init (&mdContext);
                        while ((bytes = fread(data, 1, 1024, fp)) != 0) {
                                MD5Update (&mdContext, data, bytes);
                        }
                        
                        MD5Final (&mdContext);
                        fclose(fp);
                        
                        for (i = 0; i < 16; i++) {
                                sprintf(part_hash, "%02x", mdContext.digest[i]);
                                strcat(chkfile, part_hash);
                        }
                        strcat(chkfile, "\n");
                        if (mode == GENERATE) {
                                fprintf(filep, "%s", chkfile);
                        } else {
                                fgets(hash, 34, filep);
                                //printf("Comparing %s and %s\n", chkfile, hash);
                                if (strcmp(chkfile, hash)) {
                                        printf("File integrity corrupt detected!\n");
                                        return 0;
                                }
                        }
                }
                
                closedir(dp);
        } else {
                printf("Couldn't open specified directory\n");
                return ERR_OPENING;
        }
        
        fclose(filep);
        printf("%s", mode == GENERATE ? "File integrity successful generated.\n"
                                                                  :        "File integrity is not corrupted.\n");
        return 0;
}

int usage(char *msg) {
        printf("Argument error.\n");
        printf("%s", msg);
        printf("Usage: integrity\t[-g -d directory -f file] to generate integrity file\n");        
        printf("\t\t\t[-c -d directory -f file] to check directory integrity\n");
        return ERR_ARG;
}

Запуск:
jightuse1@debian:~/code/2701/course_work$ make
gcc -Wall -o integrity integrity.c md5.c
jightuse1@debian:~/code/2701/course_work$ ./integrity -g -d . -f test
Generate integrity mode activated.
File integrity successful generated.
jightuse1@debian:~/code/2701/course_work$ cat test 
8801e49c277245731de1651cc92580ac
69be7b8c2356971993b5c571bc26d03a
2128dcde0c3cceeaaa74568200383828
91248fe33a48d557eb77a21b08506b15
13e18c11875db296a1b7e21fb0b9f23e
52f6c5476ae41bad2fa6af21f0d286b0
3d436d38da78eef0cda531f5b0e63afb
47b950cc631fa34d7af94b5bffa5ee9d
jightuse1@debian:~/code/2701/course_work$ ./integrity -c -d . -f test
Check integrity mode activated.
File integrity is not corrupted.
jightuse1@debian:~/code/2701/course_work$ 

1 комментарий:

Анонимный комментирует...

Интересная программа. Полезна в области безопасности, чтобы проверять на изменения системные бинарники.