📄 protocol.cpp
字号:
/* * Copyright (c) 1999-2002 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" {voidcse_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(config_t *config, void *value) {}voidcse_set_socket_cleanup(int socket, void *pool){}voidcse_kill_socket_cleanup(int socket, void *pool){}}voidcse_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);}intcse_lock(void *lock){ if (lock) { WaitForSingleObject(lock, INFINITE); } return 1;}voidcse_unlock(void *lock){ if (lock) { ReleaseMutex(lock); }}static voidcse_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 voidcse_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 intconnection_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 intcse_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 voidwrite_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 voidwrite_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 voidwrite_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 voidwrite_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]) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -