Commit 6c76c9ba authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

http cookies: take explicit secure flag, host and path

There is no need for a full URL structure here, and it is sometimes
inconvenient to require one.
parent 50387530
...@@ -78,10 +78,13 @@ VLC_API void vlc_http_cookies_destroy( vlc_http_cookie_jar_t * p_jar ); ...@@ -78,10 +78,13 @@ VLC_API void vlc_http_cookies_destroy( vlc_http_cookie_jar_t * p_jar );
* Parse a value of an incoming Set-Cookie header and append the * Parse a value of an incoming Set-Cookie header and append the
* cookie to the cookie jar if appropriate. * cookie to the cookie jar if appropriate.
* *
* @param p_jar cookie jar object * @param jar cookie jar object
* @param psz_cookie_header value of Set-Cookie * @param cookie header field value of Set-Cookie
* @return true, if the cookie was added, false otherwise * @return true, if the cookie was added, false otherwise
*/ */
VLC_API bool vlc_http_cookies_store( vlc_http_cookie_jar_t *jar,
const char *cookie, bool secure, const char *host, const char *path );
VLC_API bool vlc_http_cookies_append( vlc_http_cookie_jar_t * p_jar, const char * psz_cookie_header, const vlc_url_t * p_url ); VLC_API bool vlc_http_cookies_append( vlc_http_cookie_jar_t * p_jar, const char * psz_cookie_header, const vlc_url_t * p_url );
/** /**
...@@ -91,6 +94,9 @@ VLC_API bool vlc_http_cookies_append( vlc_http_cookie_jar_t * p_jar, const char ...@@ -91,6 +94,9 @@ VLC_API bool vlc_http_cookies_append( vlc_http_cookie_jar_t * p_jar, const char
* @param p_url the URL for which the cookies are returned * @param p_url the URL for which the cookies are returned
* @return A string consisting of semicolon-separated cookie NAME=VALUE pairs. * @return A string consisting of semicolon-separated cookie NAME=VALUE pairs.
*/ */
VLC_API char *vlc_http_cookies_fetch( vlc_http_cookie_jar_t *jar, bool secure,
const char *host, const char *path );
VLC_API char *vlc_http_cookies_for_url( vlc_http_cookie_jar_t * p_jar, const vlc_url_t * p_url ); VLC_API char *vlc_http_cookies_for_url( vlc_http_cookie_jar_t * p_jar, const vlc_url_t * p_url );
#endif /* VLC_HTTP_H */ #endif /* VLC_HTTP_H */
...@@ -139,6 +139,8 @@ http_auth_ParseAuthenticationInfoHeader ...@@ -139,6 +139,8 @@ http_auth_ParseAuthenticationInfoHeader
http_auth_FormatAuthorizationHeader http_auth_FormatAuthorizationHeader
vlc_http_cookies_new vlc_http_cookies_new
vlc_http_cookies_destroy vlc_http_cookies_destroy
vlc_http_cookies_store
vlc_http_cookies_fetch
vlc_http_cookies_append vlc_http_cookies_append
vlc_http_cookies_for_url vlc_http_cookies_for_url
httpd_ClientIP httpd_ClientIP
......
...@@ -51,14 +51,14 @@ struct vlc_http_cookie_jar_t ...@@ -51,14 +51,14 @@ struct vlc_http_cookie_jar_t
vlc_mutex_t lock; vlc_mutex_t lock;
}; };
static http_cookie_t * cookie_parse( const char * cookie_header, const vlc_url_t * url ); static http_cookie_t * cookie_parse( const char *, const char *, const char * );
static void cookie_destroy( http_cookie_t * p_cookie ); static void cookie_destroy( http_cookie_t * p_cookie );
static char * cookie_get_content( const char * cookie ); static char * cookie_get_content( const char * cookie );
static char * cookie_get_domain( const char * cookie ); static char * cookie_get_domain( const char * cookie );
static char * cookie_get_attribute_value( const char * cookie, const char *attr ); static char * cookie_get_attribute_value( const char * cookie, const char *attr );
static bool cookie_has_attribute( const char * cookie, const char *attr ); static bool cookie_has_attribute( const char * cookie, const char *attr );
static bool cookie_should_be_sent( const http_cookie_t * cookie, const vlc_url_t * url ); static bool cookie_should_be_sent(const http_cookie_t *, bool, const char *, const char *);
static bool cookie_is_valid( const http_cookie_t * cookie, const char *host ); static bool cookie_is_valid(const http_cookie_t *, bool, const char *, const char *);
static bool cookie_domain_matches( const http_cookie_t * cookie, const char *host ); static bool cookie_domain_matches( const http_cookie_t * cookie, const char *host );
static bool cookie_path_matches( const http_cookie_t * cookie, const char *path ); static bool cookie_path_matches( const http_cookie_t * cookie, const char *path );
static bool cookie_domain_is_public_suffix( const char *domain ); static bool cookie_domain_is_public_suffix( const char *domain );
...@@ -91,14 +91,20 @@ void vlc_http_cookies_destroy( vlc_http_cookie_jar_t * p_jar ) ...@@ -91,14 +91,20 @@ void vlc_http_cookies_destroy( vlc_http_cookie_jar_t * p_jar )
free( p_jar ); free( p_jar );
} }
bool vlc_http_cookies_append( vlc_http_cookie_jar_t * p_jar, const char * psz_cookie_header, const vlc_url_t *p_url ) bool vlc_http_cookies_store(vlc_http_cookie_jar_t *p_jar, const char *cookies,
bool secure, const char *host, const char *path)
{ {
assert(host != NULL);
assert(path != NULL);
int i; int i;
http_cookie_t *cookie = cookie_parse( psz_cookie_header, p_url ); http_cookie_t *cookie = cookie_parse(cookies, host, path);
if( !cookie || !cookie_is_valid( cookie, p_url->psz_host ) ) if (cookie == NULL)
return false;
if (!cookie_is_valid(cookie, secure, host, path))
{ {
cookie_destroy( cookie ); cookie_destroy(cookie);
return false; return false;
} }
...@@ -131,7 +137,25 @@ bool vlc_http_cookies_append( vlc_http_cookie_jar_t * p_jar, const char * psz_co ...@@ -131,7 +137,25 @@ bool vlc_http_cookies_append( vlc_http_cookie_jar_t * p_jar, const char * psz_co
return true; return true;
} }
char *vlc_http_cookies_for_url( vlc_http_cookie_jar_t * p_jar, const vlc_url_t * p_url ) bool vlc_http_cookies_append(vlc_http_cookie_jar_t *jar,
const char *cookies, const vlc_url_t *url)
{
bool secure;
if (url->psz_protocol == NULL || url->psz_host == NULL
|| url->psz_path == NULL)
return false;
else if (!vlc_ascii_strcasecmp(url->psz_protocol, "https"))
secure = true;
else
secure = false;
return vlc_http_cookies_store(jar, cookies, secure, url->psz_host,
url->psz_path);
}
char *vlc_http_cookies_fetch(vlc_http_cookie_jar_t *p_jar, bool secure,
const char *host, const char *path)
{ {
int i; int i;
char *psz_cookiebuf = NULL; char *psz_cookiebuf = NULL;
...@@ -141,7 +165,7 @@ char *vlc_http_cookies_for_url( vlc_http_cookie_jar_t * p_jar, const vlc_url_t * ...@@ -141,7 +165,7 @@ char *vlc_http_cookies_for_url( vlc_http_cookie_jar_t * p_jar, const vlc_url_t *
for( i = 0; i < vlc_array_count( &p_jar->cookies ); i++ ) for( i = 0; i < vlc_array_count( &p_jar->cookies ); i++ )
{ {
const http_cookie_t * cookie = vlc_array_item_at_index( &p_jar->cookies, i ); const http_cookie_t * cookie = vlc_array_item_at_index( &p_jar->cookies, i );
if ( cookie_should_be_sent( cookie, p_url ) ) if (cookie_should_be_sent(cookie, secure, host, path))
{ {
char *psz_updated_buf = NULL; char *psz_updated_buf = NULL;
if ( asprintf(&psz_updated_buf, "%s%s%s=%s", if ( asprintf(&psz_updated_buf, "%s%s%s=%s",
...@@ -165,13 +189,31 @@ char *vlc_http_cookies_for_url( vlc_http_cookie_jar_t * p_jar, const vlc_url_t * ...@@ -165,13 +189,31 @@ char *vlc_http_cookies_for_url( vlc_http_cookie_jar_t * p_jar, const vlc_url_t *
return psz_cookiebuf; return psz_cookiebuf;
} }
static http_cookie_t * cookie_parse( const char * cookie_header, const vlc_url_t * url ) char *vlc_http_cookies_for_url(vlc_http_cookie_jar_t *jar,
const vlc_url_t *url)
{
bool secure;
if (url->psz_protocol == NULL || url->psz_host == NULL
|| url->psz_path == NULL)
return NULL;
else if (!vlc_ascii_strcasecmp(url->psz_protocol, "https"))
secure = true;
else
secure = false;
return vlc_http_cookies_fetch(jar, secure, url->psz_host, url->psz_path);
}
static http_cookie_t *cookie_parse(const char *value,
const char *host, const char *path)
{ {
http_cookie_t *cookie = calloc( 1, sizeof( http_cookie_t ) ); http_cookie_t *cookie = calloc( 1, sizeof( http_cookie_t ) );
if ( unlikely( !cookie ) ) if ( unlikely( !cookie ) )
return NULL; return NULL;
char *content = cookie_get_content( cookie_header ); char *content = cookie_get_content(value);
if ( !content ) if ( !content )
{ {
cookie_destroy( cookie ); cookie_destroy( cookie );
...@@ -190,24 +232,24 @@ static http_cookie_t * cookie_parse( const char * cookie_header, const vlc_url_t ...@@ -190,24 +232,24 @@ static http_cookie_t * cookie_parse( const char * cookie_header, const vlc_url_t
cookie->psz_value = NULL; cookie->psz_value = NULL;
} }
cookie->psz_domain = cookie_get_domain( cookie_header ); cookie->psz_domain = cookie_get_domain(value);
if ( !cookie->psz_domain || strlen(cookie->psz_domain) == 0 ) if ( !cookie->psz_domain || strlen(cookie->psz_domain) == 0 )
{ {
free(cookie->psz_domain); free(cookie->psz_domain);
cookie->psz_domain = strdup( url->psz_host ); cookie->psz_domain = strdup(host);
cookie->b_host_only = true; cookie->b_host_only = true;
} }
else else
cookie->b_host_only = false; cookie->b_host_only = false;
cookie->psz_path = cookie_get_attribute_value( cookie_header, "path" ); cookie->psz_path = cookie_get_attribute_value(value, "path" );
if ( !cookie->psz_path || strlen(cookie->psz_path) == 0 ) if ( !cookie->psz_path || strlen(cookie->psz_path) == 0 )
{ {
free(cookie->psz_path); free(cookie->psz_path);
cookie->psz_path = cookie_default_path( url->psz_path ); cookie->psz_path = cookie_default_path(path);
} }
cookie->b_secure = cookie_has_attribute( cookie_header, "secure" ); cookie->b_secure = cookie_has_attribute(value, "secure" );
FREENULL( content ); FREENULL( content );
...@@ -299,17 +341,18 @@ static bool cookie_has_attribute( const char * cookie, const char *attr ) ...@@ -299,17 +341,18 @@ static bool cookie_has_attribute( const char * cookie, const char *attr )
return false; return false;
} }
static bool cookie_should_be_sent( const http_cookie_t * cookie, const vlc_url_t * url ) static bool cookie_should_be_sent(const http_cookie_t *cookie, bool secure,
const char *host, const char *path)
{ {
bool protocol_ok = !cookie->b_secure || bool protocol_ok = secure || !cookie->b_secure;
( url->psz_protocol && strcasecmp(url->psz_protocol, "https") == 0 ); bool domain_ok = cookie_domain_matches(cookie, host);
bool domain_ok = cookie_domain_matches( cookie, url->psz_host ); bool path_ok = cookie_path_matches(cookie, path);
bool path_ok = cookie_path_matches( cookie, url->psz_path );
return protocol_ok && domain_ok && path_ok; return protocol_ok && domain_ok && path_ok;
} }
/* Check if a cookie from host should be added to the cookie jar */ /* Check if a cookie from host should be added to the cookie jar */
static bool cookie_is_valid( const http_cookie_t * cookie, const char *host ) static bool cookie_is_valid(const http_cookie_t * cookie, bool secure,
const char *host, const char *path)
{ {
return cookie && cookie->psz_name && strlen(cookie->psz_name) > 0 && return cookie && cookie->psz_name && strlen(cookie->psz_name) > 0 &&
cookie->psz_domain && cookie->psz_domain &&
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment