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

📄 mod_cas.c

📁 cas 客户端文件
💻 C
📖 第 1 页 / 共 3 页
字号:
 */static void send_cookie(char *ticket, request_rec *r) {    mod_cas_conf *c = (mod_cas_conf *) ap_get_module_config(	r->server->module_config, &cas_module);    char *cookie = apr_pstrcat(r->pool,        (c->CASLocalCacheInsecure ? COOKIENAME : COOKIENAME_SECURE),        "=", ticket,	(c->CASLocalCacheInsecure ? "" : ";Secure"),	";Path=", COOKIEPATH, NULL);    LOG("in send_cookie()\n");    LOG("-> sending cookie '");    LOG(cookie);    LOG("'\n");    apr_table_add(r->headers_out, "Set-Cookie", cookie);}/* * Walks through the given request's headers, reading all cookies that * can correspond to tickets and checking them against our ticket cache. * If a valid NetID is found, we stop immediately and return it; * otherwise, if no valid NetID is ever found, we return NULL. */static char *get_netid_from_cookies(request_rec *r) {    // msg_buf is used as a two-way message buffer between apr_table_do    // and the function we have it call here.    // as input to check_individual_cookie:    //   -- its first byte is our config's value of CASLocalCacheInsecure    // as output from check_individual_cookie:    //   -- it stores a NUL-terminated string representing the found    //      NetID, or is equivalent to "" if no NetID was found.    char msg_buf[USERBUFSIZE];    mod_cas_conf *c;    c = (mod_cas_conf *) ap_get_module_config(	r->server->module_config, &cas_module);    msg_buf[0] = c->CASLocalCacheInsecure;		// initialize input    msg_buf[1] = '\0';    // fail trivially if there's no ticket cache    if (!ticket_cache)	return NULL;    // the following call ends up with a valid netid or NULL in 'preauth_netid'    apr_table_do(	(int (*)()) check_individual_cookie,	msg_buf,	r->headers_in,	"Cookie",	NULL);    if (msg_buf[0] == c->CASLocalCacheInsecure	    && msg_buf[1] == '\0')	// the buffer is unchanged, meaning nobody wrote a NetID to it	return NULL;    else	return apr_pstrdup(r->pool, msg_buf);}/* * A support function for get_netid_from_cookies, used by apr_table_do * to handle individual cookies.  (There may be multiple "Cookie" headers * in the request that we receive, so we can't just use ap_table_get.) */static int check_individual_cookie(void *msg_buf, char *key, char *value) {    char *ticket, *p;    char netid_buf[USERBUFSIZE];    LOG("in check_individual_cookie()\n");    // we're looking for whatever's between COOKIENAME= and ';'    // (or the end), ignoring optional quotation marks at the beginning or    // the end    ticket = alloca(strlen(value) + 1);    strcpy(ticket, value);    // msg_buf[0] stores our "insecure" status    if (*((char *) msg_buf)) {      ticket = strstr(ticket, COOKIENAME "=");           // find key      if (!ticket)          return 1;      ticket += strlen(COOKIENAME "=");                  // skip key and '='    } else {      ticket = strstr(ticket, COOKIENAME_SECURE "=");    // find key      if (!ticket)          return 1;      ticket += strlen(COOKIENAME_SECURE "=");           // skip key and '='    }    if (*ticket == '"')	ticket++;			// if it starts with '"', skip '"'    p = strchr(ticket, ';');    if (p)	*p = '\0';			// end the string at ';' if it's there    p = ticket + strlen(ticket);    if (*p == '"')	*p = '\0';			// if we ended with '"', delete it    // now, we have the ticket from the cookie.    // let's see what it buys us.    // (msg_buf[0] stores our current CASLocalCacheInsecure status)    if (cache_get(ticket, netid_buf, sizeof(netid_buf), *((char *) msg_buf))) {	// copy the netid back out	// the 'msg_buf' parameter is a char[] of size USERBUFSIZE,	// so it can just take the NetID we found, byte for byte	strcpy((char *) msg_buf, netid_buf);        LOG("-> check_individual_cookie succeeded; found ");        LOG(netid_buf);        LOG("\n");	return 0;			// stop processing in apr_table_do    }    return 1;				// continue process in apr_table_do}static void logout(request_rec *r) {    char *ticket;    LOG("in logout()\n");    // if there's no ticket cache, there's nothing to do    if(!ticket_cache) {	LOG("-> no ticket cache... don't need to logout\n");	return;    }    ticket = get_ticket_from_cookies(r);    cache_invalidate(ticket);    return;}    static char *get_ticket_from_cookies(request_rec *r) {    // msg_buf is used as a two-way message buffer between apr_table_do    // and the function we have it call here.    // as input to check_individual_cookie:    //   -- its first byte is our config's value of CASLocalCacheInsecure    // as output from check_individual_cookie:    //   -- it stores a NUL-terminated string representing the found    //      NetID, or is equivalent to "" if no NetID was found.    char msg_buf[TICKETBUFSIZE];    mod_cas_conf *c;    c = (mod_cas_conf *) ap_get_module_config(        r->server->module_config, &cas_module);    msg_buf[0] = c->CASLocalCacheInsecure;              // initialize input    msg_buf[1] = '\0';    // fail trivially if there's no ticket cache    if (!ticket_cache)        return NULL;    // the following call ends up with a valid netid or NULL in 'preauth_netid'    apr_table_do(        (int (*)()) check_individual_cookie_for_ticket,        msg_buf,        r->headers_in,        "Cookie",        NULL);    if (msg_buf[0] == c->CASLocalCacheInsecure            && msg_buf[1] == '\0')        // the buffer is unchanged, meaning nobody wrote a ticket to it        return NULL;    else        return apr_pstrdup(r->pool, msg_buf);}/* * A support function for get_netid_from_cookies, used by apr_table_do * to handle individual cookies.  (There may be multiple "Cookie" headers * in the request that we receive, so we can't just use ap_table_get.) */static int check_individual_cookie_for_ticket(void *msg_buf, char *key, char *value) {    char *ticket, *p;    LOG("in check_individual_cookie_for_ticket()\n");    // we're looking for whatever's between COOKIENAME= and ';'    // (or the end), ignoring optional quotation marks at the beginning or    // the end    ticket = alloca(strlen(value) + 1);    strcpy(ticket, value);    // msg_buf[0] stores our "insecure" status    if (*((char *) msg_buf)) {      ticket = strstr(ticket, COOKIENAME "=");           // find key      if (!ticket)          return 1;      ticket += strlen(COOKIENAME "=");                  // skip key and '='    } else {      ticket = strstr(ticket, COOKIENAME_SECURE "=");    // find key      if (!ticket)          return 1;      ticket += strlen(COOKIENAME_SECURE "=");           // skip key and '='    }    if (*ticket == '"')	ticket++;			// if it starts with '"', skip '"'    p = strchr(ticket, ';');    if (p)	*p = '\0';			// end the string at ';' if it's there    p = ticket + strlen(ticket);    if (*p == '"')	*p = '\0';			// if we ended with '"', delete it    strcpy((char *) msg_buf, ticket);    LOG("-> check_individual_cookie_for_ticket succeeded; found ");    LOG(ticket);    LOG("\n");    return 0;			// stop processing in apr_table_do}/* * Creates and sends a cookie holding a new ticket, which we add to * the ticket cache under the appropriate NetID. */static void create_and_send_new_ticket(request_rec *r) {    mod_cas_conf *c;    TicketEntry t;    LOG("in create_and_send_new_ticket()\n");    c = (mod_cas_conf *) ap_get_module_config(	r->server->module_config, &cas_module);    // don't do anything if we're not supposed to have a ticket cache,    // or if the ticket cache doesn't exist    if (!c->CASLocalCacheFile || !ticket_cache)	return;    // set up the TicketEntry    t.valid = 1;    t.secure = !(c->CASLocalCacheInsecure);    strcpy(t.netid, r->user);    if (random_ticket(t.ticket, sizeof(t.ticket), c->CASEGDFile)) {	LOG("random_ticket successful: ticket = ");	LOG(t.ticket);	LOG("\n");        t.expiration = time(NULL) + c->CASLocalCacheTimeout;        cache_put(t);        send_cookie(t.ticket, r);    }}/* Returns 1 if 'user' is in 'group', 0 otherwise. */static int is_user_in_group(const char *user,			    const char *group,			    apr_pool_t *p) {    // TODO: cache here for performance?  (it's cleaner to cache in nscd)    char *gn;    char **t;    struct group *g;    struct passwd *u;    // this isn't thread-safe, but the current APR doesn't support generalized    // access to getgrnam() or getpwnam()    if (!(g = getgrnam(group)))        return 0;    for (t = g->gr_mem; t && *t; t++) {	LOG("checking "); LOG(user); LOG(" against"); LOG(*t); LOG("\n");        if (!strcmp(*t, user))            return 1;    }    if (!(u = getpwnam(user)))        return 0;    if (apr_group_name_get(&gn, u->pw_gid, p) != APR_SUCCESS)        return 0;    if (!strcmp(gn, group))	return 1;    else	return 0;}static void write_lock(int fd) {    /* prepare for writelock on (or unlock of) entire file */    struct flock lock;    lock.l_type = F_WRLCK;    lock.l_whence = 0;    lock.l_start = 0L;    lock.l_len = 0L;    /* block until we can get a shared lock */    fcntl(fd, F_SETLKW, &lock);}static void read_lock(int fd) {    /* prepare for writelock on (or unlock of) entire file */    struct flock lock;    lock.l_type = F_RDLCK;    lock.l_whence = 0;    lock.l_start = 0L;    lock.l_len = 0L;    /* block until we can get a shared lock */    fcntl(fd, F_SETLKW, &lock);}static void un_lock(int fd) {    /* prepare for writelock on (or unlock of) entire file */    struct flock lock;    lock.l_type = F_UNLCK;    lock.l_whence = 0;    lock.l_start = 0L;    lock.l_len = 0L;    /* block until we can get a shared lock */    fcntl(fd, F_SETLKW, &lock);}/* For debugging... */static void log(const char *msg) {    static FILE *fp;    if (!fp)	fp = fopen("/tmp/log", "a");    fputs(msg, fp);    fflush(fp);}/* Table of supported configuration directives */static const command_rec cas_directives[] = {    AP_INIT_TAKE1(	"CASLocalCacheFile",			/* name */	read_CASLocalCacheFile,			/* handler */	NULL,					/* handler's argument */	RSRC_CONF,				/* availability */	"Path to local cache in support of mod_cas"						/* description */    ),    AP_INIT_TAKE1(	"CASLogoutParameter",			/* name */	read_CASLogoutParameter,		/* handler */	NULL,					/* handler's argument */	RSRC_CONF,				/* availability */	"GET parameter used to indicate logout is desired"						/* description */    ),    AP_INIT_TAKE1(	"CASLogoutLocalURL",			/* name */	read_CASLogoutLocalURL,			/* handler */	NULL,					/* handler's argument */	RSRC_CONF,				/* availability */	"Local URL to redirect to after logout is performed"						/* description */    ),    AP_INIT_TAKE1(	"CASEGDFile",			/* name */	read_CASEGDFile,			/* handler */	NULL,					/* handler's argument */	RSRC_CONF,				/* availability */	"If specified, use EGD based on given file; "        "otherwise, use /dev/urandom"						/* description */    ),    AP_INIT_TAKE1(	"CASLocalCacheSize",			/* name */	read_CASLocalCacheSize,			/* handler */	NULL,					/* handler's argument */	RSRC_CONF,				/* availability */	"Size of local cache in support of mod_cas"						/* description */    ),    AP_INIT_TAKE1(	"CASLocalCacheTimeout",			/* name */	read_CASLocalCacheTimeout,		/* handler */	NULL,					/* handler's argument */	RSRC_CONF,				/* availability */	"Cookie usefulness timeout in local cache in support of mod_cas"						/* description */    ),    AP_INIT_FLAG(	"CASLocalCacheInsecure",		/* name */	read_CASLocalCacheInsecure,		/* handler */	NULL,					/* handler's argument */	RSRC_CONF,				/* availability */	"Cookie restriction for local cache in support of mod_cas"						/* description */    ),    {NULL}};/* Apache 2.0-style hook registration */static void cas_register_hooks(apr_pool_t *p) {  ap_hook_check_user_id(do_cas, NULL, NULL, APR_HOOK_MIDDLE);  ap_hook_auth_checker(authorize, NULL, NULL, APR_HOOK_MIDDLE);  ap_hook_child_init(init_child, NULL, NULL, APR_HOOK_MIDDLE);}/* Our actual module structure */module AP_MODULE_DECLARE_DATA cas_module ={    STANDARD20_MODULE_STUFF,		/* header */    NULL,				/* per-directory init */    NULL,				/* per-directory merge */    init_server_config,			/* per-server init */    NULL,				/* per-server merge */    cas_directives,			/* command handler */    cas_register_hooks			/* hook registration */};

⌨️ 快捷键说明

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