Webrelay: A Multithreaded HTTP Relay Server by Peter Zhang Listing One /* Update cookie in the session control data */ int sess_manager_update_cookie(char *seskey, unsigned int keylen, accept_info *aip, relay_info *rip) { chain_node_t *cnp; int status; cnp = sess_manager_find(seskey, keylen); if(cnp != NULL) { sess_info_t *sip; Spthread_mutex_lock(&cnp->lock); sip = (sess_info_t *) cnp->data; if(sip != NULL && sip->ClientIPAddr) { if ((aip->cliaddr->sin_addr.s_addr == sip->ClientIPAddr)) { time_t ct; time(&ct); if ( difftime(ct, cnp->LastUpdated) <= sess_manager_refresh ) { char *cookie_cookie = NULL; char *cookie_name = NULL; char *cookie_path = NULL; char *cookie_domain = NULL; char *p; int i, j, len1, len2; /* Session still valid.*/ cnp->LastUpdated = ct; /* rip->cookie: NAME=VALUE; PATH=/path1/path2, while cookie_cookie contains NAME=VALUE, and cookie_path is /path1/path2 */ cookie_cookie = parse_cookie(rip->cookie, &cookie_path, &cookie_domain); if ((p = strchr(cookie_cookie, '=')) != NULL) /* cookie_name is NAME */ cookie_name = strdupdelim(cookie_cookie, p); if(sip->cookie_path[0] == NULL && sip->cookie_name[0] == NULL && sip->cookie_value[0] == NULL) { /* There is no existing cookies in the SIP yet. Simply insert the new cookie into it. */ sip->cookie_path[0] = xstrdup(cookie_path); sip->cookie_name[0] = xstrdup(cookie_name); sip->cookie_domain[0] = xstrdup(cookie_domain); sip->cookie_value[0] = xstrdup(cookie_cookie); } else { /* Match the existing cookies already stored in SIP */ for(i=0; icookie_path[i] != NULL; ++i) { len1 = strlen(cookie_path); if(!strncasecmp(cookie_path, sip->cookie_path[i], len1)) { for (j=i; jcookie_name[j]!=NULL;++j ) { len2 = strlen(cookie_name); if(!strncasecmp(cookie_name, sip->cookie_name[j], len2) && !strncasecmp(cookie_path, sip->cookie_path[j], len1)) { /* Overwrite this cookie */ FREE_MAYBE(sip->cookie_value[j]); /* We store NAME=VALUE together as one single cookie */ sip->cookie_value[j] = xstrdup(cookie_cookie); break; } } /* No match of cookie_name, regarded as a new cookie of the same path. Now we ADD this new cookie at j */ sip->cookie_path[j] = xstrdup(cookie_path); sip->cookie_name[j] = xstrdup(cookie_name); sip->cookie_domain[j] = xstrdup(cookie_domain); sip->cookie_value[j] = xstrdup(cookie_cookie); break; } } if (sip->cookie_path[i] == NULL && sip->cookie_name[i] == NULL) { /* No match either of cookie_name nor cookie_path. This is a new cookie of a new path. Now we add this new cookie at i */ sip->cookie_path[i] = xstrdup(cookie_path); sip->cookie_name[i] = xstrdup(cookie_name); sip->cookie_domain[i] = xstrdup(cookie_domain); sip->cookie_value[i] = xstrdup(cookie_cookie); } } FREE_MAYBE(cookie_name); FREE_MAYBE(cookie_path); FREE_MAYBE(cookie_domain); FREE_MAYBE(cookie_cookie); cnp->data = (void *) sip; status = SES_OK; } else status = SES_TIMEOUT; } else status = SES_CLIENT_ENDS; } else status = SES_CLIENT_ENDS; Spthread_mutex_unlock(&cnp->lock); chain_hash_release(cnp); } else status = SES_CLIENT_ENDS; return status; } Listing Two /* Retrieve cookie from session control data */ int sess_manager_retrieve_cookie(char *seskey, unsigned int keylen, accept_info *aip, relay_info *rip) { int i, len1, len2, len; chain_node_t *cnp; int status; cnp = sess_manager_find(seskey, keylen); if(cnp != NULL) { sess_info_t *sip; Spthread_mutex_lock(&cnp->lock); sip = (sess_info_t *) cnp->data; if(sip != NULL && sip->ClientIPAddr) { if ((aip->cliaddr->sin_addr.s_addr == sip->ClientIPAddr)) { time_t ct; time(&ct); if ( difftime(ct, cnp->LastUpdated) <= sess_manager_refresh ) { char *targethost = NULL; char *targetpath = NULL; int i, len, len1, len2, old_len, num_entries; int ck_dom_len, targethost_len; /* Session still valid.*/ if(rip->redir_targethost != NULL) targethost = xstrdup(rip->redir_targethost); else targethost = xstrdup(rip->targethost); if(rip->redir_targetpath != NULL) targetpath = xstrdup(rip->redir_targetpath); else targetpath = xstrdup(rip->targetpath); FREE_MAYBE(rip->cookie); old_len = 0; num_entries = 0; for(i = 0;icookie_path[i] != NULL; ++i) { /* First match the domain */ targethost_len = strlen(targethost); if(sip->cookie_domain[i] != NULL) ck_dom_len = strlen(sip->cookie_domain[i]); else goto Match_path; /* Consume chars one by one from the end of the cookie_domain */ while(--ck_dom_len >= 0 && --targethost_len >= 0) { if(sip->cookie_domain[i][ck_dom_len] != targethost[targethost_len]) break; } if(ck_dom_len > 0) { /* No match of domain, search the next entry */ continue; } /* Match the path */ Match_path: len1 = (strlen(sip->cookie_path[i]) < strlen(targetpath)) ? strlen(sip->cookie_path[i]) : strlen(targetpath); if(!strncasecmp(targetpath, sip->cookie_path[i], len1)) { num_entries++; len2 = strlen(sip->cookie_value[i]); if(num_entries == 1) { len = len2; rip->cookie = Smalloc(len); memcpy(rip->cookie, sip->cookie_value[i], len); } else { len = old_len + 1 + 1 + len2; rip->cookie = Srealloc(rip->cookie, len); memcpy(rip->cookie + old_len, "; ", 2); memcpy(rip->cookie + old_len + 2, sip->cookie_value[i], len2); } old_len = len; } } if(num_entries > 0) { rip->cookie = Srealloc(rip->cookie, len + 1); rip->cookie[len] = '\0'; } FREE_MAYBE(targethost); FREE_MAYBE(targetpath); status = SES_OK; } else { status = SES_TIMEOUT; } } else status = SES_CLIENT_ENDS; } else status = SES_CLIENT_ENDS; Spthread_mutex_unlock(&cnp->lock); chain_hash_release(cnp); } else status = SES_CLIENT_ENDS; return status; } 1