📄 protocol.cpp
字号:
/*
* Copyright (c) 1999-2003 Caucho Technology. All rights reserved.
*
* Caucho Technology permits redistribution, modification and use
* of this file in source and binary form ("the Software") under the
* Caucho Public License ("the License"). In particular, the following
* conditions must be met:
*
* 1. Each copy or derived work of the Software must preserve the copyright
* notice and this notice unmodified.
*
* 2. Redistributions of the Software in source or binary form must include
* an unmodified copy of the License, normally in a plain ASCII text
*
* 3. The names "Resin" or "Caucho" are trademarks of Caucho Technology and
* may not be used to endorse products derived from this software.
* "Resin" or "Caucho" may not appear in the names of products derived
* from this software.
*
* 4. Caucho Technology requests that attribution be given to Resin
* in any manner possible. We suggest using the "Resin Powered"
* button or creating a "powered by Resin(tm)" link to
* http://www.caucho.com for each page served by Resin.
*
* This Software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
* IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
* OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
*
* CAUCHO TECHNOLOGY AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES
* SUFFERED BY LICENSEE OR ANY THIRD PARTY AS A RESULT OF USING OR
* DISTRIBUTING SOFTWARE. IN NO EVENT WILL Caucho OR ITS LICENSORS BE LIABLE
* FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
* CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
* REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
* INABILITY TO USE SOFTWARE, EVEN IF HE HAS BEEN ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGES.
*
* @author Scott Ferguson
*/
/*
* SSL client certificate contributed by Ahn Le
*/
/*
* Anh: We have to define _WIN32_WINNT as 0x0400 to have access to
* the Crypto API. By definning as this way, the dll can only work
* with Windows 95 OEM Service Release 2 or above.
*/
#define _WIN32_WINNT 0x0400
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <windows.h>
#include "httpext.h"
#include <errno.h>
#include <ctype.h>
#include <string.h>
#define ISAPI_SCRIPT "/scripts/isapi_srun.dll"
extern "C" {
#include "../common/cse.h"
#include "../common/version.h"
}
extern "C" {
void
cse_error(config_t *config, char *fmt, ...)
{
va_list arg;
char buf[1024];
va_start(arg, fmt);
if (fmt)
vsprintf(buf, fmt, arg);
else
buf[0] = 0;
va_end(arg);
if (buf[0]) {
config->error = strdup(buf);
config->disable_caucho_status = 0;
}
#ifdef DEBUG
{
FILE *file;
file = fopen("/temp/isapi.log", "a+b");
fprintf(file, "%s\n", buf);
fclose(file);
}
#endif
}
void *
cse_malloc(int size)
{
return malloc(size);
}
void cse_free(void *value) {}
void
cse_set_socket_cleanup(int socket, void *pool)
{
}
void
cse_kill_socket_cleanup(int socket, void *pool)
{
}
}
void
cse_log(char *fmt, ...)
{
#ifdef DEBUG
va_list arg;
FILE *file;
file = fopen("/temp/isapi.log", "a+");
va_start(arg, fmt);
if (file)
vfprintf(file, fmt, arg);
va_end(arg);
fclose(file);
#endif
}
void *
cse_create_lock(config_t *config)
{
return CreateMutex(0, false, 0);
}
int
cse_lock(void *lock)
{
if (lock) {
WaitForSingleObject(lock, INFINITE);
}
return 1;
}
void
cse_unlock(void *lock)
{
if (lock) {
ReleaseMutex(lock);
}
}
static void
cse_printf(EXTENSION_CONTROL_BLOCK *r, char *fmt, ...)
{
va_list args;
char buf[4096];
unsigned long len;
va_start(args, fmt);
vsprintf(buf, fmt, args);
va_end(args);
len = strlen(buf);
r->WriteClient(r->ConnID, buf, &len, 0);
}
static void
cse_pad(EXTENSION_CONTROL_BLOCK *r)
{
cse_printf(r, "\n\n\n\n");
cse_printf(r, "<!--\n");
cse_printf(r, " - Unfortunately, Microsoft has added a clever new\n");
cse_printf(r, " - \"feature\" to Internet Explorer. If the text in\n");
cse_printf(r, " - an error's message is \"too small\", specifically\n");
cse_printf(r, " - less than 512 bytes, Internet Explorer returns\n");
cse_printf(r, " - its own error message. Yes, you can turn that\n");
cse_printf(r, " - off, but *surprise* it's pretty tricky to find\n");
cse_printf(r, " - buried as a switch called \"smart error\n");
cse_printf(r, " - messages\" That means, of course, that many of\n");
cse_printf(r, " - Resin's error messages are censored by default.\n");
cse_printf(r, " - And, of course, you'll be shocked to learn that\n");
cse_printf(r, " - IIS always returns error messages that are long\n");
cse_printf(r, " - enough to make Internet Explorer happy. The\n");
cse_printf(r, " - workaround is pretty simple: pad the error\n");
cse_printf(r, " - message with a big comment to push it over the\n");
cse_printf(r, " - five hundred and twelve byte minimum. Of course,\n");
cse_printf(r, " - that's exactly what you're reading right now.\n");
cse_printf(r, " -->\n");
}
static int
connection_error(config_t *config, EXTENSION_CONTROL_BLOCK *r)
{
// r->content_type = "text/html";
// ap_send_http_header(r);
char *hostname = 0;
int port = 0;
if (config->error_page) {
DWORD size = strlen(config->error_page);
DWORD type = 0;
cse_printf(r, "HTTP/1.0 302 Redirect\r\n");
cse_printf(r, "Location: %s\r\n", config->error_page);
cse_printf(r, "\r\n");
return 1;
}
cse_printf(r, "HTTP/1.0 503 Server Error\n\n");
cse_printf(r, "<html><body bgcolor='white'>\n");
cse_printf(r, "<h1>Can't contact Servlet Runner at %s:%d\n",
(hostname ? hostname : "localhost"),
(port ? port : 6802));
cse_printf(r, "</h1>\n");
cse_printf(r, "</body></html>\n");
cse_pad(r);
return 1;
}
static int
cse_error(config_t *config, EXTENSION_CONTROL_BLOCK *r)
{
// r->content_type = "text/html";
// ap_send_http_header(r);
if (config->error_page) {
DWORD size = strlen(config->error_page);
DWORD type = 0;
cse_printf(r, "HTTP/1.0 302 Redirect\n");
cse_printf(r, "Location: %s\n", config->error_page);
cse_printf(r, "\n");
return 1;
}
cse_printf(r, "HTTP/1.0 500 Server Error\n\n");
cse_printf(r, "<html><body bgcolor='white'>\n");
cse_printf(r, "<h1>Can't access URL</h1>\n");
if (config->error)
cse_printf(r, "<pre>%s</pre>", config->error);
cse_printf(r, "</body></html>\n");
cse_pad(r);
return 1;
}
static void
write_var(stream_t *s, EXTENSION_CONTROL_BLOCK *r, char *name, int code)
{
char buf[8192];
char *ptr;
unsigned long size = sizeof(buf);
buf[0] = 0;
if (r->GetServerVariable(r->ConnID, name, buf, &size) && size > 0 && buf[0]) {
buf[size] = 0;
for (ptr = buf; isspace(*ptr); ptr++) {
}
cse_write_string(s, code, ptr);
}
}
static void
write_header(stream_t *s, EXTENSION_CONTROL_BLOCK *r, char *name)
{
char buf[8192];
unsigned long size = sizeof(buf);
char *ptr = buf;
buf[0] = 0;
if (r->GetServerVariable(r->ConnID, name, buf, &size) && size > 0 && buf[0]) {
for (; size > 0 && buf[size - 1] <= ' '; size--) {
}
buf[size] = 0;
cse_write_string(s, CSE_HEADER, name);
for (ptr = buf; isspace(*ptr); ptr++) {
}
cse_write_string(s, CSE_VALUE, ptr);
}
}
/**
* Writes SSL data, including client certificates.
*/
static void
write_ssl(stream_t *s, EXTENSION_CONTROL_BLOCK *r)
{
char buf[8192];
unsigned long size = sizeof(buf);
if (! r->GetServerVariable(r->ConnID, "SERVER_PORT_SECURE", buf, &size) ||
size <= 0 || buf[0] != '1')
return;
cse_write_string(s, CSE_IS_SECURE, "");
// Anh : Add SSL connection informations
cse_write_string(s, CSE_HEADER, "HTTPS");
cse_write_string(s, CSE_VALUE, "on");
write_header(s, r, "HTTPS_KEYSIZE");
write_header(s, r, "HTTPS_SECRETKEYSIZE");
// Anh : Check client certificate existence
size = sizeof(buf);
buf[0] = 0;
if (! r->GetServerVariable(r->ConnID, "CERT_FLAGS", buf, &size) ||
size <= 0 || buf[0] != '1')
return;
// There is a client certificate
char cert_buf[8192]={0};
CERT_CONTEXT_EX cert;
cert.cbAllocated = sizeof(cert_buf);
cert.CertContext.pbCertEncoded = (BYTE*) cert_buf;
cert.CertContext.cbCertEncoded = 0;
DWORD dwSize = sizeof(cert);
if (r->ServerSupportFunction(r->ConnID,
(DWORD)HSE_REQ_GET_CERT_INFO_EX,
(LPVOID)&cert, &dwSize,NULL) != FALSE)
{
// cert now contains valid client certificate information
LOG(("\ndwCertEncodingType = %d (%d) %ld\n",
cert.CertContext.dwCertEncodingType & X509_ASN_ENCODING ,
cert.CertContext.cbCertEncoded,
cert.dwCertificateFlags));
cse_write_packet(s, CSE_CLIENT_CERT,
(char *)cert.CertContext.pbCertEncoded,
cert.CertContext.cbCertEncoded);
write_header(s, r, "CERT_ISSUER");
write_header(s, r, "CERT_SERIALNUMBER");
write_header(s, r, "CERT_SUBJECT");
write_header(s, r, "CERT_SERVER_ISSUER");
write_header(s, r, "CERT_SERVER_SUBJECT");
}
}
static int
write_env(stream_t *s, EXTENSION_CONTROL_BLOCK *r)
{
int isHttp11 = 0;
char protocol[8192];
char rawUri[8192];
char *uri = rawUri;
char buf[1024];
unsigned long size = sizeof(protocol);
if (r->GetServerVariable(r->ConnID, "SERVER_PROTOCOL", protocol, &size) && size > 0) {
protocol[size] = 0;
isHttp11 = ! strcmp(protocol, "HTTP/1.1");
}
size = sizeof(rawUri);
if (r->GetServerVariable(r->ConnID, "PATH_INFO", uri, &size) && size > 0) {
uri[size] = 0;
if (! strncmp(uri, ISAPI_SCRIPT, sizeof(ISAPI_SCRIPT) - 1))
uri += sizeof(ISAPI_SCRIPT) - 1;
}
else
uri[size] = 0;
write_var(s, r, "SERVER_PROTOCOL", CSE_PROTOCOL);
write_var(s, r, "REQUEST_METHOD", CSE_METHOD);
cse_write_string(s, CSE_URI, uri);
// write_var(s, r, "PATH_TRANSLATED", CSE_PATH_TRANSLATED);
write_var(s, r, "QUERY_STRING", CSE_QUERY_STRING);
write_var(s, r, "SERVER_NAME", CSE_SERVER_NAME);
write_var(s, r, "SERVER_PORT", CSE_SERVER_PORT);
write_var(s, r, "REMOTE_HOST", CSE_REMOTE_HOST);
write_var(s, r, "REMOTE_ADDR", CSE_REMOTE_ADDR);
write_var(s, r, "REMOTE_USER", CSE_REMOTE_USER);
write_var(s, r, "AUTH_TYPE", CSE_AUTH_TYPE);
// write_var(s, r, "CONTENT_TYPE", CSE_CONTENT_TYPE);
// write_var(s, r, "CONTENT_LENGTH", CSE_CONTENT_LENGTH);
// cse_write_string(s, CSE_DOCROOT, ap_document_root(r));
sprintf(buf, "%d", s->srun->session);
cse_write_string(s, CSE_SESSION_GROUP, buf);
cse_write_string(s, CSE_SERVER_TYPE, "ISAPI");
size = sizeof(buf);
write_ssl(s, r);
return isHttp11;
}
static void
write_headers(stream_t *s, EXTENSION_CONTROL_BLOCK *r)
{
char buf[16384];
unsigned long i = 0;
unsigned long len = sizeof(buf);
if (! r->GetServerVariable(r->ConnID, "ALL_RAW", buf, &len))
return;
while (i < len) {
for (; i < len && isspace(buf[i]); i++) {
}
int head = i;
int tail;
for (; i < len && buf[i] != ':'; i++) {
}
buf[i] = 0;
for (i++; i < len && buf[i] == ' ' && buf[i] != '\n'; i++) {
}
tail = i;
for (; i < len && (buf[i] != '\n' || isspace(buf[i+1])); i++) {
if (isspace(buf[i]))
buf[i] = ' ';
}
if (buf[i - 1] == ' ')
buf[i - 1] = 0;
buf[i++] = 0;
if (buf[head]) {
cse_write_string(s, CSE_HEADER, buf + head);
cse_write_string(s, CSE_VALUE, buf + tail);
}
}
}
static int
cse_write_response(stream_t *s, unsigned long len, EXTENSION_CONTROL_BLOCK *r)
{
while (len > 0) {
unsigned long sublen;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -