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

📄 mod_cas.c

📁 cas 客户端文件
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *  Copyright (c) 2000-2003 Yale University. All rights reserved. * *  THIS SOFTWARE IS PROVIDED "AS IS," AND ANY EXPRESS OR IMPLIED *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE EXPRESSLY *  DISCLAIMED. IN NO EVENT SHALL YALE UNIVERSITY OR ITS EMPLOYEES BE *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED, THE COSTS OF *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA OR *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *  SOFTWARE, EVEN IF ADVISED IN ADVANCE OF THE POSSIBILITY OF SUCH *  DAMAGE. * *  Redistribution and use of this software in source or binary forms, *  with or without modification, are permitted, provided that the *  following conditions are met: * *  1. Any redistribution must include the above copyright notice and *  disclaimer and this list of conditions in any related documentation *  and, if feasible, in the redistributed software. * *  2. Any redistribution must include the acknowledgment, "This product *  includes software developed by Yale University," in any related *  documentation and, if feasible, in the redistributed software. * *  3. The names "Yale" and "Yale University" must not be used to endorse *  or promote products derived from this software. *//* * "Require NetID Authentication" module that allows a server to act as a * client of the Central Authentication Service. * * Original author: Shawn Bayern <shawn.bayern@yale.edu> * Original version: February, 2001 * * Current maintainer: Drew Mazurek <drew.mazurek@yale.edu> * * Note: the "LOG" messages are entirely for debugging and should not be * enabled for any production deployment.  They're somewhat arbitrary; * we've found them useful at Yale for debugging new features, so I've * left them in in case they're useful. */#include "httpd.h"#include "http_config.h"#include "http_core.h"#include "http_log.h"#include "http_main.h"#include "http_protocol.h"#include "util_script.h"#include <sys/file.h>#include <sys/mman.h>#include <sys/stat.h>#include <sys/types.h>#include <unistd.h>#include <fcntl.h>#include <stdio.h>#include "cas.h"#include "ticketcache.h"#define URLBUFSIZE 4096#define USERBUFSIZE 20// support two different cookie names to allow secure and insecure cookies// to exist side-by-side#define COOKIENAME "MODCASID"#define COOKIENAME_SECURE "MODCASIDS"#define COOKIEPATH "/"#define DEFAULT_CASLocalCacheFile NULL#define DEFAULT_CASEGDFile NULL#define DEFAULT_CASLocalCacheSize 1000#define DEFAULT_CASLocalCacheTimeout 3600#define DEFAULT_CASLocalCacheInsecure 0//#define DEBUG#undef DEBUG#ifdef DEBUG# define LOG(X) log(X)#else# define LOG(X) #endif/* Utility function declarations */static char *get_service(request_rec *r, char *buf, int buflen);static char *get_ticket(request_rec *r);static void log(const char *msg);static int is_user_in_group(const char *user, const char *group, pool *p);static int check_individual_cookie(void *netid, char *key, char *value);static char *get_netid_from_cookies(request_rec *r);static void create_and_send_new_ticket(request_rec *r);static void write_lock(int fd);static void read_lock(int fd);static void un_lock(int fd);/* Our exported link to Apache. */module MODULE_VAR_EXPORT cas_module;/* our internal "configuration record" */typedef struct {   char *CASLocalCacheFile;   char *CASEGDFile;   int CASLocalCacheSize;   time_t CASLocalCacheTimeout;   char CASLocalCacheInsecure;} mod_cas_conf;/* effectively per-process local pointer to our mmap()'d ticket cache */static char *ticket_cache = NULL;static size_t ticket_cache_size = 0;static int ticket_cache_fd;/* * Reads CASLocalCacheFile from the configuration file. */static const char *read_CASLocalCacheFile(	cmd_parms *cmd, void *dummy, char *word) {    mod_cas_conf *c = (mod_cas_conf *) ap_get_module_config(	cmd->server->module_config, &cas_module);    c->CASLocalCacheFile = word;    return NULL;}/* * Reads CASLocalCacheSize from the configuration file. */static const char *read_CASLocalCacheSize(	cmd_parms *cmd, void *dummy, char *word) {    mod_cas_conf *c = (mod_cas_conf *) ap_get_module_config(	cmd->server->module_config, &cas_module);    c->CASLocalCacheSize = atoi(word);    if (c->CASLocalCacheSize <= 0)	return "CASLocalCacheSize must be a positive number";    return NULL;}/* * Reads CASLocalCacheTimeout from the configuration file. */static const char *read_CASLocalCacheTimeout(	cmd_parms *cmd, void *dummy, char *word) {    mod_cas_conf *c = (mod_cas_conf *) ap_get_module_config(	cmd->server->module_config, &cas_module);    c->CASLocalCacheTimeout = atoi(word);    if (c->CASLocalCacheTimeout <= 0)	return "CASLocalCacheTimeout must be a positive number";    return NULL;}/* * Reads CASEGDFile from the configuration file. */static const char *read_CASEGDFile(        cmd_parms *cmd, void *dummy, char *word) {    mod_cas_conf *c = (mod_cas_conf *) ap_get_module_config(        cmd->server->module_config, &cas_module);    c->CASEGDFile = word;    return NULL;}/* * Reads CASLocalCacheInsecure from the configuration file. */static const char *read_CASLocalCacheInsecure(	cmd_parms *cmd, void *dummy, int bool) {    mod_cas_conf *c = (mod_cas_conf *) ap_get_module_config(	cmd->server->module_config, &cas_module);    c->CASLocalCacheInsecure = (!(!bool));    return NULL;}/* * Returns a newly allocated server configuration record, filled in with the * default values.  Since we provide no "merge" routine, we expect that * more specific settings will occlude less specific settings.  This may * be important -- for instance, if there is a virtual server configured * for SSL support on a server that is otherwise unprotected. */static void *init_server_config(pool *p, server_rec *s) {    mod_cas_conf *c = ap_pcalloc(p, sizeof(mod_cas_conf));    c->CASLocalCacheFile = DEFAULT_CASLocalCacheFile;    c->CASLocalCacheSize = DEFAULT_CASLocalCacheSize;    c->CASLocalCacheTimeout = DEFAULT_CASLocalCacheTimeout;    c->CASLocalCacheInsecure = DEFAULT_CASLocalCacheInsecure;    c->CASEGDFile = DEFAULT_CASEGDFile;    return c;}/* * Called upon the initializaion of a child process.  mod_cas currently * takes this opportunity to mmap() our cache database if one has been * requested. */static void init_child(server_rec *s, pool *p) {    int fd;    mod_cas_conf *c;    LOG("in init_child()\n");    // if ticket_cache is already initialized, don't bother re-mapping it    if (ticket_cache)	return;    // retrieve our configuration    c = (mod_cas_conf *) ap_get_module_config(s->module_config, &cas_module);    if (c != NULL)       LOG("-> c is not null\n");    else      LOG("-> c is null\n");    // don't do anything if the server admin doesn't want a cache    if (!(c->CASLocalCacheFile))	return;    LOG("-> dereferenced c\n");    // if a cache file is requested, mmap() it and store its in-memory    // location in our static, per-process cell    fd = open(c->CASLocalCacheFile, O_RDWR | O_CREAT, 0600);    if (fd < 0) {	LOG("-> couldn't open CAS cache file\n");	return;					// open() failure    }    // make sure the file is as large as we need it to be    ticket_cache_size =	sizeof(int) + (c->CASLocalCacheSize * sizeof(TicketEntry));    lseek(fd, ticket_cache_size, SEEK_SET);    write(fd, "", 1);    ticket_cache =	mmap(0, ticket_cache_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);    /*      * If mmap() failed, there's really not much we can do other than     * abandon the idea of a ticket cache, at least for us.  But at least     * we can set ticket_cache back to NULL as a marker.     */    if (ticket_cache == MAP_FAILED) {	ticket_cache = NULL;	LOG("-> mmap() failed\n");	return;    }    ticket_cache_fd = fd;    LOG("-> init_child() done\n");}/* * Called upon the exit of a child process.  mod_cas currently takes this * opportunity to munmap() our cache database if one was previously * mmap()'d. */static void cleanup_child(server_rec *s, pool *p) {    if (ticket_cache)	munmap(ticket_cache, ticket_cache_size);}/* * Handles CAS authentication.  Redirects to CAS if we can't authenticate * the user, and expects a ticket back.  Sets r->connection->user with * a validated user.  Operates only when the AuthType is set to "CAS." * * Once past this point, we never directly return DECLINED; we return * success with OK and, if we can't authenticate the user, merely redirect * to the CAS with HTTP_MOVED_TEMPORARILY.  On error, we return * HTTP_INTERNAL_SERVER_ERROR.  If we return OK, no other modules are * supposed to handle this request during the "check user" phase. */static int do_cas(request_rec *r){    // it's okay to use these buffers since we're single-threaded    char *urlbuf = (char *) ap_pcalloc(r->pool, URLBUFSIZE);    char *userbuf = (char *) ap_pcalloc(r->connection->pool, USERBUFSIZE);    char *service, *ticket;    const char *auth_type = ap_auth_type(r);    char *p;    int validate_status = 0;    /* We only have something to do if "CAS" is the AuthType. */    if (auth_type && strcmp(auth_type, "CAS"))        return DECLINED;    /*     * Okay, we're relevant.  Now, if we've been handed a cookie that     * identifies the user (with the help of the ticket cache), we can     * simply honor the user's preauthenticated status.  (This call     * uses the ticket cache behind the scenes.  Separately, as a nice     * side effect, this sets r->connection->user to NULL if we don't     * find a cookie; that way, if we proceed, we know that r->connnection->     * user doesn't have some bogus value in in.     */    if (r->connection->user = get_netid_from_cookies(r))	return OK;    /*     * "CAS" is the AuthType, so we consider the request in terms of     * a service and a ticket.     */    service = get_service(r, urlbuf, URLBUFSIZE);    ticket = get_ticket(r);    LOG("  service = '"); LOG(service);    LOG("'; ticket = '");    if (ticket)        LOG(ticket);    else        LOG("(null)");    LOG("'\n");    if (service == NULL) {	ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "mod_cas: null service\n");        return HTTP_INTERNAL_SERVER_ERROR;	/* shouldn't happen */    }    LOG("about to call CAS_validate()\n");    if (ticket != NULL            && (validate_status = CAS_validate(ticket, service, userbuf, USERBUFSIZE)) == 1) {        LOG("-> successful primary authentication for '");        LOG(userbuf);        LOG("'\n");        // Successful authentication        r->connection->user = userbuf;        // If relevant, send a cookie since we authenticated the user with        // a real CAS ticket        create_and_send_new_ticket(r);

⌨️ 快捷键说明

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