about summary refs log tree commit diff stats
path: root/cookie.c
diff options
context:
space:
mode:
authormarco <marco@conformal.com>2011-11-02 17:46:44 -0500
committermarco <marco@conformal.com>2011-11-02 17:46:44 -0500
commit495b08e32d7e55f2e77295269f457eeb9caae676 (patch)
tree469b37260804594564bf92872ee3c5a4c8d46799 /cookie.c
parentaceea683ab3a019002265bd41d50874a5493ad97 (diff)
downloadxombrero-495b08e32d7e55f2e77295269f457eeb9caae676.tar.gz
move cookies to own file
Diffstat (limited to 'cookie.c')
-rw-r--r--cookie.c231
1 files changed, 231 insertions, 0 deletions
diff --git a/cookie.c b/cookie.c
new file mode 100644
index 0000000..5712549
--- /dev/null
+++ b/cookie.c
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2010, 2011 Marco Peereboom <marco@peereboom.us>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "xxxterm.h"
+
+#define XT_REJECT_FILE		("rejected.txt")
+#define XT_COOKIE_FILE		("cookies.txt")
+
+/* hooked functions */
+void		(*_soup_cookie_jar_add_cookie)(SoupCookieJar *, SoupCookie *);
+void		(*_soup_cookie_jar_delete_cookie)(SoupCookieJar *,
+		    SoupCookie *);
+
+void
+print_cookie(char *msg, SoupCookie *c)
+{
+	if (c == NULL)
+		return;
+
+	if (msg)
+		DNPRINTF(XT_D_COOKIE, "%s\n", msg);
+	DNPRINTF(XT_D_COOKIE, "name     : %s\n", c->name);
+	DNPRINTF(XT_D_COOKIE, "value    : %s\n", c->value);
+	DNPRINTF(XT_D_COOKIE, "domain   : %s\n", c->domain);
+	DNPRINTF(XT_D_COOKIE, "path     : %s\n", c->path);
+	DNPRINTF(XT_D_COOKIE, "expires  : %s\n",
+	    c->expires ? soup_date_to_string(c->expires, SOUP_DATE_HTTP) : "");
+	DNPRINTF(XT_D_COOKIE, "secure   : %d\n", c->secure);
+	DNPRINTF(XT_D_COOKIE, "http_only: %d\n", c->http_only);
+	DNPRINTF(XT_D_COOKIE, "====================================\n");
+}
+
+void
+set_hook(void **hook, char *name)
+{
+	if (hook == NULL)
+		errx(1, "set_hook");
+
+	if (*hook == NULL) {
+		*hook = dlsym(RTLD_NEXT, name);
+		if (*hook == NULL)
+			errx(1, "can't hook %s", name);
+	}
+}
+
+/* override libsoup soup_cookie_equal because it doesn't look at domain */
+gboolean
+soup_cookie_equal(SoupCookie *cookie1, SoupCookie *cookie2)
+{
+	g_return_val_if_fail(cookie1, FALSE);
+	g_return_val_if_fail(cookie2, FALSE);
+
+	return (!strcmp (cookie1->name, cookie2->name) &&
+	    !strcmp (cookie1->value, cookie2->value) &&
+	    !strcmp (cookie1->path, cookie2->path) &&
+	    !strcmp (cookie1->domain, cookie2->domain));
+}
+
+void
+transfer_cookies(void)
+{
+	GSList			*cf;
+	SoupCookie		*sc, *pc;
+
+	cf = soup_cookie_jar_all_cookies(p_cookiejar);
+
+	for (;cf; cf = cf->next) {
+		pc = cf->data;
+		sc = soup_cookie_copy(pc);
+		_soup_cookie_jar_add_cookie(s_cookiejar, sc);
+	}
+
+	soup_cookies_free(cf);
+}
+
+void
+soup_cookie_jar_delete_cookie(SoupCookieJar *jar, SoupCookie *c)
+{
+	GSList			*cf;
+	SoupCookie		*ci;
+
+	print_cookie("soup_cookie_jar_delete_cookie", c);
+
+	if (cookies_enabled == 0)
+		return;
+
+	if (jar == NULL || c == NULL)
+		return;
+
+	/* find and remove from persistent jar */
+	cf = soup_cookie_jar_all_cookies(p_cookiejar);
+
+	for (;cf; cf = cf->next) {
+		ci = cf->data;
+		if (soup_cookie_equal(ci, c)) {
+			_soup_cookie_jar_delete_cookie(p_cookiejar, ci);
+			break;
+		}
+	}
+
+	soup_cookies_free(cf);
+
+	/* delete from session jar */
+	_soup_cookie_jar_delete_cookie(s_cookiejar, c);
+}
+
+void
+soup_cookie_jar_add_cookie(SoupCookieJar *jar, SoupCookie *cookie)
+{
+	struct domain		*d = NULL;
+	SoupCookie		*c;
+	FILE			*r_cookie_f;
+
+	DNPRINTF(XT_D_COOKIE, "soup_cookie_jar_add_cookie: %p %p %p\n",
+	    jar, p_cookiejar, s_cookiejar);
+
+	if (cookies_enabled == 0)
+		return;
+
+	/* see if we are up and running */
+	if (p_cookiejar == NULL) {
+		_soup_cookie_jar_add_cookie(jar, cookie);
+		return;
+	}
+	/* disallow p_cookiejar adds, shouldn't happen */
+	if (jar == p_cookiejar)
+		return;
+
+	/* sanity */
+	if (jar == NULL || cookie == NULL)
+		return;
+
+	if (enable_cookie_whitelist &&
+	    (d = wl_find(cookie->domain, &c_wl)) == NULL) {
+		blocked_cookies++;
+		DNPRINTF(XT_D_COOKIE,
+		    "soup_cookie_jar_add_cookie: reject %s\n",
+		    cookie->domain);
+		if (save_rejected_cookies) {
+			if ((r_cookie_f = fopen(rc_fname, "a+")) == NULL) {
+				show_oops(NULL, "can't open reject cookie file");
+				return;
+			}
+			fseek(r_cookie_f, 0, SEEK_END);
+			fprintf(r_cookie_f, "%s%s\t%s\t%s\t%s\t%lu\t%s\t%s\n",
+			    cookie->http_only ? "#HttpOnly_" : "",
+			    cookie->domain,
+			    *cookie->domain == '.' ? "TRUE" : "FALSE",
+			    cookie->path,
+			    cookie->secure ? "TRUE" : "FALSE",
+			    cookie->expires ?
+			        (gulong)soup_date_to_time_t(cookie->expires) :
+			        0,
+			    cookie->name,
+			    cookie->value);
+			fflush(r_cookie_f);
+			fclose(r_cookie_f);
+		}
+		if (!allow_volatile_cookies)
+			return;
+	}
+
+	if (cookie->expires == NULL && session_timeout) {
+		soup_cookie_set_expires(cookie,
+		    soup_date_new_from_now(session_timeout));
+		print_cookie("modified add cookie", cookie);
+	}
+
+	/* see if we are white listed for persistence */
+	if ((d && d->handy) || (enable_cookie_whitelist == 0)) {
+		/* add to persistent jar */
+		c = soup_cookie_copy(cookie);
+		print_cookie("soup_cookie_jar_add_cookie p_cookiejar", c);
+		_soup_cookie_jar_add_cookie(p_cookiejar, c);
+	}
+
+	/* add to session jar */
+	print_cookie("soup_cookie_jar_add_cookie s_cookiejar", cookie);
+	_soup_cookie_jar_add_cookie(s_cookiejar, cookie);
+}
+
+void
+setup_cookies(void)
+{
+	char			file[PATH_MAX];
+
+	set_hook((void *)&_soup_cookie_jar_add_cookie,
+	    "soup_cookie_jar_add_cookie");
+	set_hook((void *)&_soup_cookie_jar_delete_cookie,
+	    "soup_cookie_jar_delete_cookie");
+
+	if (cookies_enabled == 0)
+		return;
+
+	/*
+	 * the following code is intricate due to overriding several libsoup
+	 * functions.
+	 * do not alter order of these operations.
+	 */
+
+	/* rejected cookies */
+	if (save_rejected_cookies)
+		snprintf(rc_fname, sizeof file, "%s/%s", work_dir,
+		    XT_REJECT_FILE);
+
+	/* persistent cookies */
+	snprintf(file, sizeof file, "%s/%s", work_dir, XT_COOKIE_FILE);
+	p_cookiejar = soup_cookie_jar_text_new(file, read_only_cookies);
+
+	/* session cookies */
+	s_cookiejar = soup_cookie_jar_new();
+	g_object_set(G_OBJECT(s_cookiejar), SOUP_COOKIE_JAR_ACCEPT_POLICY,
+	    cookie_policy, (void *)NULL);
+	transfer_cookies();
+
+	soup_session_add_feature(session, (SoupSessionFeature*)s_cookiejar);
+}
+