⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jk_isapi_plugin.c

📁 精通tomcat书籍原代码,希望大家共同学习
💻 C
📖 第 1 页 / 共 4 页
字号:
/*
 * Find the first occurrence of find in s.
 */
static char *stristr(const char *s, const char *find)
{
    char c, sc;
    size_t len;

    if ((c = tolower((unsigned char)(*find++))) != 0) {
        len = strlen(find);
        do {
            do {
                if ((sc = tolower((unsigned char)(*s++))) == 0)
                    return (NULL);
            } while (sc != c);
        } while (strnicmp(s, find, len) != 0);
        s--;
    }
    return ((char *)s);
}

static int uri_is_web_inf(const char *uri)
{
    if (stristr(uri, "web-inf")) {
        return JK_TRUE;
    }
    if (stristr(uri, "meta-inf")) {
        return JK_TRUE;
    }

    return JK_FALSE;
}

static void write_error_response(PHTTP_FILTER_CONTEXT pfc, char *status,
                                 char *msg)
{
    DWORD len = (DWORD)strlen(msg);

    /* reject !!! */
    pfc->AddResponseHeaders(pfc, CONTENT_TYPE, 0);
    pfc->ServerSupportFunction(pfc,
                               SF_REQ_SEND_RESPONSE_HEADER,
                               status, 0, 0);
    pfc->WriteClient(pfc, msg, &len, 0);
}


static int JK_METHOD start_response(jk_ws_service_t *s,
                                    int status,
                                    const char *reason,
                                    const char *const *header_names,
                                    const char *const *header_values,
                                    unsigned int num_of_headers)
{
    static char crlf[3] = { (char)13, (char)10, '\0' };

    JK_TRACE_ENTER(logger);
    if (status < 100 || status > 1000) {
        jk_log(logger, JK_LOG_ERROR,
               "invalid status %d",
               status);
        JK_TRACE_EXIT(logger);
        return JK_FALSE;
    }

    if (s && s->ws_private) {
        isapi_private_data_t *p = s->ws_private;
        if (!p->request_started) {
            size_t len_of_status;
            char *status_str;
            char *headers_str;

            p->request_started = JK_TRUE;

            /*
             * Create the status line
             */
            if (!reason) {
                reason = status_reason(status);
            }
            status_str = (char *)_alloca((6 + strlen(reason)) * sizeof(char));
            sprintf(status_str, "%d %s", status, reason);
            len_of_status = strlen(status_str);

            /*
             * Create response headers string
             */
            if (num_of_headers) {
                size_t i, len_of_headers;
                for (i = 0, len_of_headers = 0; i < num_of_headers; i++) {
                    len_of_headers += strlen(header_names[i]);
                    len_of_headers += strlen(header_values[i]);
                    len_of_headers += 4;        /* extra for colon, space and crlf */
                }

                len_of_headers += 3;    /* crlf and terminating null char */
                headers_str = (char *)_alloca(len_of_headers * sizeof(char));
                headers_str[0] = '\0';

                for (i = 0; i < num_of_headers; i++) {
                    strcat(headers_str, header_names[i]);
                    strcat(headers_str, ": ");
                    strcat(headers_str, header_values[i]);
                    strcat(headers_str, crlf);
                }
                strcat(headers_str, crlf);
            }
            else {
                headers_str = crlf;
            }

            if (!p->lpEcb->ServerSupportFunction(p->lpEcb->ConnID,
                                                 HSE_REQ_SEND_RESPONSE_HEADER,
                                                 status_str,
                                                 (LPDWORD) &len_of_status,
                                                 (LPDWORD) headers_str)) {
                jk_log(logger, JK_LOG_ERROR,
                       "HSE_REQ_SEND_RESPONSE_HEADER failed");
                JK_TRACE_EXIT(logger);
                return JK_FALSE;
            }
        }
        JK_TRACE_EXIT(logger);
        return JK_TRUE;

    }

    JK_LOG_NULL_PARAMS(logger);
    JK_TRACE_EXIT(logger);
    return JK_FALSE;
}

static int JK_METHOD read(jk_ws_service_t *s,
                          void *b, unsigned int l, unsigned int *a)
{
    JK_TRACE_ENTER(logger);

    if (s && s->ws_private && b && a) {
        isapi_private_data_t *p = s->ws_private;

        *a = 0;
        if (l) {
            char *buf = b;
            DWORD already_read = p->lpEcb->cbAvailable - p->bytes_read_so_far;

            if (already_read >= l) {
                memcpy(buf, p->lpEcb->lpbData + p->bytes_read_so_far, l);
                p->bytes_read_so_far += l;
                *a = l;
            }
            else {
                /*
                 * Try to copy what we already have
                 */
                if (already_read > 0) {
                    memcpy(buf, p->lpEcb->lpbData + p->bytes_read_so_far,
                           already_read);
                    buf += already_read;
                    l -= already_read;
                    p->bytes_read_so_far = p->lpEcb->cbAvailable;

                    *a = already_read;
                }

                /*
                 * Now try to read from the client ...
                 */
                if (p->lpEcb->ReadClient(p->lpEcb->ConnID, buf, (LPDWORD)&l)) {
                    *a += l;
                }
                else {
                    jk_log(logger, JK_LOG_ERROR,
                           "ReadClient failed with %08x", GetLastError());
                    JK_TRACE_EXIT(logger);
                    return JK_FALSE;
                }
            }
        }
        JK_TRACE_EXIT(logger);
        return JK_TRUE;
    }

    JK_LOG_NULL_PARAMS(logger);
    JK_TRACE_EXIT(logger);
    return JK_FALSE;
}

