Search code examples
clinuxfilemd5sumstrncmp

Compare md5 after tftp transfer


Because I use the tftp command to transfer an important file, I would like to compare md5 in order to valid the transfer. Note : The file has been already transfered in the the example below

int main(int argc, char *argv[])
{
    FILE *input_md5_fd;
    FILE *md5_fd;
    size_t md5_length;
    size_t nbr_items;
    char *input_md5 = NULL; 
    char *file_md5 = NULL;  
    int ret;

    chdir("/tmp");

    system("tftp -g -r INPUT_MD5 192.168.0.1");
    input_md5_fd = fopen("INPUT_MD5", "r");
    if (input_md5_fd != NULL)
    {   
       fprintf(stdout,"MD5 transfered\n");
       fseek(input_md5_fd,0L,SEEK_END);
       md5_length = ftell(md5_fd);
       input_md5 = malloc(md5_length + 1);
       fseek(input_md5_fd,0L,SEEK_SET);
       nbr_items = fread(input_md5, 1, md5_length, input_md5_fd);
       input_md5[nbr_items] = 0;
       fprintf(stdout, "length = %lu B\n",md5_length);
       fprintf(stdout, "contains %s\n", input_md5);
       fclose(input_md5_fd);    
    }
    else
    {
       return -1;
    }

    system("md5sum IMPORTANT_FILE > /tmp/file_md5.txt");

    md5_fd = fopen("file_md5.txt", "r");
    if (md5_fd != NULL)
    {   
       file_md5 = malloc(md5_length +1);
       rewind(md5_fd);
       nbr_items = fread(file_md5, 1, md5_length, md5_fd);
       file_md5[nbr_items] = 0;
       fprintf(stdout, "contains %s\n", file_md5);
       fclose(md5_fd);  
    }
    else
    {    
       return -1;
    }

    printf("file_md5 = %s\n", file_md5);
    printf("input_md5 = %s\n", input_md5);  
    ret = strncmp(file_md5, input_md5, md5_length);
    printf("ret = %d\n", ret);  

    free(input_md5);
    free(file_md5);

}

Output :

MD5 transfered
length = 33 B
contains a95ef51ec6b1b06f61c97559ddf4868f

contains a95ef51ec6b1b06f61c97559ddf4868f
file_md5 = a95ef51ec6b1b06f61c97559ddf4868f 
input_md5 = a95ef51ec6b1b06f61c97559ddf4868f

ret = 22

The input files contain :

# cat /tmp/INPUT_MD5 
a95ef51ec6b1b06f61c97559ddf4868f

 # cat /tmp/file_md5 
a95ef51ec6b1b06f61c97559ddf4868f  XXX_XX-XXXX-XX-DD.DDD-DD.DDD.DD.bin

X being char and D decimal values.

Why ret is not equal to 0 ? In addition, I don't know from where 34 comes from

EDIT : CODE HAS BEEN UPDATED, problem came from md5_length definition. long type has been exchanged to size_t


Solution

  • You risk printing out and comparing garbage since you don't ensure the strings are nul terminated.

    You need to do

     fread(file_md5, 1, md5_length, md5_fd);
     file_md5[md5_length] = 0;
    

    And similar for input_md5. Or to do it properly, use the return value of fread() to add the nul terminator in the proper place, check if fread() fails, Check how much it returned.

    If you also place your debug output inside quotes, it'll also be easier to spot unwanted whitespace or unprintable characters:

    fprintf(stdout, "contains '%s'\n", input_md5);