修正方法
CGI 应答头包括多行, 我们必须对其进行逐行分析, 并作出正确的应答.
下面是修改好的源程序, 即将原来的 82-136 (即相当下文#else, #endif内部分) 替换成如下代码:
#if 1 while(1) { int len; char * pnext = NULL; char * ptmp = NULL; /* not find HTTP header tailer */ if (NULL == (pnext=strchr(buf, '\n'))) /* has no '\n' */ break; /* the length of this line, * include '\n' */ len = pnext - buf + 1; if (!strncasecmp(buf, "Location: ", 10)) { /* got a location header */ /* not the first one * exchange this line to the first line */ if (buf != req->header_line) { if (NULL == (ptmp=(char *)malloc(len))) { log_error_time(); perror("malloc"); send_r_error(req); return 0; } /* move Status: to line header */ memcpy(ptmp, buf, len); memmove(req->header_line+len, req->header_line, buf-req->header_line); memcpy(req->header_line, ptmp, len); free(ptmp); } /* force pointer header */ buf = req->header_line; #ifdef FASCIST_LOGGING log_error_time(); fprintf(stderr, "%s:%d - found Location header \"%s\"\n", __FILE__, __LINE__, buf + 10); #endif if (buf[10] == '/') { /* virtual path */ log_error_time(); fprintf(stderr, "server does not support internal redirection: " \ "\"%s\"\n", buf + 10); send_r_bad_request(req); /* * We (I, Jon) have declined to support absolute-path parsing * because I see it as a major security hole. * Location: /etc/passwd or Location: /etc/shadow is not funny. * * Also, the below code is borked. * request_uri could contain /cgi-bin/bob/extra_path */ /* strcpy(req->request_uri, buf + 10); return internal_redirect(req); */ } else { /* URL */ char *c2; c2 = strchr(buf + 10, '\n'); /* c2 cannot ever equal NULL here because we already have found one */ --c2; while (*c2 == '\r') --c2; ++c2; /* c2 now points to a '\r' or the '\n' */ *c2++ = '\0'; /* end header */ /* first next header, or is at req->header_end */ while ((*c2 == '\n' || *c2 == '\r') && c2 < req->header_end) ++c2; if (c2 == req->header_end) send_r_moved_temp(req, buf + 10, ""); else send_r_moved_temp(req, buf + 10, c2); } req->status = DONE; return 1; } else if (!strncasecmp(buf, "Status: ", 8)) { /* not the first one * exchange this line to the first line */ if (buf != req->header_line) { if (NULL == (ptmp=(char *)malloc(len))) { log_error_time(); perror("malloc"); send_r_error(req); return 0; } /* move Status: to line header */ memcpy(ptmp, buf, len); memmove(req->header_line+len, req->header_line, buf-req->header_line); memcpy(req->header_line, ptmp, len); free(ptmp); } req->header_line--; memcpy(req->header_line, "HTTP/1.0 ", 9); return 1; } /* pointer to next line */ buf = pnext + 1; /* reach the end of HTTP header */ if ('\0' == buf[0] || '\n' == buf[0] || '\r' == buf[0]) break; } if (1) { /* always done */ #else if (!strncasecmp(buf, "Status: ", 8)) { req->header_line--; memcpy(req->header_line, "HTTP/1.0 ", 9); } else if (!strncasecmp(buf, "Location: ", 10)) { /* got a location header */ #ifdef FASCIST_LOGGING log_error_time(); fprintf(stderr, "%s:%d - found Location header \"%s\"\n", __FILE__, __LINE__, buf + 10); #endif if (buf[10] == '/') { /* virtual path */ log_error_time(); fprintf(stderr, "server does not support internal redirection: " \ "\"%s\"\n", buf + 10); send_r_bad_request(req); /* * We (I, Jon) have declined to support absolute-path parsing * because I see it as a major security hole. * Location: /etc/passwd or Location: /etc/shadow is not funny. * * Also, the below code is borked. * request_uri could contain /cgi-bin/bob/extra_path */ /* strcpy(req->request_uri, buf + 10); return internal_redirect(req); */ } else { /* URL */ char *c2; c2 = strchr(buf + 10, '\n'); /* c2 cannot ever equal NULL here because we already have found one */ --c2; while (*c2 == '\r') --c2; ++c2; /* c2 now points to a '\r' or the '\n' */ *c2++ = '\0'; /* end header */ /* first next header, or is at req->header_end */ while ((*c2 == '\n' || *c2 == '\r') && c2 < req->header_end) ++c2; if (c2 == req->header_end) send_r_moved_temp(req, buf + 10, ""); else send_r_moved_temp(req, buf + 10, c2); } req->status = DONE; return 1; } else { /* not location and not status */ #endif |