static int JK_METHOD write(jk_ws_service_t *s, const void *b, unsigned int l)
{
    JK_TRACE_ENTER(logger);

    if (s && s->ws_private && b) {
        isapi_private_data_t *p = s->ws_private;

        if (l) {
            unsigned int written = 0;
            char *buf = (char *)b;

            if (!p->request_started) {
                start_response(s, 200, NULL, NULL, NULL, 0);
            }

            while (written < l) {
                DWORD try_to_write = l - written;
                if (!p->lpEcb->WriteClient(p->lpEcb->ConnID,
                                           buf + written, &try_to_write, 0)) {
                    jk_log(logger, JK_LOG_ERROR,
                           "WriteClient failed with %08x", GetLastError());
                    JK_TRACE_EXIT(logger);
                    return JK_FALSE;
                }
                written += try_to_write;
            }
        }

        JK_TRACE_EXIT(logger);
        return JK_TRUE;

    }

    JK_LOG_NULL_PARAMS(logger);
    JK_TRACE_EXIT(logger);
    return JK_FALSE;
}

BOOL WINAPI GetFilterVersion(PHTTP_FILTER_VERSION pVer)
{
    ULONG http_filter_revision = HTTP_FILTER_REVISION;

    pVer->dwFilterVersion = pVer->dwServerFilterVersion;

    if (pVer->dwFilterVersion > http_filter_revision) {
        pVer->dwFilterVersion = http_filter_revision;
    }

    pVer->dwFlags = SF_NOTIFY_ORDER_HIGH |
                    SF_NOTIFY_SECURE_PORT |
                    SF_NOTIFY_NONSECURE_PORT |
                    SF_NOTIFY_PREPROC_HEADERS |
                    SF_NOTIFY_LOG |
                    SF_NOTIFY_AUTH_COMPLETE;

    strcpy(pVer->lpszFilterDesc, VERSION_STRING);

    if (!is_inited) {
        return initialize_extension();
    }

    return TRUE;
}

