235 |
*/ |
*/ |
236 |
void out_print(HttpResponse res, const char *format, ...) { |
void out_print(HttpResponse res, const char *format, ...) { |
237 |
|
|
238 |
if ( format ) { |
if(format) { |
239 |
|
|
240 |
int n= 0; |
int n= 0; |
241 |
ssize_t need= 0; |
ssize_t need= 0; |
272 |
} |
} |
273 |
|
|
274 |
/* Check for possible buffersize overflow and abort if detected */ |
/* Check for possible buffersize overflow and abort if detected */ |
275 |
if ( (float)((float)(sizeof(char)*(res->bufsize + RES_STRLEN + n + 1)) |
if((float)((float)(sizeof(char)*(res->bufsize + RES_STRLEN + n + 1)) |
276 |
> SSIZE_MAX) ) { |
> SSIZE_MAX)) { |
277 |
|
|
278 |
log("out_print: Possible http response buffer overflow detected. " |
log("out_print: Possible http response buffer overflow detected. " |
279 |
"aborting \n"); |
"aborting \n"); |
284 |
have= res->bufsize - res->bufused; |
have= res->bufsize - res->bufused; |
285 |
need= sizeof(char)*( n + 1); |
need= sizeof(char)*( n + 1); |
286 |
|
|
287 |
if ( have <= need ) { |
if(have <= need) { |
288 |
|
|
289 |
/* Geometrical expand the outputbuffer size */ |
/* Geometrical expand the outputbuffer size */ |
290 |
res->outputbuffer= |
res->outputbuffer= |
292 |
|
|
293 |
res->bufsize+= (need + RES_STRLEN); |
res->bufsize+= (need + RES_STRLEN); |
294 |
|
|
295 |
if ( !res->bufused ) { |
if(!res->bufused) { |
296 |
|
|
297 |
memset(res->outputbuffer, 0, res->bufsize); |
memset(res->outputbuffer, 0, res->bufsize); |
298 |
|
|
321 |
*/ |
*/ |
322 |
void destroy_wrapper(RequestWrapper w) { |
void destroy_wrapper(RequestWrapper w) { |
323 |
|
|
324 |
if ( w && w->inetaddr ) { |
if(w && w->inetaddr) { |
325 |
|
|
326 |
free(w->inetaddr->remote_host); |
free(w->inetaddr->remote_host); |
327 |
free(w->inetaddr->local_host); |
free(w->inetaddr->local_host); |
329 |
|
|
330 |
} |
} |
331 |
|
|
332 |
if ( Run.httpdssl ) { |
if(Run.httpdssl) { |
333 |
|
|
334 |
close_accepted_ssl_socket(mySSLServerConnection, w->ssl); |
close_accepted_ssl_socket(mySSLServerConnection, w->ssl); |
335 |
|
|
423 |
|
|
424 |
HttpHeader p; |
HttpHeader p; |
425 |
|
|
426 |
for ( p= req->headers; p; p= p->next) { |
for(p= req->headers; p; p= p->next) { |
427 |
|
|
428 |
if ( !strcasecmp(p->name, name) ) { |
if(!strcasecmp(p->name, name)) { |
429 |
|
|
430 |
return xstrdup(p->value); |
return xstrdup(p->value); |
431 |
|
|
448 |
|
|
449 |
HttpParameter p; |
HttpParameter p; |
450 |
|
|
451 |
for ( p= req->params; p; p= p->next) { |
for(p= req->params; p; p= p->next) { |
452 |
|
|
453 |
if ( !strcasecmp(p->name, name) ) { |
if(!strcasecmp(p->name, name)) { |
454 |
|
|
455 |
return xstrdup(p->value); |
return xstrdup(p->value); |
456 |
|
|
478 |
|
|
479 |
*buf=0; |
*buf=0; |
480 |
|
|
481 |
for ( p= res->headers; p; p= p->next) { |
for(p= res->headers; p; p= p->next) { |
482 |
|
|
483 |
b+= snprintf(b, STRLEN-(b-buf),"%s: %s\r\n", p->name, p->value); |
b+= snprintf(b, STRLEN-(b-buf),"%s: %s\r\n", p->name, p->value); |
484 |
|
|
597 |
volatile HttpResponse res= create_HttpResponse(w); |
volatile HttpResponse res= create_HttpResponse(w); |
598 |
volatile HttpRequest req= create_HttpRequest(w); |
volatile HttpRequest req= create_HttpRequest(w); |
599 |
|
|
600 |
if ( res && req ) { |
if(res && req) { |
601 |
|
|
602 |
if ( is_authenticated(req, res) ) { |
if(is_authenticated(req, res)) { |
603 |
|
|
604 |
if ( !strcmp(req->method, METHOD_GET) ) { |
if(!strcmp(req->method, METHOD_GET)) { |
605 |
|
|
606 |
Impl.doGet(req, res); |
Impl.doGet(req, res); |
607 |
|
|
608 |
} |
} |
609 |
else if ( !strcmp(req->method, METHOD_POST) ) { |
else if(!strcmp(req->method, METHOD_POST)) { |
610 |
|
|
611 |
Impl.doPost(req, res); |
Impl.doPost(req, res); |
612 |
|
|
619 |
|
|
620 |
} |
} |
621 |
|
|
622 |
if ( Run.httpdssl ) { |
if(Run.httpdssl) { |
623 |
|
|
624 |
send_response(res); |
send_response(res); |
625 |
|
|
626 |
} else { |
} else { |
627 |
|
|
628 |
if ( check_socket(w->socket) ) { |
if(check_socket(w->socket)) { |
629 |
|
|
630 |
send_response(res); |
send_response(res); |
631 |
} |
} |
649 |
|
|
650 |
time(&now); |
time(&now); |
651 |
|
|
652 |
if ( !strftime(date, STRLEN, DATEFMT, gmtime(&now)) ) { |
if(!strftime(date, STRLEN, DATEFMT, gmtime(&now))) { |
653 |
|
|
654 |
memset(date, 0, STRLEN); |
memset(date, 0, STRLEN); |
655 |
|
|
679 |
*/ |
*/ |
680 |
static void send_response(HttpResponse res) { |
static void send_response(HttpResponse res) { |
681 |
|
|
682 |
if ( !res->is_committed ) { |
if(!res->is_committed) { |
683 |
char *date= get_date(); |
char *date= get_date(); |
684 |
char *server= get_server(); |
char *server= get_server(); |
685 |
char *headers= get_headers(res); |
char *headers= get_headers(res); |
686 |
int len= res->bufused?strlen((char *) res->outputbuffer):0; |
int len= res->bufused?strlen((char *) res->outputbuffer):0; |
687 |
|
|
688 |
if ( Run.httpdssl ) { |
if(Run.httpdssl) { |
689 |
|
|
690 |
printf_ssl_socket(res->ssl, "%s %d %s\r\n", res->protocol, res->status, |
printf_ssl_socket(res->ssl, "%s %d %s\r\n", res->protocol, res->status, |
691 |
res->status_msg); |
res->status_msg); |
693 |
printf_ssl_socket(res->ssl, "Server: %s\r\n", server); |
printf_ssl_socket(res->ssl, "Server: %s\r\n", server); |
694 |
printf_ssl_socket(res->ssl, "Content-length: %d\r\n", len); |
printf_ssl_socket(res->ssl, "Content-length: %d\r\n", len); |
695 |
printf_ssl_socket(res->ssl, "Connection: close\r\n"); |
printf_ssl_socket(res->ssl, "Connection: close\r\n"); |
696 |
if ( headers ) printf_ssl_socket(res->ssl, "%s", headers); |
if(headers)printf_ssl_socket(res->ssl, "%s", headers); |
697 |
printf_ssl_socket(res->ssl, "\r\n\r\n"); |
printf_ssl_socket(res->ssl, "\r\n\r\n"); |
698 |
|
|
699 |
if ( res->bufused ) send_ssl_socket(res->ssl, res->outputbuffer, len); |
if(res->bufused)send_ssl_socket(res->ssl, res->outputbuffer, len); |
700 |
|
|
701 |
} else { |
} else { |
702 |
|
|
708 |
fprintf(out, "Server: %s\r\n", server); |
fprintf(out, "Server: %s\r\n", server); |
709 |
fprintf(out, "Content-length: %d\r\n", len); |
fprintf(out, "Content-length: %d\r\n", len); |
710 |
fprintf(out, "Connection: close\r\n"); |
fprintf(out, "Connection: close\r\n"); |
711 |
if ( headers ) fprintf(out, "%s", headers); |
if(headers)fprintf(out, "%s", headers); |
712 |
fprintf(out, "\r\n\r\n"); |
fprintf(out, "\r\n\r\n"); |
713 |
|
|
714 |
if ( res->bufused ) fprintf(out, "%s", res->outputbuffer); |
if(res->bufused)fprintf(out, "%s", res->outputbuffer); |
715 |
|
|
716 |
} |
} |
717 |
|
|
739 |
HttpRequest req; |
HttpRequest req; |
740 |
FILE *in= NULL; |
FILE *in= NULL; |
741 |
|
|
742 |
if ( Run.httpdssl ) { |
if(Run.httpdssl) { |
743 |
|
|
744 |
if ( gets_ssl_socket(W->ssl, line, sizeof(line)) == NULL ) { |
if(gets_ssl_socket(W->ssl, line, sizeof(line)) == NULL) { |
745 |
|
|
746 |
internal_error_ssl(W->ssl, SC_BAD_REQUEST, "No request found"); |
internal_error_ssl(W->ssl, SC_BAD_REQUEST, "No request found"); |
747 |
return NULL; |
return NULL; |
748 |
|
|
749 |
} |
} |
750 |
|
|
751 |
if ( sscanf(line, "%s %s HTTP/%3[1.0]", method, url, protocol) != 3 ) { |
if(sscanf(line, "%s %s HTTP/%3[1.0]", method, url, protocol) != 3) { |
752 |
|
|
753 |
internal_error_ssl(W->ssl, SC_BAD_REQUEST, "Cannot parse request"); |
internal_error_ssl(W->ssl, SC_BAD_REQUEST, "Cannot parse request"); |
754 |
return NULL; |
return NULL; |
759 |
|
|
760 |
in= fdopen(dup(W->socket), "r"); |
in= fdopen(dup(W->socket), "r"); |
761 |
|
|
762 |
if ( in == NULL ) { |
if(in == NULL) { |
763 |
|
|
764 |
internal_error(W->socket, SC_INTERNAL_SERVER_ERROR, |
internal_error(W->socket, SC_INTERNAL_SERVER_ERROR, |
765 |
"Cannot create inputstream"); |
"Cannot create inputstream"); |
767 |
|
|
768 |
} |
} |
769 |
|
|
770 |
if ( fgets(line, sizeof(line), in) == NULL ) { |
if(fgets(line, sizeof(line), in) == NULL) { |
771 |
|
|
772 |
internal_error(W->socket, SC_BAD_REQUEST, "No request found"); |
internal_error(W->socket, SC_BAD_REQUEST, "No request found"); |
773 |
fclose(in); |
fclose(in); |
775 |
|
|
776 |
} |
} |
777 |
|
|
778 |
if ( sscanf(line, "%s %s HTTP/%3[1.0]", method, url, protocol) != 3 ) { |
if(sscanf(line, "%s %s HTTP/%3[1.0]", method, url, protocol) != 3) { |
779 |
|
|
780 |
internal_error(W->socket, SC_BAD_REQUEST, "Cannot parse request"); |
internal_error(W->socket, SC_BAD_REQUEST, "Cannot parse request"); |
781 |
fclose(in); |
fclose(in); |
792 |
req->protocol= xstrdup(protocol); |
req->protocol= xstrdup(protocol); |
793 |
req->ssl= W->ssl; |
req->ssl= W->ssl; |
794 |
|
|
795 |
if (! Run.httpdssl ) { |
if (! Run.httpdssl) { |
796 |
|
|
797 |
req->inputstream= in; |
req->inputstream= in; |
798 |
|
|
806 |
|
|
807 |
create_headers(req); |
create_headers(req); |
808 |
|
|
809 |
if ( !create_parameters(req) ) { |
if(!create_parameters(req)) { |
810 |
|
|
811 |
if ( Run.httpdssl ) { |
if(Run.httpdssl) { |
812 |
|
|
813 |
internal_error_ssl(W->ssl, SC_BAD_REQUEST, |
internal_error_ssl(W->ssl, SC_BAD_REQUEST, |
814 |
"Cannot parse Request parameters"); |
"Cannot parse Request parameters"); |
839 |
HttpResponse res; |
HttpResponse res; |
840 |
FILE *out= NULL; |
FILE *out= NULL; |
841 |
|
|
842 |
if ( ! Run.httpdssl ) { |
if(! Run.httpdssl) { |
843 |
|
|
844 |
out = fdopen(dup(W->socket), "w"); |
out = fdopen(dup(W->socket), "w"); |
845 |
|
|
846 |
if ( out == NULL ) { |
if(out == NULL) { |
847 |
|
|
848 |
internal_error(W->socket, SC_INTERNAL_SERVER_ERROR, |
internal_error(W->socket, SC_INTERNAL_SERVER_ERROR, |
849 |
"Cannot create outputstream"); |
"Cannot create outputstream"); |
879 |
HttpHeader p; |
HttpHeader p; |
880 |
HttpHeader header; |
HttpHeader header; |
881 |
|
|
882 |
while ( 1 ) { |
while(1) { |
883 |
|
|
884 |
if ( Run.httpdssl ) { |
if(Run.httpdssl) { |
885 |
|
|
886 |
if (NULL == gets_ssl_socket(req->ssl, line, sizeof(line))) { |
if (NULL == gets_ssl_socket(req->ssl, line, sizeof(line))) { |
887 |
|
|
899 |
|
|
900 |
} |
} |
901 |
|
|
902 |
if ( !strcmp(line, "\r\n") || !strcmp(line, "\n") ) |
if(!strcmp(line, "\r\n") || !strcmp(line, "\n")) |
903 |
break; |
break; |
904 |
|
|
905 |
if( NULL != (value= strchr(line, ':')) ) { |
if( NULL != (value= strchr(line, ':'))) { |
906 |
|
|
907 |
NEW(header); |
NEW(header); |
908 |
*value++= '\0'; |
*value++= '\0'; |
912 |
header->name= xstrdup(line); |
header->name= xstrdup(line); |
913 |
header->value= xstrdup(value); |
header->value= xstrdup(value); |
914 |
|
|
915 |
if ( req->headers ) { |
if(req->headers) { |
916 |
|
|
917 |
for ( p= req->headers; p->next; p= p->next) |
for(p= req->headers; p->next; p= p->next) |
918 |
/* Empty */; |
/* Empty */; |
919 |
p->next= header; |
p->next= header; |
920 |
|
|
940 |
char *query_string= NULL; |
char *query_string= NULL; |
941 |
int alloc= FALSE; |
int alloc= FALSE; |
942 |
|
|
943 |
if ( !strcmp(req->method, METHOD_POST) ) { |
if(!strcmp(req->method, METHOD_POST)) { |
944 |
|
|
945 |
int len; char *l= get_header(req, "Content-Length"); |
int len; char *l= get_header(req, "Content-Length"); |
946 |
|
|
947 |
if ( l && (len= atoi(l)) ) { |
if(l && (len= atoi(l))) { |
948 |
|
|
949 |
query_string= xmalloc(sizeof(char) * (len + 1)); |
query_string= xmalloc(sizeof(char) * (len + 1)); |
950 |
|
|
951 |
if ( fgets(query_string, (sizeof(char)*(len+1)), |
if(fgets(query_string, (sizeof(char)*(len+1)), |
952 |
req->inputstream) == NULL ) { |
req->inputstream) == NULL) { |
953 |
|
|
954 |
free(query_string); |
free(query_string); |
955 |
return FALSE; |
return FALSE; |
960 |
|
|
961 |
} |
} |
962 |
|
|
963 |
} else if ( !strcmp(req->method, METHOD_GET) ) { |
} else if(!strcmp(req->method, METHOD_GET)) { |
964 |
|
|
965 |
char *p; |
char *p; |
966 |
|
|
967 |
if( NULL != (p= strchr(req->url, '?')) ) { |
if( NULL != (p= strchr(req->url, '?'))) { |
968 |
|
|
969 |
*p++= '\0'; |
*p++= '\0'; |
970 |
query_string= p; |
query_string= p; |
973 |
|
|
974 |
} |
} |
975 |
|
|
976 |
if ( query_string ) { |
if(query_string) { |
977 |
|
|
978 |
char *p; |
char *p; |
979 |
|
|
980 |
if( NULL != (p= strchr(query_string, '/')) ) { |
if( NULL != (p= strchr(query_string, '/'))) { |
981 |
|
|
982 |
*p++= '\0'; |
*p++= '\0'; |
983 |
req->pathinfo= p; |
req->pathinfo= p; |
988 |
|
|
989 |
} |
} |
990 |
|
|
991 |
if ( alloc ) free(query_string); |
if(alloc)free(query_string); |
992 |
|
|
993 |
return TRUE; |
return TRUE; |
994 |
|
|
1004 |
*/ |
*/ |
1005 |
static void reset_response(HttpResponse res) { |
static void reset_response(HttpResponse res) { |
1006 |
|
|
1007 |
if ( res->headers ) destroy_entry(res->headers); |
if(res->headers)destroy_entry(res->headers); |
1008 |
memset(res->outputbuffer, 0, res->bufsize); |
memset(res->outputbuffer, 0, res->bufsize); |
1009 |
res->headers= NULL; /* Release Pragma */ |
res->headers= NULL; /* Release Pragma */ |
1010 |
|
|
1027 |
*/ |
*/ |
1028 |
static void destroy_HttpRequest(HttpRequest req) { |
static void destroy_HttpRequest(HttpRequest req) { |
1029 |
|
|
1030 |
if ( req ) { |
if(req) { |
1031 |
|
|
1032 |
if ( req->inputstream ) fclose(req->inputstream); |
if(req->inputstream)fclose(req->inputstream); |
1033 |
free(req->method); |
free(req->method); |
1034 |
free(req->url); /* req->pathinfo is freed with url */ |
free(req->url); /* req->pathinfo is freed with url */ |
1035 |
free(req->protocol); |
free(req->protocol); |
1036 |
if ( req->headers ) destroy_entry(req->headers); |
if(req->headers)destroy_entry(req->headers); |
1037 |
if ( req->params ) destroy_entry(req->params); |
if(req->params)destroy_entry(req->params); |
1038 |
free(req); |
free(req); |
1039 |
|
|
1040 |
} |
} |
1047 |
*/ |
*/ |
1048 |
static void destroy_HttpResponse(HttpResponse res) { |
static void destroy_HttpResponse(HttpResponse res) { |
1049 |
|
|
1050 |
if ( res ) { |
if(res) { |
1051 |
|
|
1052 |
if ( res->outputstream ) fclose(res->outputstream); |
if(res->outputstream)fclose(res->outputstream); |
1053 |
free(res->protocol); |
free(res->protocol); |
1054 |
free(res->outputbuffer); |
free(res->outputbuffer); |
1055 |
if ( res->headers) destroy_entry(res->headers); |
if(res->headers) destroy_entry(res->headers); |
1056 |
free(res); |
free(res); |
1057 |
|
|
1058 |
} |
} |
1068 |
|
|
1069 |
struct entry *h= p; |
struct entry *h= p; |
1070 |
|
|
1071 |
if ( h->next ) { |
if(h->next) { |
1072 |
|
|
1073 |
destroy_entry(h->next); |
destroy_entry(h->next); |
1074 |
|
|
1089 |
*/ |
*/ |
1090 |
static int is_authenticated(HttpRequest req, HttpResponse res) { |
static int is_authenticated(HttpRequest req, HttpResponse res) { |
1091 |
|
|
1092 |
if ( Run.Auth.defined ) { |
if(Run.Auth.defined) { |
1093 |
|
|
1094 |
if ( ! basic_authenticate(req) ) { |
if(! basic_authenticate(req)) { |
1095 |
|
|
1096 |
send_error(res, SC_UNAUTHORIZED, |
send_error(res, SC_UNAUTHORIZED, |
1097 |
"You are <b>not</b> authorized to access <i>monit</i>. " |
"You are <b>not</b> authorized to access <i>monit</i>. " |
1120 |
int rv= FALSE; |
int rv= FALSE; |
1121 |
char *credentials= get_header(req, "Authorization"); |
char *credentials= get_header(req, "Authorization"); |
1122 |
|
|
1123 |
if ( credentials ) { |
if(credentials) { |
1124 |
|
|
1125 |
unsigned char *cr= xcalloc(sizeof(unsigned char), strlen(credentials)+1); |
unsigned char *cr= xcalloc(sizeof(unsigned char), strlen(credentials)+1); |
1126 |
|
|
1127 |
if ( decode_base64(cr, strchr(credentials, ' ')) ) { |
if(decode_base64(cr, strchr(credentials, ' '))) { |
1128 |
|
|
1129 |
char buf[STRLEN]; |
char buf[STRLEN]; |
1130 |
|
|
1131 |
snprintf(buf, STRLEN, "%s:%s", Run.Auth.uname, Run.Auth.passwd); |
snprintf(buf, STRLEN, "%s:%s", Run.Auth.uname, Run.Auth.passwd); |
1132 |
|
|
1133 |
if ( !strncmp((char *) cr, buf, strlen(buf)) ) { |
if(!strncmp((char *) cr, buf, strlen(buf))) { |
|
|
|
|
rv= TRUE; |
|
|
|
|
|
} |
|
1134 |
|
|
1135 |
} |
rv= TRUE; |
1136 |
|
|
1137 |
|
} else { |
1138 |
|
|
1139 |
|
log("Warning: Client '%s' supplied wrong credentials" |
1140 |
|
" accessing monit httpd\n", req->inetaddr->remote_host); |
1141 |
|
|
1142 |
|
} |
1143 |
|
|
1144 |
|
} |
1145 |
|
|
1146 |
free(cr); |
free(cr); |
1147 |
free(credentials); |
free(credentials); |
1148 |
|
|
1224 |
HttpParameter head= NULL; |
HttpParameter head= NULL; |
1225 |
int controller= 1000; |
int controller= 1000; |
1226 |
|
|
1227 |
while ( query_string[0] && controller-- ) { |
while(query_string[0] && controller--) { |
1228 |
|
|
1229 |
HttpParameter p; |
HttpParameter p; |
1230 |
NEW(p); |
NEW(p); |