summaryrefslogtreecommitdiff
path: root/content
diff options
context:
space:
mode:
authorJohn Mark Bell <jmb@netsurf-browser.org>2007-01-27 20:58:20 +0000
committerJohn Mark Bell <jmb@netsurf-browser.org>2007-01-27 20:58:20 +0000
commitdf4dbaf4cfebf0b8b5ec9ae7d0bf6ae467609a4e (patch)
tree8668484e194b0f7cb6fbc169f04e0cae2d85374a /content
parentcd98970628e9cfcea702df8038ed653a8d1ea6a2 (diff)
downloadnetsurf-df4dbaf4cfebf0b8b5ec9ae7d0bf6ae467609a4e.tar.gz
netsurf-df4dbaf4cfebf0b8b5ec9ae7d0bf6ae467609a4e.tar.bz2
Handle cookies in unverifiable transactions
svn path=/trunk/netsurf/; revision=3151
Diffstat (limited to 'content')
-rw-r--r--content/content.c3
-rw-r--r--content/fetch.c63
-rw-r--r--content/fetch.h7
-rw-r--r--content/fetchcache.c33
-rw-r--r--content/fetchcache.h6
-rw-r--r--content/urldb.c52
-rw-r--r--content/urldb.h5
7 files changed, 121 insertions, 48 deletions
diff --git a/content/content.c b/content/content.c
index d211bb109..8af888699 100644
--- a/content/content.c
+++ b/content/content.c
@@ -565,7 +565,8 @@ bool content_set_type(struct content *c, content_type type,
}
content_remove_user(c, callback, p1, p2);
content_broadcast(clone, CONTENT_MSG_NEWPTR, msg_data);
- fetchcache_go(clone, 0, callback, p1, p2,
+ fetchcache_go(clone, fetch_get_referer(c->fetch),
+ callback, p1, p2,
clone->width, clone->height,
0, 0, false);
}
diff --git a/content/fetch.c b/content/fetch.c
index 0842d3cc4..ed1431741 100644
--- a/content/fetch.c
+++ b/content/fetch.c
@@ -64,9 +64,10 @@ struct fetch {
bool abort; /**< Abort requested. */
bool stopped; /**< Download stopped on purpose. */
bool only_2xx; /**< Only HTTP 2xx responses acceptable. */
- bool cookies; /**< Send & accept cookies. */
+ bool verifiable; /**< Transaction is verifiable */
char *url; /**< URL. */
char *referer; /**< URL for Referer header. */
+ bool send_referer; /**< Valid to send the referer */
void *p; /**< Private data for callback. */
struct curl_slist *headers; /**< List of request headers. */
char *host; /**< Host part of URL. */
@@ -299,12 +300,12 @@ void fetch_quit(void)
* callbacks will contain this.
*/
-struct fetch * fetch_start(char *url, char *referer,
+struct fetch * fetch_start(const char *url, const char *referer,
void (*callback)(fetch_msg msg, void *p, const void *data,
unsigned long size),
- void *p, bool only_2xx, char *post_urlenc,
- struct form_successful_control *post_multipart, bool cookies,
- char *headers[])
+ void *p, bool only_2xx, const char *post_urlenc,
+ struct form_successful_control *post_multipart,
+ bool verifiable, char *headers[])
{
char *host;
struct fetch *fetch;
@@ -355,13 +356,16 @@ struct fetch * fetch_start(char *url, char *referer,
fetch->abort = false;
fetch->stopped = false;
fetch->only_2xx = only_2xx;
- fetch->cookies = cookies;
+ fetch->verifiable = verifiable;
fetch->url = strdup(url);
fetch->referer = 0;
+ fetch->send_referer = false;
/* only send the referer if the schemes match */
if (referer) {
- if (ref1 && ref2 && strcasecmp(ref1, ref2) == 0)
- fetch->referer = strdup(referer);
+ fetch->referer = strdup(referer);
+ if (option_send_referer && ref1 && ref2 &&
+ strcasecmp(ref1, ref2) == 0)
+ fetch->send_referer = true;
}
fetch->p = p;
fetch->headers = 0;
@@ -394,9 +398,7 @@ struct fetch * fetch_start(char *url, char *referer,
fetch->r_prev = 0;
fetch->r_next = 0;
- if (!fetch->url || (referer &&
- (ref1 && ref2 && strcasecmp(ref1, ref2) == 0) &&
- !fetch->referer) ||
+ if (!fetch->url || (referer && !fetch->referer) ||
(post_urlenc && !fetch->post_urlenc) ||
(post_multipart && !fetch->post_multipart))
goto failed;
@@ -647,7 +649,7 @@ CURLcode fetch_set_options(struct fetch *f)
SETOPT(CURLOPT_WRITEDATA, f);
SETOPT(CURLOPT_WRITEHEADER, f);
SETOPT(CURLOPT_PROGRESSDATA, f);
- SETOPT(CURLOPT_REFERER, f->referer);
+ SETOPT(CURLOPT_REFERER, f->send_referer ? f->referer : 0);
SETOPT(CURLOPT_HTTPHEADER, f->headers);
if (f->post_urlenc) {
SETOPT(CURLOPT_POSTFIELDS, f->post_urlenc);
@@ -656,11 +658,11 @@ CURLcode fetch_set_options(struct fetch *f)
} else {
SETOPT(CURLOPT_HTTPGET, 1L);
}
- if (f->cookies) {
- f->cookie_string = urldb_get_cookie(f->url, f->referer);
- if (f->cookie_string)
- SETOPT(CURLOPT_COOKIE, f->cookie_string);
- }
+
+ f->cookie_string = urldb_get_cookie(f->url);
+ if (f->cookie_string)
+ SETOPT(CURLOPT_COOKIE, f->cookie_string);
+
#ifdef WITH_AUTH
if ((auth = urldb_get_auth_details(f->url)) != NULL) {
SETOPT(CURLOPT_HTTPAUTH, CURLAUTH_ANY);
@@ -1212,11 +1214,20 @@ size_t fetch_curl_header(char *data, size_t size, size_t nmemb,
f->cachedata.last_modified =
curl_getdate(&data[i], NULL);
}
- } else if (f->cookies && 11 < size &&
- strncasecmp(data, "Set-Cookie:", 11) == 0) {
+ } else if (11 < size && strncasecmp(data, "Set-Cookie:", 11) == 0) {
/* extract Set-Cookie header */
SKIP_ST(11);
- urldb_set_cookie(&data[i], f->url);
+
+ /* If the fetch is unverifiable and there's no referer,
+ * err on the side of caution and do not set the cookie */
+
+ if (f->verifiable || f->referer) {
+ /* If the transaction's verifiable, we don't require
+ * that the request uri and the referer domain match,
+ * so don't pass in the referer in this case. */
+ urldb_set_cookie(&data[i], f->url,
+ f->verifiable ? 0 : f->referer);
+ }
}
return size;
@@ -1454,6 +1465,18 @@ long fetch_http_code(struct fetch *fetch)
}
+/**
+ * Get the referer
+ *
+ * \param fetch fetch to retrieve referer from
+ * \return Pointer to referer string, or NULL if none.
+ */
+const char *fetch_get_referer(struct fetch *fetch)
+{
+ return fetch->referer;
+}
+
+
#ifdef WITH_SSL
/**
* OpenSSL Certificate verification callback
diff --git a/content/fetch.h b/content/fetch.h
index 331207fe2..847d16abf 100644
--- a/content/fetch.h
+++ b/content/fetch.h
@@ -66,12 +66,12 @@ extern bool fetch_active;
extern CURLM *fetch_curl_multi;
void fetch_init(void);
-struct fetch * fetch_start(char *url, char *referer,
+struct fetch * fetch_start(const char *url, const char *referer,
void (*callback)(fetch_msg msg, void *p, const void *data,
unsigned long size),
- void *p, bool only_2xx, char *post_urlenc,
+ void *p, bool only_2xx, const char *post_urlenc,
struct form_successful_control *post_multipart,
- bool cookies, char *headers[]);
+ bool verifiable, char *headers[]);
void fetch_abort(struct fetch *f);
void fetch_poll(void);
void fetch_quit(void);
@@ -83,5 +83,6 @@ void fetch_change_callback(struct fetch *fetch,
unsigned long size),
void *p);
long fetch_http_code(struct fetch *fetch);
+const char *fetch_get_referer(struct fetch *fetch);
#endif
diff --git a/content/fetchcache.c b/content/fetchcache.c
index 0a630661b..0a7e34c2d 100644
--- a/content/fetchcache.c
+++ b/content/fetchcache.c
@@ -58,7 +58,7 @@ static void fetchcache_notmodified(struct content *c, const void *data);
* of generating an error page
* \param post_urlenc url encoded post data, or 0 if none
* \param post_multipart multipart post data, or 0 if none
- * \param cookies send and accept cookies
+ * \param verifiable this transaction is verifiable
* \param download download, rather than render content
* \return a new content, or 0 on memory exhaustion
*
@@ -73,7 +73,7 @@ struct content * fetchcache(const char *url,
bool no_error_pages,
char *post_urlenc,
struct form_successful_control *post_multipart,
- bool cookies,
+ bool verifiable,
bool download)
{
struct content *c;
@@ -202,19 +202,19 @@ struct content * fetchcache(const char *url,
* \param height available space
* \param post_urlenc url encoded post data, or 0 if none
* \param post_multipart multipart post data, or 0 if none
- * \param cookies send and accept cookies
+ * \param verifiable this transaction is verifiable
*
* Errors will be sent back through the callback.
*/
-void fetchcache_go(struct content *content, char *referer,
+void fetchcache_go(struct content *content, const char *referer,
void (*callback)(content_msg msg, struct content *c,
intptr_t p1, intptr_t p2, union content_msg_data data),
intptr_t p1, intptr_t p2,
int width, int height,
char *post_urlenc,
struct form_successful_control *post_multipart,
- bool cookies)
+ bool verifiable)
{
char error_message[500];
union content_msg_data msg_data;
@@ -307,7 +307,7 @@ void fetchcache_go(struct content *content, char *referer,
content->fetch = fetch_start(content->url, referer,
fetchcache_callback, content,
content->no_error_pages,
- post_urlenc, post_multipart, cookies,
+ post_urlenc, post_multipart, verifiable,
headers);
for (i = 0; headers[i]; i++)
free(headers[i]);
@@ -745,6 +745,20 @@ void fetchcache_notmodified(struct content *c, const void *data)
else {
/* No cached content, so unconditionally refetch */
struct content_user *u;
+ const char *ref = fetch_get_referer(c->fetch);
+ char *referer = NULL;
+
+ if (ref) {
+ referer = strdup(ref);
+ if (!referer) {
+ c->type = CONTENT_UNKNOWN;
+ c->status = CONTENT_STATUS_ERROR;
+ msg_data.error = messages_get("NoMemory");
+ content_broadcast(c, CONTENT_MSG_ERROR,
+ msg_data);
+ return;
+ }
+ }
fetch_abort(c->fetch);
c->fetch = 0;
@@ -754,9 +768,12 @@ void fetchcache_notmodified(struct content *c, const void *data)
c->cache_data->etag = 0;
for (u = c->user_list->next; u; u = u->next) {
- fetchcache_go(c, 0, u->callback, u->p1, u->p2,
- c->width, c->height, 0, 0, false);
+ fetchcache_go(c, referer, u->callback, u->p1, u->p2,
+ c->width, c->height, 0, 0,
+ false);
}
+
+ free(referer);
}
}
diff --git a/content/fetchcache.h b/content/fetchcache.h
index 76537cd93..43a6649fe 100644
--- a/content/fetchcache.h
+++ b/content/fetchcache.h
@@ -30,15 +30,15 @@ struct content * fetchcache(const char *url,
bool no_error_pages,
char *post_urlenc,
struct form_successful_control *post_multipart,
- bool cookies,
+ bool verifiable,
bool download);
-void fetchcache_go(struct content *content, char *referer,
+void fetchcache_go(struct content *content, const char *referer,
void (*callback)(content_msg msg, struct content *c,
intptr_t p1, intptr_t p2, union content_msg_data data),
intptr_t p1, intptr_t p2,
int width, int height,
char *post_urlenc,
struct form_successful_control *post_multipart,
- bool cookies);
+ bool verifiable);
#endif
diff --git a/content/urldb.c b/content/urldb.c
index 4a6682e29..7d7b5aa15 100644
--- a/content/urldb.c
+++ b/content/urldb.c
@@ -2336,12 +2336,9 @@ struct search_node *urldb_search_split(struct search_node *root)
* Retrieve cookies for an URL
*
* \param url URL being fetched
- * \param referer Referring resource, or NULL
* \return Cookies string for libcurl (on heap), or NULL on error/no cookies
- *
- * \todo Handle unvalidated fetches
*/
-char *urldb_get_cookie(const char *url, const char *referer)
+char *urldb_get_cookie(const char *url)
{
const struct path_data *p, *q;
const struct host_part *h;
@@ -2356,11 +2353,7 @@ char *urldb_get_cookie(const char *url, const char *referer)
assert(url);
-// LOG(("%s : %s", url, referer));
-
-// if (referer)
-// /* No unvalidated fetches for now */
-// return NULL;
+// LOG(("%s", url));
urldb_add_url(url);
@@ -2455,7 +2448,8 @@ char *urldb_get_cookie(const char *url, const char *referer)
version = c->version;
c->last_used = now;
- cookies_update(c->domain, (struct cookie_data *)c);
+ cookies_update(c->domain,
+ (struct cookie_data *)c);
count++;
}
}
@@ -2577,9 +2571,11 @@ char *urldb_get_cookie(const char *url, const char *referer)
*
* \param header Header to parse, with Set-Cookie: stripped
* \param url URL being fetched
+ * \param referer Referring resource, or 0 for verifiable transaction
* \return true on success, false otherwise
*/
-bool urldb_set_cookie(const char *header, const char *url)
+bool urldb_set_cookie(const char *header, const char *url,
+ const char *referer)
{
const char *cur = header, *end;
char *path, *host, *scheme, *urlt;
@@ -2616,6 +2612,40 @@ bool urldb_set_cookie(const char *header, const char *url)
return false;
}
+ if (referer) {
+ char *rhost, *rscheme;
+
+ /* Ensure that url's host name domain matches
+ * referer's (4.3.5) */
+ res = url_scheme(referer, &rscheme);
+ if (res != URL_FUNC_OK) {
+ goto error;
+ }
+
+ res = url_host(referer, &rhost);
+ if (res != URL_FUNC_OK) {
+ free(rscheme);
+ goto error;
+ }
+
+ if (strcasecmp(scheme, rscheme) != 0) {
+ /* Schemes don't match => fail */
+ free(rhost);
+ free(rscheme);
+ goto error;
+ }
+
+ /* Domain match host names (both are FQDN or IP) */
+ if (strcasecmp(host, rhost) != 0) {
+ free(rhost);
+ free(rscheme);
+ goto error;
+ }
+
+ free(rhost);
+ free(rscheme);
+ }
+
end = cur + strlen(cur) - 2 /* Trailing CRLF */;
do {
diff --git a/content/urldb.h b/content/urldb.h
index f71471e6c..adf13c11b 100644
--- a/content/urldb.h
+++ b/content/urldb.h
@@ -98,8 +98,9 @@ void urldb_iterate_cookies(bool (*callback)(const char *domain,
void urldb_dump(void);
/* Cookies */
-bool urldb_set_cookie(const char *header, const char *url);
-char *urldb_get_cookie(const char *url, const char *referer);
+bool urldb_set_cookie(const char *header, const char *url,
+ const char *referer);
+char *urldb_get_cookie(const char *url);
void urldb_delete_cookie(const char *domain, const char *path, const char *name);
void urldb_load_cookies(const char *filename);
void urldb_save_cookies(const char *filename);