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

📄 mod_cspace.c

📁 开源的OpenId的一个java实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements.  See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License.  You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */#include <string.h>#include <openssl/x509.h>#include <openssl/sha.h>#include <openssl/hmac.h>#include <openssl/bio.h>#include <openssl/buffer.h>#include "apr_tables.h"#include "apr_strings.h"#include "ap_config.h"#include "mod_cspace.h"#include "http_core.h"#include "http_request.h"#include "http_protocol.h"#include "http_log.h"#include "http_main.h"#include "cspace_utils.h"#include "session.h"#include "process_request.h"#include "cspace_validator.h"#define SESSION_ID_LEN 64#define MYMIN(a, b) ((a)<(b)?(a):(b))#define UNAUTHORIZED_REDIRECT(r, u) redirect_external((r), (u))#define CARDSPACE_HEADER_PFX "cardspace_"#define CARDSPACE_HEADER_PPID "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/privatepersonalidentifier"static void remove_cspace_headers(request_rec *r);void cspace_log_error(const char *msg, pc_log_level_t level, void *cb_ctx){            ap_log_error(APLOG_MARK, level, 0, (server_rec *)cb_ctx, msg);}/*static X509 *x509_create_with_buffer(unsigned char *input, int length);static int is_valid_cert(const char *cert, const char *uri, const char *dso_filename,                  apr_pool_t *p);*//* moved to mod_cspace.h static void cspace_log_error(const char *msg, pc_log_level_t level,                              void *cb_ctx){    ap_log_error(APLOG_MARK, level, 0, (server_rec *)cb_ctx, msg);}*/static int redirect_external(request_rec *r, char *url){    /* set a "Location:" header and 302 redirect. */    printf("redirecting to: %s", url);    apr_table_setn(r->headers_out, "Location", url);    return HTTP_MOVED_TEMPORARILY;  }#if 0static int redirect_internal(request_rec *r, char* url){    remove_cspace_headers(r);    ap_internal_redirect(url, r);    return OK;    /*return HTTP_UNAUTHORIZED;*/}#endifstatic int find_uri(const char *uri, apr_array_header_t *a){    int i;    void *tmp;    tmp = a->elts;    for (i = 0; i < a->nelts; i++) {#ifdef CSPACE_DEBUG        printf("comparing:%s (%d), %s (%d), min=%d\n", *(char **)tmp,                strlen(*(char **)tmp), uri, strlen(uri),                MYMIN(strlen(*(char **)tmp), strlen(uri)));#endif        if (strcmp(uri, "/") == 0) {            if (strcmp(*(char **)tmp, "/") == 0) {                return SUCC;            } else {                return FAIL;            }        }        if (strncmp(*(char **)tmp, uri,                    MYMIN(strlen(*(char **)tmp), strlen(uri))) == 0) {            return SUCC;        }        tmp = (char *)tmp + a->elt_size;    }    return FAIL;}/*This piece of code is used only for testing purposes*/#ifdef CSPACE_DEBUGstatic int cspace_access_check_testing(request_rec *r) {    cspace_dir_cfg *dir_cfg = (cspace_dir_cfg *)ap_get_module_config(            r->per_dir_config, &cspace_module);        cspace_svr_cfg *svr_cfg = (cspace_svr_cfg *)ap_get_module_config(            r->server->module_config, &cspace_module);    printf("\n\n\nCSPACE_ACCESS_CHECK\n");    cfg_svr_printf("\tsvr cfg:", svr_cfg, "\n");    cfg_dir_printf("\tdir cfg:", dir_cfg, "\n");    printf("\tURI: %s\n\n\n\n", r->uri);         return DECLINED;}#endif/* FROM http_filter.c: * * Here we deal with getting the request message body from the client. * Whether or not the request contains a body is signaled by the presence * of a non-zero Content-Length or by a Transfer-Encoding: chunked. * * Note that this is more complicated than it was in Apache 1.1 and prior * versions, because chunked support means that the module does less. * * The proper procedure is this: * * 1. Call ap_setup_client_block() near the beginning of the request *    handler. This will set up all the necessary properties, and will *    return either OK, or an error code. If the latter, the module should *    return that error code. The second parameter selects the policy to *    apply if the request message indicates a body, and how a chunked *    transfer-coding should be interpreted. Choose one of * *    REQUEST_NO_BODY          Send 413 error if message has any body *    REQUEST_CHUNKED_ERROR    Send 411 error if body without Content-Length *    REQUEST_CHUNKED_DECHUNK  If chunked, remove the chunks for me. *    REQUEST_CHUNKED_PASS     If chunked, pass the chunk headers with body. * *    In order to use the last two options, the caller MUST provide a buffer *    large enough to hold a chunk-size line, including any extensions. * * 2. When you are ready to read a body (if any), call ap_should_client_block(). *    This will tell the module whether or not to read input. If it is 0, *    the module should assume that there is no message body to read. * * 3. Finally, call ap_get_client_block in a loop. Pass it a buffer and its *    size. It will put data into the buffer (not necessarily a full buffer), *    and return the length of the input block. When it is done reading, it will *    return 0 if EOF, or -1 if there was an error. *    If an error occurs on input, we force an end to keepalive. * *    This step also sends a 100 Continue response to HTTP/1.1 clients if *    appropriate. */static int cspace_read_request(request_rec *r, char **buf, int *retval){    apr_array_header_t *a;    apr_pool_t *p = r->pool;    apr_pool_t *temp_pool;    int res, ret;    #ifdef CSPACE_DEBUG    printf("CSPACE_READ_REQUEST:\n");#endif    if (apr_pool_create(&temp_pool, p) != APR_SUCCESS)        return FAIL; /*TODO: should it be UNAUTHORIZED?*/        a = apr_array_make(temp_pool, 1, sizeof(char *));        ret = ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK);    if (ret != OK) {        *retval = ret;        return FAIL; /*above: module should return that error code*/    }        if (ap_should_client_block(r)) {        char temp_buf[HUGE_STRING_LEN + 1];                while ((res = ap_get_client_block(r, temp_buf, HUGE_STRING_LEN)) > 0) {            *(temp_buf + res) = '\0';            *(const char **)apr_array_push(a) =                apr_pstrdup(temp_pool, temp_buf);            /*this array is free'd before the function exits*/        }    } else {        cspace_log_error("Cannot read request body", APLOG_WARNING, r->server);#ifdef CSPACE_DEBUG        printf("ERR: should_client_block false!\n");#endif        return FAIL;    }    *buf = apr_array_pstrcat(p, a, '\0'); /*use the request pool here*/    apr_pool_destroy(temp_pool);    return SUCC;    /*return (res == OK);*/}static void set_header(char *uri, char *key, char *val, void* table, void *pool){	apr_table_t *t = (apr_table_t *)table;#ifdef CSPACE_DEBUG    printf("Header %s/%s:%s\n", uri, key, val);#endif    /*process_context_extract info dups for us*/#ifndef DONT_INCLUDE_CS_PFX_IN_HEADERS    if (uri) {        apr_table_set(t, apr_pstrcat(pool, CARDSPACE_HEADER_PFX, uri, "/",                                     key, NULL),val);    } else {        apr_table_set(t, apr_pstrcat(pool, CARDSPACE_HEADER_PFX, key, NULL),                      val);    }#else /* DONT_INCLUDE_CS_PFX_IN_HEADERS */    if (uri) {        apr_table_set(t, apr_pstrcat(pool, uri, "/", key, NULL), val);    } else {        apr_table_set(t, apr_pstrcat(pool, key, NULL), val);    }#endif /* DONT_INCLUDE_CS_PFX_IN_HEADERS */}/*static int iterate_headers_remove(void *rec, const char *key, const char *val){    if (ap_strstr_c(key, CARDSPACE_HEADER_PFX))        apr_table_unset(((request_rec *)rec)->subprocess_env, key);    return SUCC;}*/static void remove_cspace_headers(request_rec *r){    const apr_array_header_t *hdr = apr_table_elts(r->subprocess_env);    apr_table_entry_t *elts = (apr_table_entry_t *)hdr->elts;     /*apr_table_entry_t *elts = (apr_table_entry_t *) r->subprocess_env->a.elts;*/    int j = hdr->nelts;    int i;    for (i = 0; i < j; ++i) {        if (elts[i].key) {            if (ap_strstr_c(elts[i].key, CARDSPACE_HEADER_PFX)) {                apr_table_unset(r->subprocess_env, elts[i].key);                --i; --j; /* HACK: this was done according to the                                   impl of apr_table_unset */            }        }    }}static int iterate_headers_check(void *rec, const char *key, const char *val){    if (ap_strstr_c(key, CARDSPACE_HEADER_PFX))        return FAIL;    else        return SUCC;}/* may be we need a config option to specify where the claims should be * added. is processing at the proxy a real use case?*/static int check_valid_headers(request_rec *r){    return apr_table_do(iterate_headers_check, NULL, r->subprocess_env, NULL);}static int set_cookie(request_rec *r, const char* session_id){    /*apr_table_set(r->headers_out, SET_COOKIE, session_id);*/    const char *cookie_header = NULL;    char *cookies = NULL;    size_t cookie_len = 0; /*header len*/    cookie_header = apr_table_get(r->headers_out, HTTP_COOKIE_HEADER_OUT);    if (cookie_header) {        /*header already set*/        if (ap_strstr_c(cookie_header, SESSION_COOKIE)) {            return SUCC; /*session_id is already set*/        } else {            /*session id not set, set it now*/            cookie_len = strlen(cookie_header) -                          strlen(HTTP_COOKIE_HEADER_OUT);            if (!(cookies = apr_palloc(r->pool, cookie_len + 3 +                                                /*3 for ";=\0"*/                                                strlen(SESSION_COOKIE) +                                                MAX_SESSION_ID_LEN)))                    return HTTP_INTERNAL_SERVER_ERROR;            strncpy(cookies, cookie_header + strlen(HTTP_COOKIE_HEADER_OUT),                    cookie_len);            strncpy(cookies + cookie_len, ";", 1);        }    }    else {        if (!(cookies = apr_palloc(r->pool, cookie_len + 3 + /*3 for ";=\0"*/                                            strlen(SESSION_COOKIE) +                                            MAX_SESSION_ID_LEN)))            return HTTP_INTERNAL_SERVER_ERROR;    }    /*no cookie header found, or cookie not in header*/        strncpy(cookies + cookie_len, SESSION_COOKIE, strlen(SESSION_COOKIE));    strncpy(cookies + cookie_len + strlen(SESSION_COOKIE), "=", 1);    strncpy(cookies + cookie_len + 1 + strlen(SESSION_COOKIE), session_id,            strlen(session_id));    strncpy(cookies + cookie_len + 1 + strlen(SESSION_COOKIE) +            strlen(session_id), "\0", 1);        apr_table_unset(r->headers_out, HTTP_COOKIE_HEADER_OUT);    apr_table_set(r->headers_out, HTTP_COOKIE_HEADER_OUT, cookies);    return SUCC;}static int get_cookie(request_rec *r, char **cookies){    const char *cookie_header = NULL;    size_t cookie_len; /*header len*/    cookie_header = apr_table_get(r->headers_in, HTTP_COOKIE_HEADER_IN);    if (!cookie_header)        return FAIL; /*no cookie header found*/      cookie_len = strlen(cookie_header); /*- strlen(HTTP_COOKIE_HEADER_IN)*/    if (!(*cookies = apr_palloc(r->pool, cookie_len)))        return HTTP_INTERNAL_SERVER_ERROR;    strncpy(*cookies, cookie_header /* + strlen(HTTP_COOKIE_HEADER_IN)*/,            cookie_len);    strncpy(*cookies + cookie_len, "\0", 1);        return SUCC;}static char *get_session_id_from_cookies(char *cookies){    char *ptr = NULL;    if ((cookies) && (cookies = ap_strstr(cookies, SESSION_COOKIE))) {        /*cookie in hand*/        if ((cookies) && (ptr = strchr(cookies, '='))) {            /*cookie structure is fine, now get the value*/            if ((ptr) && (ptr = strtok(ptr + 1, " ;\n\t\r\f"))) {                /*ptr contains the valid session ID*/                printf("session id received:%s\n", ptr);                printf("all cookies received: %s\n", cookies);                return ptr;            }        }    }    return NULL;}/*TODO:DONE make this to handle an excluded list instead of just one uri*/static int excluded_uri(const char *uri, apr_array_header_t *excluded_list){    if (find_uri(uri, excluded_list))        return SUCC;    else        return FAIL;}static int cspace_login_arg_avail(request_rec *r){    if (r->args) {        if (strncmp(r->args, CSPACE_DEFAULT_LOGIN_ARG,                    MYMIN(strlen(CSPACE_DEFAULT_LOGIN_ARG),                          strlen(r->args))) == 0)            return SUCC;        else if (ap_strstr_c(r->args, CSPACE_DEFAULT_LOGIN_AMP_ARG))            return SUCC;    }    return FAIL;}static int handle_session_sso(request_rec *r, cspace_dir_cfg *dir_cfg,                              cspace_svr_cfg *svr_cfg){    /*TODO*/    return UNAUTHORIZED_REDIRECT(r, dir_cfg->redir_uri);}static int handle_nosession_sso(request_rec *r, cspace_dir_cfg *dir_cfg,                                cspace_svr_cfg *svr_cfg){    char *session_id = NULL;    int valid_session = FAIL;    int status = FAIL;    char *cookies = NULL;    void *session_ctx = NULL;    status = get_cookie(r, &cookies);    if (status == HTTP_INTERNAL_SERVER_ERROR)        return status;    session_ctx = session_ctx_create(r->pool, dir_cfg->session_file,                                     svr_cfg->session_expire);    /*NB: should we return HTTP_METHOD_NOT_ALLOWED if not POST?*/    /* TODO: make the argument (tag identifying login page) a config option */    if ((cookies) && (session_id = get_session_id_from_cookies(cookies))) {        if ((valid_session = handle_session(session_id, SESSION_ID_LEN,                                            session_ctx)))            return OK;    }    if ((cspace_login_arg_avail(r)) && (r->method_number == M_POST)) {       /*TODO*/ 

⌨️ 快捷键说明

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