/[monit]/monit/protocols/http.c
ViewVC logotype

Diff of /monit/protocols/http.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.33 by martinp, Tue Sep 28 14:24:01 2004 UTC revision 1.34 by hauk, Sun Dec 12 23:45:09 2004 UTC
# Line 43  Line 43 
43  #include <netinet/in.h>  #include <netinet/in.h>
44  #endif  #endif
45    
46  #ifdef HAVE_ARPA_INET_H  #include "md5.h"
47  #include <arpa/inet.h>  #include "sha.h"
 #endif  
   
 #include "../md5.h"  
 #include "../sha.h"  
48  #include "protocol.h"  #include "protocol.h"
49    
50    
# Line 58  Line 54 
54    
55  /* Private prototypes */  /* Private prototypes */
56  static int check_request(Socket_T s);  static int check_request(Socket_T s);
57  static char *get_host_header(Socket_T s, char * host);  static int check_request_checksum(Socket_T s, char *checksum, int hashtype);
 static int check_request_checksum(Socket_T s, char *checksum, int);  
58    
59    
60  /**  /**
# Line 78  static int check_request_checksum(Socket Line 73  static int check_request_checksum(Socket
73   *   *
74   *  @author Jan-Henrik Haukeland, <hauk@tildeslash.com>   *  @author Jan-Henrik Haukeland, <hauk@tildeslash.com>
75   *  @author Martin Pala, <martinp@tildeslash.com>   *  @author Martin Pala, <martinp@tildeslash.com>
  *  
76   *  @version \$Id$   *  @version \$Id$
  *  
77   *  @file   *  @file
78   */   */
79  int check_http(Socket_T s) {  int check_http(Socket_T s) {
80    
81    char host[STRLEN];    char host[STRLEN];
82    char *request= NULL;    char *request= NULL;
   char *request_checksum= NULL;  
   int  request_hashtype= 0;  
83    
84    ASSERT(s);    ASSERT(s);
85        
   if(socket_get_Port(s)) {  
     request= ((Port_T)(socket_get_Port(s)))->request;  
     request_checksum= ((Port_T)(socket_get_Port(s)))->request_checksum;  
     request_hashtype= ((Port_T)(socket_get_Port(s)))->request_hashtype;  
   }  
   
86    request= request?request:"/";    request= request?request:"/";
87    
88    if(socket_print(s, "GET %s HTTP/1.1\r\n"    if(socket_print(s,
89                      "GET %s HTTP/1.1\r\n"
90                    "Host: %s\r\n"                    "Host: %s\r\n"
91                    "Accept: */*\r\n"                    "Accept: */*\r\n"
92                    "User-Agent: %s/%s\r\n"                    "User-Agent: %s/%s\r\n"
93                    "Connection: close\r\n\r\n",                    "Connection: close\r\n\r\n",
94                    request, get_host_header(s, host), prog, VERSION) < 0) {                    request, Util_getHTTPHostHeader(s, host,STRLEN),
95                      prog, VERSION) < 0) {
96      log("HTTP: error sending data -- %s\n", STRERROR);      log("HTTP: error sending data -- %s\n", STRERROR);
97      return FALSE;      return FALSE;
98    }    }
99    
   if(request_checksum) {  
     return check_request_checksum(s, request_checksum, request_hashtype);  
   }  
   
100    return check_request(s);    return check_request(s);
101        
102  }  }
# Line 123  int check_http(Socket_T s) { Line 106  int check_http(Socket_T s) {
106    
107    
108  /**  /**
  * @return a "hostname:port" or a void string if host  
  * equals LOCALHOST or if it is an IP address  
  */  
 static char *get_host_header(Socket_T s, char *hostbuf) {  
   
   if(! strcmp(LOCALHOST, socket_get_remote_host(s)) ||  
      inet_aton(socket_get_remote_host(s), NULL)) {  
   
     *hostbuf= 0;  
   
   } else {  
   
     snprintf(hostbuf, STRLEN, "%s:%d",  
              socket_get_remote_host(s),  
              socket_get_remote_port(s));  
       
   }  
   
   return hostbuf;  
   
 }  
   
   
 /**  
109   * Check that the server returns a valid HTTP response   * Check that the server returns a valid HTTP response
110   * @param s A socket   * @param s A socket
111   * @return TRUE if the response is valid otherwise FALSE   * @return TRUE if the response is valid otherwise FALSE
# Line 156  static int check_request(Socket_T s) { Line 115  static int check_request(Socket_T s) {
115    int n;    int n;
116    int status;    int status;
117    char buf[STRLEN];    char buf[STRLEN];
118    char msg[STRLEN];    Port_T P= (Port_T)socket_get_Port(s);
119    char proto[STRLEN];    
   
120    if(! socket_readln(s, buf, sizeof(buf))) {    if(! socket_readln(s, buf, sizeof(buf))) {
121      log("HTTP: error receiving data -- %s\n", STRERROR);      log("HTTP: error receiving data -- %s\n", STRERROR);
122      return FALSE;      return FALSE;
123    }    }
124      Util_chomp(buf, STRLEN);
125    chomp(buf, STRLEN);    n= sscanf(buf, "%*s %d", &status);
126      if(n!=1 || (status >= 400)) {
   /* RATS: ignore */ /* chomp does zero termination */  
   n= sscanf(buf, "%s %d %s", proto, &status, msg);  
   if(n!=3 || (status >= 400)) {  
127      log("HTTP error: %s\n", buf);      log("HTTP error: %s\n", buf);
128      return FALSE;      return FALSE;
129    }    }
130      
131      if(P && P->request_checksum) {
132        return check_request_checksum(s, P->request_checksum, P->request_hashtype);
133      }
134      
135    return TRUE;    return TRUE;
136        
137  }  }
# Line 184  static int check_request(Socket_T s) { Line 143  static int check_request(Socket_T s) {
143   * the response does not contain the Content-Length header, the   * the response does not contain the Content-Length header, the
144   * checksum is not tested and this method returns TRUE.   * checksum is not tested and this method returns TRUE.
145   * @param s A socket   * @param s A socket
146   * @param checksum expected checksum   * @param checksum Request digest to test
147     * @param hashtype The digest type
148   * @return TRUE if the respons is valid and the checksum match,   * @return TRUE if the respons is valid and the checksum match,
149   * otherwise FALSE   * otherwise FALSE
150   */   */
# Line 194  static int check_request_checksum(Socket Line 154  static int check_request_checksum(Socket
154    char line[STRLEN];    char line[STRLEN];
155    long content_length= 0;    long content_length= 0;
156    
   if(! check_request(s))  
       return FALSE;  
   
