Bug #1In request.c, in the function
parseHeaders, you will find:
Code:
switch (key[0]) {
case 'A':
if (strcmp(key, "AUTHORIZATION") == 0) {
req->authType = mprStrTok(value, " \t", &tok);
req->authDetails = tok;
Note that the headers of eveyy incoming HTTP requests pass through this function, and this is the bit that deals with the
Authorization header. The
value will be a string looking something like:
Code:
Digest uri="/Login/login", ..., username="admin",..., nonce="2a0f1634d499d1188bb3328b07f6db6d"...
The given code chops that string in two (by inserting a'\0' in it), and
req->authType points to the first bit, and
req->authDetails points to the rest.
Which is very naughty because, later on (using an advertised facility), some action in some controller is entitled to ask to see
request.headers, and in particular to see
request.headers.HTTP_AUTHORIZATION, and it will be told that the only context of that header is "Digest", which is a lie.
My fix for this problem (perhaps not the most elegant fix) was to change that code to
Code:
switch (key[0]) {
case 'A':
if (strcmp(key, "AUTHORIZATION") == 0) {
tok = strpbrk(value, " \t");
req->authType = mprAlloc(conn, tok-value+1);
mprStrcpyCount(req->authType, tok-value+1, value, tok-value);
req->authDetails = ++tok;
Bug #2On looking for further instances of the same problem, I encountered (in the IF_MATCH and IF_RANGE headers)
Code:
value = mprStrdup(conn, value);
word = mprStrTok(value, " ,", &tok);
while (word) {
addMatchEtag(conn, word);
word = mprStrTok(0, " ,", &tok);
}
mprFree(value);
That carefully takes a copy of
value and chops the copy into pieces, each of which has a pointer stored away as an 'etag'. Then it frees the copy, whereupon all those etags are left pointing into potentially re-allocatable storage, which might or might not work :-(.
I suggest that
mprFree(value); should simply be omitted (the storage will eventually be recovered when the whole arena for
conn is destroyed).
I have not actually encountered any problems due to this, but it seems they could happen, so this is my "half bug".
Bug #3The class
Request advertises an attribute
authUser, which is supposed to contain the field of that name in the request struncture, so that actions and controllers can access it. BUT the request structure does not contain a field of that name (though it does include a field
username which seems to contain the intended data). Fixing this might be messy ...
But it is, of course, the reason why I was trying to access
request.headers.HTTP_AUTHORIZATION and hence discovered Bug #1.