diff options
| author | jow <jow@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2012-05-03 17:19:18 +0000 | 
|---|---|---|
| committer | jow <jow@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2012-05-03 17:19:18 +0000 | 
| commit | 8329c6da4fac952135d7f10d8ee008b5342ad87b (patch) | |
| tree | 07821c9533eae5a825e921e3c712fa5e32163a9b /package/uhttpd/src | |
| parent | f6dc56506d693c2915e70f1d31bea4a894abc1a1 (diff) | |
Fixed: [PATCH 2/3] uhttpd URL-codec enhancements.
My apologies, the 2nd of those patches had a syntax error -- that's what
I get for making a last-minute edit, even to the comments, without
testing! :-p
Here is the corrected patch.
-- David
From d259cff104d2084455476b82e92a3a27524f4263 Mon Sep 17 00:00:00 2001
From: David Favro <openwrt@meta-dynamic.com>
Date: Fri, 27 Apr 2012 14:17:52 -0400
Subject: [PATCH] uhttpd URL-codec enhancements.
* uh_urlencode() and uh_urldecode() now return an error condition for
  buffer-overflow and malformed-encoding rather than normal return with corrupt
  or truncated data.  As HTTP request processing is currently implemented, this
  causes a 404 HTTP status returned to the client, while 400 is more
  appropriate.
* Exposed urlencode() to Lua.
* Lua's uhttpd.urlencode() and .urldecode() now raise an error condition for
  buffer-overflow and malformed-encoding rather than normal return with
  incorrect data.
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@31570 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'package/uhttpd/src')
| -rw-r--r-- | package/uhttpd/src/uhttpd-lua.c | 24 | ||||
| -rw-r--r-- | package/uhttpd/src/uhttpd-utils.c | 42 | ||||
| -rw-r--r-- | package/uhttpd/src/uhttpd.c | 7 | 
3 files changed, 52 insertions, 21 deletions
| diff --git a/package/uhttpd/src/uhttpd-lua.c b/package/uhttpd/src/uhttpd-lua.c index c2efe3384..a140dc2f2 100644 --- a/package/uhttpd/src/uhttpd-lua.c +++ b/package/uhttpd/src/uhttpd-lua.c @@ -108,19 +108,34 @@ static int uh_lua_sendc(lua_State *L)  	return uh_lua_send_common(L, 1);  } -static int uh_lua_urldecode(lua_State *L) +static int uh_lua_str2str(lua_State *L, int (*xlate_func) (char *, int, const char *, int))  { -	size_t inlen, outlen; +	size_t inlen; +	int outlen;  	const char *inbuf;  	char outbuf[UH_LIMIT_MSGHEAD];  	inbuf = luaL_checklstring(L, 1, &inlen); -	outlen = uh_urldecode(outbuf, sizeof(outbuf), inbuf, inlen); +	outlen = (* xlate_func)(outbuf, sizeof(outbuf), inbuf, inlen); +	if( outlen < 0 ) +		luaL_error( L, "%s on URL-encode codec", +			(outlen==-1) ? "buffer overflow" : "malformed string" );  	lua_pushlstring(L, outbuf, outlen);  	return 1;  } +static int uh_lua_urldecode(lua_State *L) +{ +	return uh_lua_str2str( L, uh_urldecode ); +} + + +static int uh_lua_urlencode(lua_State *L) +{ +	return uh_lua_str2str( L, uh_urlencode ); +} +  lua_State * uh_lua_init(const char *handler)  { @@ -146,6 +161,9 @@ lua_State * uh_lua_init(const char *handler)  	lua_pushcfunction(L, uh_lua_urldecode);  	lua_setfield(L, -2, "urldecode"); +	lua_pushcfunction(L, uh_lua_urlencode); +	lua_setfield(L, -2, "urlencode"); +  	/* _G.uhttpd = { ... } */  	lua_setfield(L, LUA_GLOBALSINDEX, "uhttpd"); diff --git a/package/uhttpd/src/uhttpd-utils.c b/package/uhttpd/src/uhttpd-utils.c index 1073f3bb3..1dac33db0 100644 --- a/package/uhttpd/src/uhttpd-utils.c +++ b/package/uhttpd/src/uhttpd-utils.c @@ -307,7 +307,7 @@ int uh_http_send(  /* blen is the size of buf; slen is the length of src.  The input-string need  ** not be, and the output string will not be, null-terminated.  Returns the -** length of the decoded string. */ +** length of the decoded string, -1 on buffer overflow, -2 on malformed string. */  int uh_urldecode(char *buf, int blen, const char *src, int slen)  {  	int i; @@ -329,7 +329,15 @@ int uh_urldecode(char *buf, int blen, const char *src, int slen)  			}  			else  			{ -				buf[len++] = '%'; +				/* Encoding error: it's hard to think of a +				** scenario in which returning an incorrect +				** 'decoding' of the malformed string is +				** preferable to signaling an error condition. */ +				#if 0 /* WORSE_IS_BETTER */ +				    buf[len++] = '%'; +				#else +				    return -2; +				#endif  			}  		}  		else @@ -338,12 +346,12 @@ int uh_urldecode(char *buf, int blen, const char *src, int slen)  		}  	} -	return len; +	return (i == slen) ? len : -1;  }  /* blen is the size of buf; slen is the length of src.  The input-string need  ** not be, and the output string will not be, null-terminated.  Returns the -** length of the encoded string. */ +** length of the encoded string, or -1 on error (buffer overflow) */  int uh_urlencode(char *buf, int blen, const char *src, int slen)  {  	int i; @@ -365,11 +373,12 @@ int uh_urlencode(char *buf, int blen, const char *src, int slen)  		}  		else  		{ +			len = -1;  			break;  		}  	} -	return len; +	return (i == slen) ? len : -1;  }  int uh_b64decode(char *buf, int blen, const unsigned char *src, int slen) @@ -495,6 +504,9 @@ static char * canonpath(const char *path, char *path_resolved)  	return NULL;  } +/* Returns NULL on error. +** NB: improperly encoded URL should give client 400 [Bad Syntax]; returning +** NULL here causes 404 [Not Found], but that's not too unreasonable. */  struct path_info * uh_path_lookup(struct client *cl, const char *url)  {  	static char path_phys[PATH_MAX]; @@ -530,21 +542,21 @@ struct path_info * uh_path_lookup(struct client *cl, const char *url)  		/* urldecode component w/o query */  		if( pathptr > url ) -			uh_urldecode( -				&buffer[strlen(docroot)], -				sizeof(buffer) - strlen(docroot) - 1, -				url, pathptr - url -			); +			if ( uh_urldecode( +					&buffer[strlen(docroot)], +					sizeof(buffer) - strlen(docroot) - 1, +					url, pathptr - url ) < 0 ) +				return NULL; /* bad URL */  	}  	/* no query string, decode all of url */  	else  	{ -		uh_urldecode( -			&buffer[strlen(docroot)], -			sizeof(buffer) - strlen(docroot) - 1, -			url, strlen(url) -		); +		if ( uh_urldecode( +				&buffer[strlen(docroot)], +				sizeof(buffer) - strlen(docroot) - 1, +				url, strlen(url) ) < 0 ) +			return NULL; /* bad URL */  	}  	/* create canon path */ diff --git a/package/uhttpd/src/uhttpd.c b/package/uhttpd/src/uhttpd.c index 9b9608628..5d66e23a5 100644 --- a/package/uhttpd/src/uhttpd.c +++ b/package/uhttpd/src/uhttpd.c @@ -948,9 +948,10 @@ int main (int argc, char **argv)  					for (opt = 0; optarg[opt]; opt++)  						if (optarg[opt] == '+')  							optarg[opt] = ' '; - -					memset(port, 0, strlen(optarg)+1); -					uh_urldecode(port, strlen(optarg), optarg, strlen(optarg)); +					/* opt now contains strlen(optarg) -- no need to re-scan */ +					memset(port, 0, opt+1); +					if (uh_urldecode(port, opt, optarg, opt) < 0) +					    fprintf( stderr, "uhttpd: invalid encoding\n" );  					printf("%s", port);  					free(port); | 
