📄 cookies.c
字号:
/* Make sure that the path is set to something */ if (!cookie->path || cookie->path[0] != '/') { g_free(cookie->path); cookie->path = Cookies_strip_path(url_path); } /* If the server never set a domain, or set one without a leading * dot (which isn't allowed), we use the calling URL's hostname. */ if (cookie->domain == NULL || cookie->domain[0] != '.') { g_free(cookie->domain); cookie->domain = g_strdup(host); return TRUE; } /* Count the number of dots and also find out if it is an IP-address */ is_ip = TRUE; for (i = 0, dots = 0; cookie->domain[i] != '\0'; i++) { if (cookie->domain[i] == '.') dots++; else if (!isdigit(cookie->domain[i])) is_ip = FALSE; } /* A valid domain must have at least two dots in it */ /* NOTE: this breaks cookies on localhost... */ if (dots < 2) { return FALSE; } /* Now see if the url matches the domain */ diff = strlen(host) - i; if (diff > 0) { if (g_strcasecmp(host + diff, cookie->domain)) return FALSE; if (!is_ip) { /* "x.y.test.com" is not allowed to set cookies for ".test.com"; * only an url of the form "y.test.com" would be. */ while ( diff-- ) if (host[diff] == '.') return FALSE; } } return TRUE;}/* * Strip of the filename from a full path */static char *Cookies_strip_path(const char *path){ char *ret; guint len; if (path) { len = strlen(path); while (len && path[len] != '/') len--; ret = g_strndup(path, len + 1); } else { ret = g_strdup("/"); } return ret;}/* * Set the value corresponding to the cookie string */void Cookies_set(gchar *cookie_string, gchar *url_host, gchar *url_path, gint url_port){ CookieControlAction action; GSList *list; if (disabled) return; action = Cookies_control_check_domain(url_host); if (action == COOKIE_DENY) { MSG("denied SET for %s\n", url_host); return; } list = Cookies_parse_string(url_port, cookie_string); while (list) { CookieData_t *cookie = list->data; if (Cookies_validate_domain(cookie, url_host, url_path)) { if (action == COOKIE_ACCEPT_SESSION) cookie->session_only = TRUE; Cookies_add_cookie(cookie); } else { MSG("Rejecting cookie for %s from host %s path %s\n", cookie->domain, url_host, url_path); Cookies_free_cookie(cookie); } list = g_slist_remove(list, list->data); }}/* * Compare the cookie with the supplied data to see if it matches */static gboolean Cookies_match(CookieData_t *cookie, gint port, const char *path, gboolean is_ssl){ /* Insecure cookies matches both secure and insecure urls, secure cookies matches only secure urls */ if (cookie->secure && !is_ssl) return FALSE; /* Check that the cookie path is a subpath of the current path */ if (strncmp(cookie->path, path, strlen(cookie->path)) != 0) return FALSE; /* Check if the port of the request URL matches any * of those set in the cookie */ if (cookie->ports) { GList *list; for (list = cookie->ports; list; list = g_list_next(list)) { if (GPOINTER_TO_INT(list->data) == port) return TRUE; } return FALSE; } /* It's a match */ return TRUE;}/* * Return a string that contains all relevant cookies as headers. */char *Cookies_get(gchar *url_host, gchar *url_path, gchar *url_scheme, gint url_port){ char *domain_string, *q, *str, *path; CookieData_t *cookie; GList *matching_cookies = NULL; GList *domain_cookie; gboolean is_ssl; GString *cookie_gstring; if (disabled) return g_strdup(""); path = Cookies_strip_path(url_path); /* Check if the protocol is secure or not */ is_ssl = (!g_strcasecmp(url_scheme, "https")); for (domain_string = (char *) url_host; domain_string != NULL && *domain_string; domain_string = strchr(domain_string+1, '.')) { domain_cookie = g_hash_table_lookup(cookies, domain_string); while (domain_cookie) { cookie = domain_cookie->data; domain_cookie = g_list_next(domain_cookie); /* Remove expired cookie. */ if (!cookie->session_only && cookie->expires_at < time(NULL)) { Cookies_remove_cookie(cookie); continue; } /* Check if the cookie matches the requesting URL */ if (Cookies_match(cookie, url_port, path, is_ssl)) matching_cookies = g_list_append(matching_cookies, cookie); } } /* Found the cookies, now make the string */ cookie_gstring = g_string_new(""); if (matching_cookies != NULL) { CookieData_t *first_cookie = matching_cookies->data; g_string_sprintfa(cookie_gstring, "Cookie: "); if (first_cookie->version != 0) g_string_sprintfa(cookie_gstring, "$Version=\"%d\"; ", first_cookie->version); while (matching_cookies) { cookie = matching_cookies->data; q = (cookie->version == 0 ? "" : "\""); g_string_sprintfa(cookie_gstring, "%s=%s; $Path=%s%s%s; $Domain=%s%s%s", cookie->name, cookie->value, q, cookie->path, q, q, cookie->domain, q); if (cookie->ports) { char *ports_str = Cookies_build_ports_str(cookie); g_string_sprintfa(cookie_gstring, "; $Port=%s", ports_str); g_free(ports_str); } matching_cookies = g_list_next(matching_cookies); g_string_append(cookie_gstring, matching_cookies ? "; " : "\r\n"); } } g_free(path); str = cookie_gstring->str; g_string_free(cookie_gstring, FALSE); return str;}/* ------------------------------------------------------------- * Access control routines * ------------------------------------------------------------- *//* * Get the cookie control rules (from cookiesrc). * Return value: * 0 = Parsed OK, with cookies enabled * 1 = Parsed OK, with cookies disabled * 2 = Can't open the control file */static int Cookie_control_init(void){ CookieControl cc; FILE *stream; char *filename; char line[LINE_MAXLEN]; char domain[LINE_MAXLEN]; char rule[LINE_MAXLEN]; int i, j; gboolean enabled = FALSE; /* Get a file pointer */ filename = g_strconcat(g_get_home_dir(), "/", ".dillo/cookiesrc", NULL); stream = Cookies_fopen(filename, "DEFAULT DENY\n"); g_free(filename); if (!stream) return 2; /* Get all lines in the file */ while (!feof(stream)) { line[0] = '\0'; fgets(line, LINE_MAXLEN, stream); /* Remove leading and trailing whitespaces */ g_strstrip(line); if (line[0] != '\0' && line[0] != '#') { i = 0; j = 0; /* Get the domain */ while (!isspace(line[i])) domain[j++] = line[i++]; domain[j] = '\0'; /* Skip past whitespaces */ i++; while (isspace(line[i])) i++; /* Get the rule */ j = 0; while (line[i] != '\0' && !isspace(line[i])) rule[j++] = line[i++]; rule[j] = '\0'; if (g_strcasecmp(rule, "ACCEPT") == 0) cc.action = COOKIE_ACCEPT; else if (g_strcasecmp(rule, "ACCEPT_SESSION") == 0) cc.action = COOKIE_ACCEPT_SESSION; else if (g_strcasecmp(rule, "DENY") == 0) cc.action = COOKIE_DENY; else { MSG("Cookies: rule '%s' for domain '%s' is not recognised.\n", rule, domain); continue; } cc.domain = g_strdup(domain); if (g_strcasecmp(cc.domain, "DEFAULT") == 0) { /* Set the default action */ default_action = cc.action; g_free(cc.domain); } else { a_List_add(ccontrol, num_ccontrol, num_ccontrol_max); ccontrol[num_ccontrol++] = cc; } if (cc.action != COOKIE_DENY) enabled = TRUE; } } fclose(stream); return (enabled ? 0 : 1);}/* * Check the rules for an appropriate action for this domain */static CookieControlAction Cookies_control_check_domain(const char *domain){ int i, diff; for (i = 0; i < num_ccontrol; i++) { if (ccontrol[i].domain[0] == '.') { diff = strlen(domain) - strlen(ccontrol[i].domain); if (diff >= 0) { if (g_strcasecmp(domain + diff, ccontrol[i].domain) != 0) continue; } else { continue; } } else { if (g_strcasecmp(domain, ccontrol[i].domain) != 0) continue; } /* If we got here we have a match */ return( ccontrol[i].action ); } return default_action;}/* -- Dpi parser ----------------------------------------------------------- *//* * Parse a data stream (dpi protocol) * Note: Buf is a zero terminated string * Return code: { 0:OK, 1:Abort, 2:Close } */static int srv_parse_buf(SockHandler *sh, char *Buf, size_t BufSize){ char *p, *cmd, *cookie, *host, *path, *scheme; gint port; if (!(p = strchr(Buf, '>'))) { /* Haven't got a full tag */ MSG("Haven't got a full tag!\n"); return 1; } cmd = a_Dpip_get_attr(Buf, BufSize, "cmd"); if (cmd && strcmp(cmd, "DpiBye") == 0) { g_free(cmd); MSG("Cookies dpi (pid %d): Got DpiBye.\n", (gint)getpid()); exit(0); } else if (cmd && strcmp(cmd, "set_cookie") == 0) { g_free(cmd); cookie = a_Dpip_get_attr(Buf, BufSize, "cookie"); host = a_Dpip_get_attr(Buf, BufSize, "host"); path = a_Dpip_get_attr(Buf, BufSize, "path"); p = a_Dpip_get_attr(Buf, BufSize, "port"); port = strtol(p, NULL, 10); g_free(p); Cookies_set(cookie, host, path, port); g_free(path); g_free(host); g_free(cookie); return 2; } else if (cmd && strcmp(cmd, "get_cookie") == 0) { g_free(cmd); scheme = a_Dpip_get_attr(Buf, BufSize, "scheme"); host = a_Dpip_get_attr(Buf, BufSize, "host"); path = a_Dpip_get_attr(Buf, BufSize, "path"); p = a_Dpip_get_attr(Buf, BufSize, "port"); port = strtol(p, NULL, 10); g_free(p); cookie = Cookies_get(host, path, scheme, port); g_free(scheme); g_free(path); g_free(host); cmd = a_Dpip_build_cmd("cmd=%s cookie=%s", "get_cookie_answer", cookie); if (sock_handler_write_str(sh, cmd, 1)) { g_free(cookie); g_free(cmd); return 1; } g_free(cookie); g_free(cmd); return 2; } return 0;}/* -- Termination handlers ----------------------------------------------- *//* * (was to delete the local namespace socket), * but this is handled by 'dpid' now. */static void cleanup(void){ Cookies_freeall(); MSG("cleanup\n"); /* no more cleanup required */}/* * Perform any necessary cleanups upon abnormal termination */static void termination_handler(int signum){ exit(signum);}/* * -- MAIN ------------------------------------------------------------------- */int main (void) { struct sockaddr_un spun; int temp_sock_descriptor; int address_size; char *buf; int code; SockHandler *sh; /* Arrange the cleanup function for terminations via exit() */ atexit(cleanup); /* Arrange the cleanup function for abnormal terminations */ if (signal (SIGINT, termination_handler) == SIG_IGN) signal (SIGINT, SIG_IGN); if (signal (SIGHUP, termination_handler) == SIG_IGN) signal (SIGHUP, SIG_IGN); if (signal (SIGTERM, termination_handler) == SIG_IGN) signal (SIGTERM, SIG_IGN); Cookies_init(); MSG("(v.1) accepting connections...\n"); if (disabled) exit(1); /* some OSes may need this... */ address_size = sizeof(struct sockaddr_un); while (1) { temp_sock_descriptor = accept(STDIN_FILENO, (struct sockaddr *)&spun, &address_size); if (temp_sock_descriptor == -1) { perror("[accept]"); exit(1); } /* create the SockHandler structure */ sh = sock_handler_new(temp_sock_descriptor,temp_sock_descriptor,8*1024); while (1) { code = 1; if ((buf = sock_handler_read(sh)) != NULL) { /* Let's see what we fished... */ code = srv_parse_buf(sh, buf, strlen(buf)); } if (code == 1) exit(1); else if (code == 2) break; } _MSG("Closing SockHandler\n"); sock_handler_close(sh); sock_handler_free(sh); }/*while*/}#endif /* !DISABLE_COOKIES */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -