mirror of
https://github.com/emikulic/darkhttpd.git
synced 2023-08-10 21:13:08 +03:00
Faster, simpler, not yet completely correct reimplementation of
make_safe_uri(). It still has a lot of debugging cruft inside.
This commit is contained in:
parent
b2f504f975
commit
b082fa213f
@ -438,93 +438,85 @@ static void consolidate_slashes(char *s)
|
|||||||
*/
|
*/
|
||||||
static char *make_safe_uri(char *uri)
|
static char *make_safe_uri(char *uri)
|
||||||
{
|
{
|
||||||
char **elements, **reassembly, *out;
|
char **elem, *out;
|
||||||
unsigned int slashes, elem, reasm, urilen, i, j;
|
unsigned int slashes = 0, elements = 0;
|
||||||
|
size_t urilen, i, j, pos;
|
||||||
|
|
||||||
assert(uri != NULL);
|
assert(uri != NULL);
|
||||||
|
debugf("make_safe_uri(`%s')\n", uri);
|
||||||
if (uri[0] != '/') return NULL;
|
if (uri[0] != '/') return NULL;
|
||||||
consolidate_slashes(uri);
|
consolidate_slashes(uri);
|
||||||
urilen = (unsigned int)strlen(uri);
|
urilen = strlen(uri);
|
||||||
|
|
||||||
/* count the slashes */
|
/* count the slashes */
|
||||||
for (i=0, slashes=0; i<urilen; i++)
|
for (i=0, slashes=0; i<urilen; i++)
|
||||||
if (uri[i] == '/') slashes++;
|
if (uri[i] == '/') slashes++;
|
||||||
|
|
||||||
/* make an array for the URI elements */
|
/* make an array for the URI elements */
|
||||||
elements = xmalloc(sizeof(char*) * slashes);
|
elem = xmalloc(sizeof(char*) * slashes);
|
||||||
for (i=0; i<slashes; i++) elements[i] = NULL;
|
for (i=0; i<slashes; i++) elem[i] = NULL;
|
||||||
|
|
||||||
/* split by slash */
|
/* split by slashes and build elem[] array */
|
||||||
elem = i = 0;
|
for (i=1; i<urilen;)
|
||||||
while (i < urilen) /* i is the left bound */
|
|
||||||
{
|
{
|
||||||
/* look for a non-slash */
|
|
||||||
for (; uri[i] == '/'; i++)
|
|
||||||
;
|
|
||||||
|
|
||||||
/* look for the next slash */
|
/* look for the next slash */
|
||||||
for (j=i+1; j < urilen && uri[j] != '/'; j++)
|
for (j=i; j<urilen && uri[j] != '/'; j++)
|
||||||
;
|
;
|
||||||
|
|
||||||
if (j <= urilen)
|
/* process uri[i,j) */
|
||||||
elements[elem++] = split_string(uri, i, j);
|
if ((j == i+1) && (uri[i] == '.'))
|
||||||
|
{
|
||||||
i = j; /* iterate */
|
/* "." */
|
||||||
|
debugf("got `.'\n");
|
||||||
}
|
}
|
||||||
|
else if ((j == i+2) && (uri[i] == '.') && (uri[i+1] == '.'))
|
||||||
|
{
|
||||||
|
/* ".." */
|
||||||
|
debugf("got `..'\n");
|
||||||
|
|
||||||
reassembly = xmalloc(sizeof(char*) * slashes);
|
if (elements == 0)
|
||||||
for (i=0; i<slashes; i++) reassembly[i] = NULL;
|
|
||||||
reasm = 0;
|
|
||||||
|
|
||||||
/* process */
|
|
||||||
for (i=0; i<elem; i++)
|
|
||||||
{
|
{
|
||||||
if (strcmp(elements[i], ".") == 0)
|
/* unsafe string so free elem[]; all its elements are free at
|
||||||
{ /* do nothing */ }
|
* this point.
|
||||||
else if (strcmp(elements[i], "..") == 0)
|
*/
|
||||||
{
|
free(elem);
|
||||||
/* try to backstep */
|
|
||||||
if (reasm == 0)
|
|
||||||
{
|
|
||||||
/* user walked out of wwwroot! unsafe uri! */
|
|
||||||
for (j=0; j<elem; j++)
|
|
||||||
if (elements[j] != NULL) free(elements[j]);
|
|
||||||
free(elements);
|
|
||||||
free(reassembly);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
/* else */
|
else
|
||||||
reasm--;
|
{
|
||||||
reassembly[reasm] = NULL;
|
elements--;
|
||||||
|
free(elem[elements]);
|
||||||
|
elem[elements] = NULL; /* FIXME: not needed */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* plain copy */
|
/* token */
|
||||||
reassembly[reasm++] = elements[i];
|
debugf("splitting [%d,%d): ", i, j);
|
||||||
}
|
elem[elements++] = split_string(uri, i, j);
|
||||||
|
debugf("splitting [%d,%d): element %d: `%s'\n",
|
||||||
|
i,j,elements,elem[elements-1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reasm == 0)
|
i = j + 1; /* uri[j] is a slash - move along one */
|
||||||
{
|
|
||||||
out = xstrdup("/");
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
/* reassemble */
|
/* reassemble */
|
||||||
size_t pos = 0;
|
|
||||||
out = xmalloc(urilen+1); /* it won't expand */
|
out = xmalloc(urilen+1); /* it won't expand */
|
||||||
|
pos = 0;
|
||||||
for (i=0; i<reasm; i++)
|
for (i=0; i<elements; i++)
|
||||||
{
|
{
|
||||||
size_t delta = strlen(reassembly[i]);
|
size_t delta = strlen(elem[i]);
|
||||||
|
|
||||||
assert(pos <= urilen);
|
assert(pos <= urilen);
|
||||||
out[pos++] = '/';
|
out[pos++] = '/';
|
||||||
|
|
||||||
assert(pos+delta <= urilen);
|
assert(pos+delta <= urilen);
|
||||||
memcpy(out+pos, reassembly[i], delta);
|
memcpy(out+pos, elem[i], delta);
|
||||||
|
free(elem[i]);
|
||||||
pos += delta;
|
pos += delta;
|
||||||
}
|
}
|
||||||
|
free(elem);
|
||||||
|
|
||||||
if (uri[urilen-1] == '/') out[pos++] = '/';
|
if (uri[urilen-1] == '/') out[pos++] = '/';
|
||||||
assert(pos <= urilen);
|
assert(pos <= urilen);
|
||||||
@ -532,13 +524,8 @@ static char *make_safe_uri(char *uri)
|
|||||||
|
|
||||||
if (pos != urilen)
|
if (pos != urilen)
|
||||||
out = xrealloc(out, strlen(out)+1); /* shorten buffer */
|
out = xrealloc(out, strlen(out)+1); /* shorten buffer */
|
||||||
}
|
|
||||||
|
|
||||||
debugf("`%s' -safe-> `%s'\n", uri, out);
|
debugf("`%s' -safe-> `%s'\n", uri, out);
|
||||||
for (j=0; j<elem; j++)
|
|
||||||
if (elements[j] != NULL) free(elements[j]);
|
|
||||||
free(elements);
|
|
||||||
free(reassembly);
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -548,7 +535,9 @@ static char *make_safe_uri(char *uri)
|
|||||||
static void test_make_safe_uri(void)
|
static void test_make_safe_uri(void)
|
||||||
{
|
{
|
||||||
#define SAFE(from,to) do { char *uri = xstrdup(from), *tmp;\
|
#define SAFE(from,to) do { char *uri = xstrdup(from), *tmp;\
|
||||||
tmp = make_safe_uri(uri); if (strcmp(tmp, to) != 0) \
|
tmp = make_safe_uri(uri); if (tmp == NULL) \
|
||||||
|
debugf("FAIL: `%s' unsafe, expecting `%s'\n", from, to); \
|
||||||
|
else if (strcmp(tmp, to) != 0) \
|
||||||
debugf("FAIL: `%s' -> `%s', expecting `%s'\n", from, tmp, to); \
|
debugf("FAIL: `%s' -> `%s', expecting `%s'\n", from, tmp, to); \
|
||||||
free(tmp); free(uri); } while(0)
|
free(tmp); free(uri); } while(0)
|
||||||
|
|
||||||
@ -574,6 +563,7 @@ static void test_make_safe_uri(void)
|
|||||||
SAFE("/foo/bar/../moo/", "/foo/moo/");
|
SAFE("/foo/bar/../moo/", "/foo/moo/");
|
||||||
SAFE("/./moo/./../a/b/c/../.././d/../..", "/");
|
SAFE("/./moo/./../a/b/c/../.././d/../..", "/");
|
||||||
SAFE("/./moo/./../a/b/c/../.././d/../../", "/");
|
SAFE("/./moo/./../a/b/c/../.././d/../../", "/");
|
||||||
|
SAFE("/./moo/./../a/b/c/../.././d/../../xyzzy/", "/xyzzy/");
|
||||||
|
|
||||||
#undef SAFE
|
#undef SAFE
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user