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

📄 mod_cas.c

📁 cas 客户端文件
💻 C
📖 第 1 页 / 共 3 页
字号:
        // Remove ticket from query string        p = r->args;        if (p != NULL)            if (p == strstr(p, "ticket="))		// a comparison...	      *p = '\0';            else if (p = strstr(p, "&ticket="))		// yes, we're setting p	      *p = '\0';        return OK;    } else if (validate_status == BAD_CERT) {	LOG("-> certificate error\n");	ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "mod_cas: certificate error: "		      "bad cert or verisignserverca.pem is not available.\n");	return HTTP_INTERNAL_SERVER_ERROR;    } else {	/* Bad or missing ticket, so bounce the user to CAS. */	char *temp = alloca(strlen(CAS_LOGIN_URL) + strlen("?service=")	    + strlen(service) + 1);	if(!temp) {	    ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "mod_cas: alloca failed "		"in function create_and_send_new_ticket()");	    return HTTP_INTERNAL_SERVER_ERROR;	}        strcpy(temp, CAS_LOGIN_URL);        strcat(temp, "?service=");        strcat(temp, service);        ap_table_set(r->headers_out, "Location", temp);        return HTTP_MOVED_TEMPORARILY;    }}/* * Compares the authenticated user (from CAS) with the list of users (and, * in the future, hopefully groups using some sensible mechanism) authorized * by "Require" directives. * * Operates only if the AuthType is CAS, returning DECLINED otherwise on * the chance that another module will validate the request if we can't. * On success, we return OK, which solves the "authorization" question * for the entire request -- on OK, other modules should not be called. * If the AuthType is CAS, though, and the user isn't authorized as far * as we're concerned, we're going to take the initiative and return * HTTP_FORBIDDEN directly (rather than just DECLINED; that is, we're * not going to give any other module a chance to authorize anyone if the * AuthType is CAS).  We return HTTP_FORBIDDEN rather than * HTTP_UNAUTHORIZED because we don't want the browser to think it's * just temporarily failed and conduct a Basic Authentication dialog with * the user. */static int authorize(request_rec *r){    const array_header *requirements_array;    const char *auth_type = ap_auth_type(r);    const char *authenticated_user = r->connection->user;    const char *req_line, *req_word;    require_line *requirements;    int i, method;    /* Someone else has to pick up the torch if "CAS" isn't our AuthType. */    if (auth_type && strcmp(auth_type, "CAS"))        return DECLINED;    /* Some design considerations here were informed by mod_auth_kerb */    requirements_array = ap_requires(r);    if (!requirements_array)	return OK;				// no restriction    requirements = (require_line *) requirements_array->elts;    method = r->method_number;    for (i = 0; i < requirements_array->nelts; i++) {	// if our method isn't covered by the requirements line, ignore it	if (!(requirements[i].method_mask & (1 << method))) {	    continue;	}	req_line = requirements[i].requirement;		// full line	req_word = ap_getword(r->pool, &req_line, ' ');	// individual word	/*	 * If the requirements simply call for a "valid user," we can	 * simply return success, because if we're called, it means that	 * CAS authentication performed in an earlier callback DIDN'T	 * redirect back to CAS, so we have a valid user already, either	 * by virtue of a ticket or of having stored authenticated status	 * earlier.	 */	if (!strcmp(req_word, "valid-user"))	    return OK;	else if (!strcmp(req_word, "user")) {	    // the rest of the words are individual user names, so see	    // if our authenticated user matches	    while (*req_line) {		req_word = ap_getword_conf(r->pool, &req_line);		if (!strcmp(req_word, authenticated_user))		    return OK;	    }	} else if (!strcmp(req_word, "group")) {            // the rest of the words are individual group names            while (*req_line) {                req_word = ap_getword_conf(r->pool, &req_line);                if (is_user_in_group(authenticated_user, req_word, r->pool))                    return OK;            }        }    }    // For now, no other sorts of requirements are supported    // For the moment, fail cleanly if we get something like    // "Require group foo" so that configuration files don't    // need to be changed; the relevant line can just be ignored,    // and we failed "closed."    return HTTP_FORBIDDEN;}/* Utility function definitions *//* * Fills buf with the 'service' portion of the URL requested.  This will * be the entire URL minus any trailing '&ticket=', if present. * The URL is determined here, heuristically, from the request record. * If buf isn't large enough to fit the entire URL, NULL is returned. */static char *get_service(request_rec *r, char *buf, int buflen) {    int l;    char portstr[6];    char *path = r->uri, *p;    mod_cas_conf *c = (mod_cas_conf *) ap_get_module_config(	r->server->module_config, &cas_module);    // /*     //  * For the server name, use the "Host" header if it exists; otherwise,    //  * consult the 'server' record.  Note that our 'server' string includes    //  * the server's name and an optional ':port'.    //  */    // const char *server = ap_table_get(r->headers_in, "Host");    // char *query = r->args;    // char *scheme = "http://";    // if (!server)    //	  server = r->server->server_hostname;    // if (!query)    //	  query = "";    /*     * Avoid using the "Host" header, for it's under the control of     * the client and may be forged unless Apache's administrator     * goes out of its way to prevent this.     */    const char *server = r->server->server_hostname;    char *query = r->args;    char *scheme = "http://";    if (!query)      query = "";    if (!(c->CASLocalCacheInsecure))	scheme = "https://";    LOG("server = '"); LOG(server); LOG("'\n");    LOG("query = '"); LOG(query); LOG("'\n");    LOG("scheme = '"); LOG(scheme); LOG("'\n");    /* convert the port number to a string in case we need it */    snprintf(portstr, 6*sizeof(char), "%d", r->server->port);    LOG("portstr: ");    LOG(portstr);    LOG("\n");    if ((l = strlen(scheme) + strlen(server) + strlen(":") + strlen(portstr)	 + strlen(path) + strlen(query) + 1) > buflen)	return NULL;    strcpy(buf, scheme);    strcat(buf, server);    /* add the port number if it's non-standard */    if(c->CASLocalCacheInsecure && r->server->port != 80      || !c->CASLocalCacheInsecure && r->server->port != 443) {	strcat(buf, ":");	strcat(buf, portstr);    }    strcat(buf, path);    if (query && *query != '\0') {	strcat(buf, "%3F");             /* "?" */        for (p = query; *p; p++) {            if (*p == '=')                strcat(buf, "%3D");            else if (*p == '?')                strcat(buf, "%3F");            else if (*p == '&')                strcat(buf, "%26");	/* rewrite later to be more complete */            else {		char t[2];                t[0] = *p;                t[1] = '\0';		strcat(buf, t);            }        }    }    /* eliminate the ticket */    if ((p = strstr(buf, "%3Fticket%3D")))	*p = '\0';    if ((p = strstr(buf, "%26ticket%3D")))	*p = '\0';    return buf;}/* * Returns the 'ticket' portion of the URL requested.  This consists * of everything following '&ticket=' in the logical full URL.  If no "ticket" * parameter was specified, we return NULL. */static char *get_ticket(request_rec *r) {    char *ticket = NULL;    if (r->args && *(r->args) != '\0') {	/* if the query starts with "ticket=", then use the whole query */	if (r->args == strstr(r->args, "ticket="))	    ticket = r->args + strlen("ticket=");	else {	    /* otherwise, we need an "&" */	    ticket = strstr(r->args, "&ticket=");	    if (ticket)		ticket += strlen("&ticket=");	}    }    if (!ticket || *ticket == '\0')	return NULL;    return ticket;}/* Functions for handling the ticket cache. *//* * Add an entry to the ticket cache.  Values are copied from the TicketEntry, * which need not persist after the call terminates. */static void cache_put(TicketEntry te) {    int next;    char *last_slot = ticket_cache + ticket_cache_size - sizeof(TicketEntry);    if (!ticket_cache)	return;			// alas, nothing to do    LOG("in cache_put()\n");    // get an advisory, exclusive lock on the ticket cache file    write_lock(ticket_cache_fd);    LOG("-> got lock\n");    // the first int of the ticket cache stores the next slot    memcpy(&next, ticket_cache, sizeof(int));    LOG("-> first memcpy() done\n");    // wrap around if necessary    if (ticket_cache + sizeof(int) + next * sizeof(TicketEntry) > last_slot)	next = 0;    memcpy(ticket_cache + sizeof(int) + next * sizeof(TicketEntry),	&te, sizeof(TicketEntry));    msync(ticket_cache + sizeof(int) + next * sizeof(TicketEntry),	sizeof(TicketEntry), MS_SYNC | MS_INVALIDATE);    LOG("-> second memcpy() done\n");    // increment next, letting our successor handle wraparound    next++;    memcpy(ticket_cache, &next, sizeof(int));    msync(ticket_cache, sizeof(int), MS_SYNC | MS_INVALIDATE);    // release our lock    un_lock(ticket_cache_fd);    LOG("-> released lock\n");}/* * Retrieves the NetID for a given ticket, storing it in the buffer * provided.  Returns 1 if the ticket was found and valid, 0 otherwise. * The 'insecure' parameter stores our current CASLocalCacheInsecure * status. */static int cache_get(char *ticket, char *buf, int buflen, char insecure) {    char *p;    char *last_slot = ticket_cache + ticket_cache_size - sizeof(TicketEntry);    TicketEntry t;    LOG("in cache_get()\n");    // get an advisory, shared file lock on the ticket cache file    read_lock(ticket_cache_fd);    // the first few bytes of the ticket array form an integer we don't    // care about    for (p = ticket_cache + sizeof(int); 	    p <= last_slot;	    p += sizeof(TicketEntry)) {	memcpy(&t, p, sizeof(TicketEntry));	if (t.valid 		&& t.secure == !insecure		&& time(NULL) < t.expiration		&& !strcmp(t.ticket, ticket)) {	    if (strlen(t.netid) + 1 > buflen)		return 0;	    strcpy(buf, t.netid);	    un_lock(ticket_cache_fd);			// release the lock	    return 1;	}    }    un_lock(ticket_cache_fd);				// release the lock    return 0;}/* * Constructs a random ticket value and stores it in the buffer provided. * The buffer is terminated with '\0'.  On unexpected failure, return 0; * otherwise, return 1. */static int random_ticket(char *buf, int buflen, char *egdfile) {    int fd;    char *pool =	"ABCDEFGHIJKLMNOPQRSTUVWXYZ"	"abcdefghijklmnopqrstuvwxyz"	"01234567890";    LOG("in random_ticket()\n");    if (egdfile == NULL) {        /* Get our randomness from /dev/urandom. */	LOG("using /dev/urandom\n");        if ((fd = open("/dev/urandom", O_RDONLY)) < 0) {	    LOG("ERROR!  Couldn't open /dev/urandom.  Do not deploy!");	    return 0;        } else if (read(fd, buf, buflen - 1) < 0) {	    close(fd);	    LOG("ERROR!  Couldn't open /dev/urandom.  Do not deploy!");	    return 0;        } else {

⌨️ 快捷键说明

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