DWORD WINAPI HttpFilterProc(PHTTP_FILTER_CONTEXT pfc,
                            DWORD dwNotificationType, LPVOID pvNotification)
{
    /* Initialise jk */
    if (is_inited && !is_mapread) {
        char serverName[MAX_SERVERNAME];
        DWORD dwLen = sizeof(serverName);

        if (pfc->GetServerVariable(pfc, SERVER_NAME, serverName, &dwLen)) {
            if (dwLen > 0)
                serverName[dwLen - 1] = '\0';
            if (init_jk(serverName))
                is_mapread = JK_TRUE;
        }
        /* If we can't read the map we become dormant */
        if (!is_mapread)
            is_inited = JK_FALSE;
    }

    if (is_inited && (iis5 < 0)) {
        char serverSoftware[256];
        DWORD dwLen = sizeof(serverSoftware);
        iis5 = 0;
        if (pfc->
            GetServerVariable(pfc, SERVER_SOFTWARE, serverSoftware, &dwLen)) {
            iis5 = (atof(serverSoftware + 14) >= 5.0);
            if (iis5) {
                jk_log(logger, JK_LOG_DEBUG, "Detected IIS >= 5.0");
            }
            else {
                jk_log(logger, JK_LOG_DEBUG, "Detected IIS < 5.0");
            }
        }
    }

    if (is_inited &&
        (((SF_NOTIFY_PREPROC_HEADERS == dwNotificationType) && !iis5) ||
         ((SF_NOTIFY_AUTH_COMPLETE == dwNotificationType) && iis5)
        )
        ) {
        char uri[INTERNET_MAX_URL_LENGTH];
        char snuri[INTERNET_MAX_URL_LENGTH] = "/";
        char Host[INTERNET_MAX_URL_LENGTH] = "";
        char Port[INTERNET_MAX_URL_LENGTH] = "";
        char Translate[INTERNET_MAX_URL_LENGTH];
        BOOL(WINAPI * GetHeader)
            (struct _HTTP_FILTER_CONTEXT * pfc, LPSTR lpszName,
             LPVOID lpvBuffer, LPDWORD lpdwSize);
        BOOL(WINAPI * SetHeader)
            (struct _HTTP_FILTER_CONTEXT * pfc, LPSTR lpszName,
             LPSTR lpszValue);
        BOOL(WINAPI * AddHeader)
            (struct _HTTP_FILTER_CONTEXT * pfc, LPSTR lpszName,
             LPSTR lpszValue);
        char *query;
        DWORD sz = sizeof(uri);
        DWORD szHost = sizeof(Host);
        DWORD szPort = sizeof(Port);
        DWORD szTranslate = sizeof(Translate);

        if (iis5) {
            GetHeader =
                ((PHTTP_FILTER_AUTH_COMPLETE_INFO) pvNotification)->GetHeader;
            SetHeader =
                ((PHTTP_FILTER_AUTH_COMPLETE_INFO) pvNotification)->SetHeader;
            AddHeader =
                ((PHTTP_FILTER_AUTH_COMPLETE_INFO) pvNotification)->AddHeader;
        }
        else {
            GetHeader =
                ((PHTTP_FILTER_PREPROC_HEADERS) pvNotification)->GetHeader;
            SetHeader =
                ((PHTTP_FILTER_PREPROC_HEADERS) pvNotification)->SetHeader;
            AddHeader =
                ((PHTTP_FILTER_PREPROC_HEADERS) pvNotification)->AddHeader;
        }

        if (JK_IS_DEBUG_LEVEL(logger))
            jk_log(logger, JK_LOG_DEBUG, "Filter started");

        /*
         * Just in case somebody set these headers in the request!
         */
        SetHeader(pfc, URI_HEADER_NAME, NULL);
        SetHeader(pfc, QUERY_HEADER_NAME, NULL);
        SetHeader(pfc, WORKER_HEADER_NAME, NULL);
        SetHeader(pfc, TOMCAT_TRANSLATE_HEADER_NAME, NULL);

        if (!GetHeader(pfc, "url", (LPVOID) uri, (LPDWORD) & sz)) {
            jk_log(logger, JK_LOG_ERROR,
                   "error while getting the url");
            return SF_STATUS_REQ_ERROR;
        }

        if (strlen(uri)) {
            int rc;
            const char *worker = NULL;
            query = strchr(uri, '?');
            if (query) {
                *query++ = '\0';
            }

            rc = unescape_url(uri);
            if (rc == BAD_REQUEST) {
                jk_log(logger, JK_LOG_ERROR,
                       "[%s] contains one or more invalid escape sequences.",
                       uri);
                write_error_response(pfc, "400 Bad Request",
                                     HTML_ERROR_400);
                return SF_STATUS_REQ_FINISHED;
            }
            else if (rc == BAD_PATH) {
                jk_log(logger, JK_LOG_EMERG,
                       "[%s] contains forbidden escape sequences.",
                       uri);
                write_error_response(pfc, "404 Not Found",
                                     HTML_ERROR_404);
                return SF_STATUS_REQ_FINISHED;
            }
            getparents(uri);
            if (pfc->
                GetServerVariable(pfc, SERVER_NAME, (LPVOID) Host,
                                  (LPDWORD) & szHost)) {
                if (szHost > 0) {
                    Host[szHost - 1] = '\0';
                }
            }
            Port[0] = '\0';
            if (pfc->
                GetServerVariable(pfc, "SERVER_PORT", (LPVOID) Port,
                                  (LPDWORD) & szPort)) {
                if (szPort > 0) {
                    Port[szPort - 1] = '\0';
                }
            }
            szPort = atoi(Port);
            if (szPort != 80 && szPort != 443 && szHost > 0) {
                strcat(Host, ":");
                strcat(Host, Port);
            }
            if (szHost > 0) {
                strcat(snuri, Host);
                strcat(snuri, uri);
                if (JK_IS_DEBUG_LEVEL(logger))
                    jk_log(logger, JK_LOG_DEBUG,
                           "Virtual Host redirection of %s",
                           snuri);
                worker = map_uri_to_worker(uw_map, snuri, logger);
            }
            if (!worker) {
                if (JK_IS_DEBUG_LEVEL(logger))
                    jk_log(logger, JK_LOG_DEBUG,
                           "Default redirection of %s",
                           uri);
                worker = map_uri_to_worker(uw_map, uri, logger);
            }
            /*
             * Check if somebody is feading us with his own TOMCAT data headers.
             * We reject such postings !
             */
            if (JK_IS_DEBUG_LEVEL(logger))
                jk_log(logger, JK_LOG_DEBUG,
                       "check if [%s] is points to the web-inf directory",
                       uri);

            if (uri_is_web_inf(uri)) {
                jk_log(logger, JK_LOG_EMERG,
                       "[%s] points to the web-inf or meta-inf directory.\nSomebody try to hack into the site!!!",
                       uri);

                write_error_response(pfc, "404 Not Found",
                                     HTML_ERROR_404);
                return SF_STATUS_REQ_FINISHED;
            }

            if (worker) {
                char *forwardURI;

                /* This is a servlet, should redirect ... */
                jk_log(logger, JK_LOG_DEBUG,
                       "[%s] is a servlet url - should redirect to %s",

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -