Read message protocol socket c
Portability  

First this program could be made more portable. There are 2 portability issues here

If it was ported to a system that did not define end of line as "\r\n" this program might not work. This problem could be solved by including the proper header files or using

#define EndOfLine "\r\n"


and using 

    ptr = strstr(buffer, EndOfLine)


The second portability issue is the use of strdup(). It is not implemented on all systems. This Stackoverflow question discusses the use of strdup.

Consistency in Coding Style  

There is one place in the code where the indentation is inconsistent:

    if (buffer)
    {
        size = strlen(buffer) + strlen(data) + 1;
        if (!(buffer = realloc(buffer, size)))
            return (NULL);
        strcat(buffer, data);
    }
    else {
        if (!(buffer = strdup(data)))
            return (NULL);
    }


The use of braces "{" and "}" should be consistent through the entire program.
Everywhere except in this code the brace starts on a new line. 

It would be very nice if the headers were included for compilation and
testing. Without the headers or the calling functions it is difficult to
compile or test this code.

Complexity  

It might be better if the function read_message(char *data) was separated
into multiple functions to reduce the complexity. All of the functions might
be more readable if there was some virtical spacing between blocks of code.

Possible Bug  

The function parse_message(char *buffer) always returns NULL, in your
testing did the function handle_message() always get called?