157    while(NULL != socket_readln(s, line, STRLEN)) {    while(NULL != socket_readln(s, line, STRLEN)) {
158      if(starts_with(line, "\r\n") || starts_with(line, "\n"))      if(Util_startsWith(line, "\r\n") || Util_startsWith(line, "\n"))
159          break;          break;
160      if(starts_with(line, "Content-Length")) {      if(Util_startsWith(line, "Content-Length")) {
       /* RATS: ignore */ /* socket_readln does zero termination */        
161        if(1 != sscanf(line, "%*s%*[: ]%ld", &content_length)) {        if(1 != sscanf(line, "%*s%*[: ]%ld", &content_length)) {
162          chomp(line, STRLEN);          Util_chomp(line, STRLEN);
163          log("HTTP error: parsing Content-Length response header '%s'\n", line);          log("HTTP error: parsing Content-Length response header '%s'\n", line);
164          return FALSE;          return FALSE;
165        }        }
# Line 211  static int check_request_checksum(Socket Line 167  static int check_request_checksum(Socket
167    }    }
168        
169    if(! content_length) {    if(! content_length) {
       
170      DEBUG("HTTP warning: Response does not contain Content-Length\n");      DEBUG("HTTP warning: Response does not contain Content-Length\n");
       
171    } else {    } else {
172            
173      int n;      int n;
# Line 226  static int check_request_checksum(Socket Line 180  static int check_request_checksum(Socket
180    
181      switch (hashtype) {      switch (hashtype) {
182      case HASH_MD5:      case HASH_MD5:
183      {        {
184        struct md5_ctx ctx;          struct md5_ctx ctx;
185        md5_init_ctx(&ctx);          md5_init_ctx(&ctx);
186        while(content_length > 0) {          while(content_length > 0) {
187          size= content_length>READ_SIZE?READ_SIZE:content_length;            size= content_length>READ_SIZE?READ_SIZE:content_length;
188          n= socket_read(s, buf, size);            n= socket_read(s, buf, size);
189          if(n<0) break;            if(n<0) break;
190          md5_process_bytes(buf, n, &ctx);            md5_process_bytes(buf, n, &ctx);
191          content_length -= n;            content_length -= n;
192            }
193            md5_finish_ctx(&ctx, hash);
194            keylength=16; /* Raw key bytes not string chars! */
195            break;
196        }        }
       md5_finish_ctx(&ctx, hash);  
       keylength=16; /* Raw key bytes not string chars! */  
       break;  
     }  
197      case HASH_SHA1:      case HASH_SHA1:
198      {        {
199        struct sha_ctx ctx;          struct sha_ctx ctx;
200        sha_init_ctx(&ctx);          sha_init_ctx(&ctx);
201        while(content_length > 0) {          while(content_length > 0) {
202          size= content_length>READ_SIZE?READ_SIZE:content_length;            size= content_length>READ_SIZE?READ_SIZE:content_length;
203          n= socket_read(s, buf, size);            n= socket_read(s, buf, size);
204          if(n<0) break;            if(n<0) break;
205          sha_process_bytes(buf, n, &ctx);            sha_process_bytes(buf, n, &ctx);
206          content_length -= n;            content_length -= n;
207            }
208            sha_finish_ctx(&ctx, hash);
209            keylength=20; /* Raw key bytes not string chars! */
210            break;
211        }        }
       sha_finish_ctx(&ctx, hash);  
       keylength=20; /* Raw key bytes not string chars! */  
       break;  
     }  
212      default:      default:
213          DEBUG("HTTP warning: Unknown hash type\n");        DEBUG("HTTP warning: Unknown hash type\n");
214          return FALSE;        return FALSE;
215      }      }
       
216      r= result;      r= result;
217      for(i= 0; i < keylength; ++i)      for(i= 0; i < keylength; ++i) {
218          r+= snprintf(r, STRLEN-(r-result) ,"%02x", hash[i]);        r+= snprintf(r, STRLEN-(r-result) ,"%02x", hash[i]);
219            }
220      if(strncasecmp(result, checksum, keylength*2) != 0) {      if(strncasecmp(result, checksum, keylength*2) != 0) {
221        DEBUG("HTTP warning: Document checksum mismatch\n");        DEBUG("HTTP warning: Document checksum mismatch\n");
222        return FALSE;        return FALSE;
223      } else {      } else {
224        DEBUG("HTTP: Succeeded testing document checksum\n");        DEBUG("HTTP: Succeeded testing document checksum\n");
225      }      }
       
226    }    }
227        
228    return TRUE;    return TRUE;
229      
230  }  }

Legend:
Removed from v.1.33  
changed lines
  Added in v.1.34

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26