Improve cookie support

This commit is contained in:
wbaumann 2014-04-18 19:59:48 +00:00
parent aebcb3c26f
commit 3d314d4b3d
10 changed files with 159 additions and 103 deletions

View File

@ -1,6 +1,10 @@
ChangeLog for davfs2
--------------------

2014-04-18 Werner Baumann (werner.baumann@onlinehome.de)
* defaults.h, mount_davfs.h, mount_davfs.c, webdav.c:
Improve cookie support (sr #107907, bug #41438).

2014-04-13 Werner Baumann (werner.baumann@onlinehome.de)
* cache.c, defaults.h, mount_davfs.c, mount_davfs.h:
Add mount option grpid (sr #108432, Thanks to

View File

@ -1,4 +1,4 @@
# davfs2 configuration file 2014-04-06
# davfs2 configuration file 2014-04-18
# version 12
# ------------------------------------

@ -41,7 +41,7 @@
# use_expect100 0
# if_match_bug 0
# drop_weak_etags 0
# allow_cookie 0
# n_cookies 0
# precheck 1
# ignore_dav_header 0
# use_compression 1

View File

@ -1,4 +1,4 @@
.TH @CONFIGFILE@ 5 2012\-02\-01 @PACKAGE_STRING@
.TH @CONFIGFILE@ 5 2014\-04\-18 @PACKAGE_STRING@


.SH NAME
@ -264,12 +264,12 @@ etag is not used at all and the resource cannot be cached.
Default: 0

.TP
.B allow_cookie
.B n_cookies
Some servers will only work when they are allowed to set a cookie and this
cookie is returned in subsequent requests. This option adds very simple
cookie support. It supports just one cookie which should usually be
a session ID.
0 = no, 1 = yes.
cookie is returned in subsequent requests. This option sets the number of
cookies you are willing to accept and include in subsequent requests. davfs2
will only care for the name and the value of the cookie and ignore all of
the possible attributes.
.br
Default: 0


View File

@ -7,7 +7,7 @@
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2014-04-06 18:16+0300\n"
"POT-Creation-Date: 2014-04-18 18:25+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -25,7 +25,7 @@ msgstr ""
#. type: TH
#: davfs2.conf.5:1
#, no-wrap
msgid "2012-02-01"
msgid "2014-04-18"
msgstr ""

#. type: TH
@ -550,16 +550,17 @@ msgstr ""
#. type: TP
#: davfs2.conf.5:266
#, no-wrap
msgid "B<allow_cookie>"
msgid "B<n_cookies>"
msgstr ""

#. type: Plain text
#: davfs2.conf.5:273
msgid ""
"Some servers will only work when they are allowed to set a cookie and this "
"cookie is returned in subsequent requests. This option adds very simple "
"cookie support. It supports just one cookie which should usually be a "
"session ID. 0 = no, 1 = yes."
"cookie is returned in subsequent requests. This option sets the number of "
"cookies you are willing to accept and include in subsequent requests. davfs2 "
"will only care for the name and the value of the cookie and ignore all of "
"the possible attributes."
msgstr ""

#. type: TP
@ -1088,7 +1089,7 @@ msgid "Includes config, kernel, cache and http."
msgstr ""

#. type: SH
#: davfs2.conf.5:513 mount.davfs.8:536 umount.davfs.8:79
#: davfs2.conf.5:513 mount.davfs.8:547 umount.davfs.8:79
#, no-wrap
msgid "AUTHORS"
msgstr ""
@ -1101,18 +1102,18 @@ msgid ""
msgstr ""

#. type: SH
#: davfs2.conf.5:519 mount.davfs.8:553 umount.davfs.8:84
#: davfs2.conf.5:519 mount.davfs.8:564 umount.davfs.8:84
#, no-wrap
msgid "DAVFS2 HOME"
msgstr ""

#. type: Plain text
#: davfs2.conf.5:522 mount.davfs.8:556 umount.davfs.8:87
#: davfs2.conf.5:522 mount.davfs.8:567 umount.davfs.8:87
msgid "@PACKAGE_BUGREPORT@"
msgstr ""

#. type: SH
#: davfs2.conf.5:524 mount.davfs.8:558 umount.davfs.8:89
#: davfs2.conf.5:524 mount.davfs.8:569 umount.davfs.8:89
#, no-wrap
msgid "SEE ALSO"
msgstr ""

View File

@ -6,8 +6,8 @@
msgid ""
msgstr ""
"Project-Id-Version: davfs2 1.5.0\n"
"POT-Creation-Date: 2014-04-06 18:16+0300\n"
"PO-Revision-Date: 2014-04-06 18:20+0200\n"
"POT-Creation-Date: 2014-04-18 18:25+0300\n"
"PO-Revision-Date: 2014-04-18 18:30+0200\n"
"Last-Translator: Werner Baumann <werner.baumann@onlinehome.de>\n"
"Language-Team: \n"
"Language: \n"
@ -25,8 +25,8 @@ msgstr "@CONFIGFILE@"
#. type: TH
#: davfs2.conf.5:1
#, no-wrap
msgid "2012-02-01"
msgstr "2012-02-01"
msgid "2014-04-18"
msgstr "2014-04-18"

# type: TH
#. type: TH
@ -740,22 +740,24 @@ msgstr "0 = nein, 1 = ja."
#. type: TP
#: davfs2.conf.5:266
#, no-wrap
msgid "B<allow_cookie>"
msgstr "B<allow_cookie>"
msgid "B<n_cookies>"
msgstr "B<n_cookies>"

# type: Plain text
#. type: Plain text
#: davfs2.conf.5:273
msgid ""
"Some servers will only work when they are allowed to set a cookie and this "
"cookie is returned in subsequent requests. This option adds very simple "
"cookie support. It supports just one cookie which should usually be a "
"session ID. 0 = no, 1 = yes."
"cookie is returned in subsequent requests. This option sets the number of "
"cookies you are willing to accept and include in subsequent requests. davfs2 "
"will only care for the name and the value of the cookie and ignore all of "
"the possible attributes."
msgstr ""
"Manche Server verweigern den Dienst, wenn ihnen nicht erlaubt is ein Cookie "
"zu setzen. Diese Option fügt sehr einfche Unterstützung für Cookies hinzu. "
"Es wird nur ein Cookie unterstützt, welches normalerweise eine Session-ID "
"sein sollte. 0 = nein, 1 = ja."
"zu setzen. Diese Option legt fest, wie vile Cookies akzeptiert und in den "
"folgenden Requests gesendet werden. davfs2 kümmert sich nur um den Namen und "
"den Wert von Cookies und ignoriert alle eventuellen zusätzlichen "
"Eigenschaften der Cookies."

# type: TP
#. type: TP
@ -1465,7 +1467,7 @@ msgstr "Beinhaltet config, kernel, cache und http."

# type: SH
#. type: SH
#: davfs2.conf.5:513 mount.davfs.8:536 umount.davfs.8:79
#: davfs2.conf.5:513 mount.davfs.8:547 umount.davfs.8:79
#, no-wrap
msgid "AUTHORS"
msgstr "AUTOREN"
@ -1482,20 +1484,20 @@ msgstr ""

# type: SH
#. type: SH
#: davfs2.conf.5:519 mount.davfs.8:553 umount.davfs.8:84
#: davfs2.conf.5:519 mount.davfs.8:564 umount.davfs.8:84
#, no-wrap
msgid "DAVFS2 HOME"
msgstr "DAVFS2 HOME"

# type: TH
#. type: Plain text
#: davfs2.conf.5:522 mount.davfs.8:556 umount.davfs.8:87
#: davfs2.conf.5:522 mount.davfs.8:567 umount.davfs.8:87
msgid "@PACKAGE_BUGREPORT@"
msgstr "@PACKAGE_BUGREPORT@"

# type: SH
#. type: SH
#: davfs2.conf.5:524 mount.davfs.8:558 umount.davfs.8:89
#: davfs2.conf.5:524 mount.davfs.8:569 umount.davfs.8:89
#, no-wrap
msgid "SEE ALSO"
msgstr "SIEHE AUCH"

View File

@ -7,7 +7,7 @@
msgid ""
msgstr ""
"Project-Id-Version: davfs2.conf.5\n"
"POT-Creation-Date: 2014-04-06 18:16+0300\n"
"POT-Creation-Date: 2014-04-18 18:25+0300\n"
"PO-Revision-Date: 2007-04-26 01:24-0300\n"
"Last-Translator: Luciano Bello <luciano@linux.org.ar>\n"
"Language-Team: Español <es@li.org>\n"
@ -24,11 +24,13 @@ msgstr ""
msgid "@CONFIGFILE@"
msgstr "@CONFIGFILE@"

# type: TH
#. type: TH
#: davfs2.conf.5:1
#, no-wrap
msgid "2012-02-01"
msgstr ""
#, fuzzy, no-wrap
#| msgid "2011-04-03"
msgid "2014-04-18"
msgstr "2011-04-03"

# type: TH
#. type: TH
@ -712,18 +714,19 @@ msgstr "0 = no, 1 = sí."
# type: TP
#. type: TP
#: davfs2.conf.5:266
#, no-wrap
msgid "B<allow_cookie>"
#, fuzzy, no-wrap
#| msgid "B<allow_cookie>"
msgid "B<n_cookies>"
msgstr "B<allow_cookie>"

# type: Plain text
#. type: Plain text
#: davfs2.conf.5:273
msgid ""
"Some servers will only work when they are allowed to set a cookie and this "
"cookie is returned in subsequent requests. This option adds very simple "
"cookie support. It supports just one cookie which should usually be a "
"session ID. 0 = no, 1 = yes."
"cookie is returned in subsequent requests. This option sets the number of "
"cookies you are willing to accept and include in subsequent requests. davfs2 "
"will only care for the name and the value of the cookie and ignore all of "
"the possible attributes."
msgstr ""

# type: TP
@ -1388,7 +1391,7 @@ msgstr ""

# type: SH
#. type: SH
#: davfs2.conf.5:513 mount.davfs.8:536 umount.davfs.8:79
#: davfs2.conf.5:513 mount.davfs.8:547 umount.davfs.8:79
#, no-wrap
msgid "AUTHORS"
msgstr "AUTORES"
@ -1405,20 +1408,20 @@ msgstr ""

# type: SH
#. type: SH
#: davfs2.conf.5:519 mount.davfs.8:553 umount.davfs.8:84
#: davfs2.conf.5:519 mount.davfs.8:564 umount.davfs.8:84
#, no-wrap
msgid "DAVFS2 HOME"
msgstr "DAVFS2 HOME"

# type: TH
#. type: Plain text
#: davfs2.conf.5:522 mount.davfs.8:556 umount.davfs.8:87
#: davfs2.conf.5:522 mount.davfs.8:567 umount.davfs.8:87
msgid "@PACKAGE_BUGREPORT@"
msgstr "@PACKAGE_BUGREPORT@"

# type: SH
#. type: SH
#: davfs2.conf.5:524 mount.davfs.8:558 umount.davfs.8:89
#: davfs2.conf.5:524 mount.davfs.8:569 umount.davfs.8:89
#, no-wrap
msgid "SEE ALSO"
msgstr "VER TAMBIÉN"

View File

@ -185,9 +185,9 @@
May be overridden by system config file and user config file. */
#define DAV_DROP_WEAK_ETAGS 0

/* Wether to allow a cookie to be set and included in requests.
/* How many cookies to store and include in requests.
May be overridden by system config file and user config file. */
#define DAV_ALLOW_COOKIE 0
#define DAV_N_COOKIES 0

/* Check on server whether a file exists or has been modified before
locking a new file or changing an existant one.

View File

@ -1686,7 +1686,7 @@ new_args(void)
args->expect100 = DAV_EXPECT100;
args->if_match_bug = DAV_IF_MATCH_BUG;
args->drop_weak_etags = DAV_DROP_WEAK_ETAGS;
args->allow_cookie = DAV_ALLOW_COOKIE;
args->n_cookies = DAV_N_COOKIES;
args->precheck = DAV_PRECHECK;
args->ignore_dav_header = DAV_IGNORE_DAV_HEADER;
args->use_compression = DAV_USE_COMPRESSION;
@ -1783,7 +1783,7 @@ log_dbg_config(dav_args *args)
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG),
" drop_weak_etags: %i", args->drop_weak_etags);
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG),
" allow_cookie: %i", args->allow_cookie);
" n_cookies: %i", args->n_cookies);
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG),
" precheck: %i", args->precheck);
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG),
@ -2168,8 +2168,8 @@ read_config(dav_args *args, const char * filename, int system)
args->if_match_bug = arg_to_int(parmv[1], 10, parmv[0]);
} else if (strcmp(parmv[0], "drop_weak_etags") == 0) {
args->drop_weak_etags = arg_to_int(parmv[1], 10, parmv[0]);
} else if (strcmp(parmv[0], "allow_cookie") == 0) {
args->allow_cookie = arg_to_int(parmv[1], 10, parmv[0]);
} else if (strcmp(parmv[0], "n_cookies") == 0) {
args->n_cookies = arg_to_int(parmv[1], 10, parmv[0]);
} else if (strcmp(parmv[0], "precheck") == 0) {
args->precheck = arg_to_int(parmv[1], 10, parmv[0]);
} else if (strcmp(parmv[0], "ignore_dav_header") == 0) {

View File

@ -89,7 +89,7 @@ typedef struct {
int expect100; /* User config file, system config file */
int if_match_bug; /* User config file, system config file */
int drop_weak_etags; /* User config file, system config file */
int allow_cookie; /* User config file, system config file */
int n_cookies; /* User config file, system config file */
int precheck; /* User config file, system config file */
int ignore_dav_header; /* User config file, system config file */
int use_compression; /* User config file, system config file */

View File

@ -231,8 +231,10 @@ static FILE *log_stream;
/* A user defined header that is added to all requests. */
char *custom_header;

/* Session cookie. */
static char *cookie;
/* Array of max. n_cookies cookie strings. NULL if configuration option
allow_cookies is 0. The array must be allocated by dav_init_webdav. */
static int n_cookies;
static char **cookie_list;


/* Private function prototypes and inline functions */
@ -278,6 +280,9 @@ auth(void *userdata, const char *realm, int attempt, char *user, char *pwd);
static int
file_reader(void *userdata, const char *block, size_t length);

static void
get_cookies(ne_request *req, void *userdata, const ne_status *status);

static void
lock_result(void *userdata, const struct ne_lock *lock, const ne_uri *uri,
const ne_status *status);
@ -294,9 +299,6 @@ quota_reader(void *userdata, const char *block, size_t length);
static int
ssl_verify(void *userdata, int failures, const ne_ssl_certificate *cert);

static int
update_cookie(ne_request *req, void *userdata, const ne_status *status);


/* Public functions */
/*==================*/
@ -412,11 +414,16 @@ dav_init_webdav(dav_args *args)

if (args->header) {
custom_header = xstrdup(args->header);
ne_hook_pre_send(session, add_header, custom_header);
}

if (args->allow_cookie)
ne_hook_post_send(session, update_cookie, NULL);
if (args->n_cookies) {
n_cookies = args->n_cookies;
cookie_list = (char **) xcalloc(n_cookies, sizeof(char *));
ne_hook_post_headers(session, get_cookies, NULL);
}

if (custom_header || cookie_list)
ne_hook_pre_send(session, add_header, NULL);

use_expect100 = args->expect100;
has_if_match_bug = args->if_match_bug;
@ -1440,7 +1447,20 @@ replace_slashes(char **name)
static void
add_header(ne_request *req, void *userdata, ne_buffer *header)
{
ne_buffer_zappend(header, (char *) userdata);
if (custom_header)
ne_buffer_zappend(header, custom_header);

if (cookie_list && cookie_list[0]) {
ne_buffer_zappend(header, "Cookie: ");
ne_buffer_zappend(header, cookie_list[0]);
int i = 1;
while (i < n_cookies && cookie_list[i]) {
ne_buffer_zappend(header, ", ");
ne_buffer_zappend(header, cookie_list[i]);
i++;
}
ne_buffer_zappend(header, "\r\n");
}
}


@ -1519,6 +1539,71 @@ file_reader(void *userdata, const char *block, size_t length)
}


/* A ne_post_header_fn to read cookies from the Set-Cookie header and
store them in the global arrray of strings cookie_list. The cookies
will be send in the Cookie header of subsequent requests.
Only the "name=value" part of the cookie is stored. All attributes
are completely ignored.
When a cookie with the same name as an already stored cookie, but with
a different value is received, it's value is updated if necessary.
Only n_cookies cookies will be stored. If the server sends more
different cookies these will be ignored.
status must be of class 2XX or 3XX, otherwise the cookie is ignored. */
static void
get_cookies(ne_request *req, void *userdata, const ne_status *status)
{
if (status->klass != 2 && status->klass != 3)
return;

const char *cookie_hdr = ne_get_response_header(req, "Set-Cookie");
if (!cookie_hdr)
return;

const char *next = cookie_hdr;
while (next) {
const char *start = next;
next = strchr(start, ',');
const char *end = strchr(start, ';');
if (next) {
if (!end || end > next)
end = next;
next++;
} else if (!end) {
end = start + strlen(start);
}

while (start < end && *start == ' ')
start++;
while (end > start && *(end - 1) == ' ')
end--;

if ((start + 4) > end || *start == '=' || *(end - 1) == '=')
continue;

char *es = strchr(start, '=');
if (!es)
continue;
size_t nl = es - start;
size_t vl = end - es - 1;

int i = 0;
for (i = 0; i < n_cookies; i++) {
if (!cookie_list[i]) {
cookie_list[i] = xstrndup(start, end - start);
break;
}
if (strncmp(cookie_list[i], start, nl) == 0) {
if (strncmp(cookie_list[i] + nl + 1, es + 1, vl) != 0) {
free(cookie_list[i]);
cookie_list[i] = xstrndup(start, end - start);
}
break;
}
}
}
}


/* If the owner of this lock is the same as global variable owner, lock is
stored in the global lock store locks and a pointer to the lock is
returned in userdata.
@ -1822,42 +1907,3 @@ ssl_verify(void *userdata, int failures, const ne_ssl_certificate *cert)
return ret;
}


static int
update_cookie(ne_request *req, void *userdata, const ne_status *status)
{
if (status->klass != 2)
return NE_OK;

const char *cookie_hdr = ne_get_response_header(req, "Set-Cookie2");
if (!cookie_hdr) {
cookie_hdr = ne_get_response_header(req, "Set-Cookie");
}
if (!cookie_hdr)
return NE_OK;

if (cookie && strstr(cookie_hdr, cookie) == cookie_hdr)
return NE_OK;

char *sep = strpbrk(cookie_hdr, "\",; \n\r\0");
if (!sep)
return NE_OK;
if (*sep == '\"')
sep = strpbrk(sep + 1, "\"");
if (!sep)
return NE_OK;

if (cookie) {
ne_unhook_pre_send(session, add_header, cookie);
free(cookie);
cookie = NULL;
}

char *value = xstrndup(cookie_hdr, sep - cookie_hdr + 1);
cookie = xasprintf("Cookie: $Version=1;%s\r\n", value);
free(value);

ne_hook_pre_send(session, add_header, cookie);
return NE_OK;
}