On Tue, May 30, 2006 at 07:05:06PM +0900, vladas wrote:
> Sorry if this is too simple. It's still ongoing learning process for me.
>
> I dare to ask about it on misc@ because the code will be running on OpenBSD
> and
> because I want to learn how to use OpenBSD properly.
>
> Its about getenv("CONTENT_LENGTH"); usage from C. I have found two sources
> on t
> hat, but I am not able to understand the differences and to determine which
> code
> is better, safer.
>
> http://www.cs.tut.fi/~jkorpela/forms/cgic.html
>
> char *lenstr;
> char input[MAXINPUT], data[MAXINPUT];
> long len;
> printf("%s%c%c\n","Content-Type:text/html;charset=iso-8859-1",13,10);
> lenstr = getenv("CONTENT_LENGTH");
> if(lenstr == NULL || sscanf(lenstr,"%ld",&len)!=1 || len > MAXLEN)
> printf("<P>Error in invocation - blah blah");
> else {
> FILE *f;
> fgets(input, len+1, stdin);
> <.....>
>
> http://www.coding-zone.co.uk/cpp/cgi/170401cgicpp.shtml
>
> main()
> {
> char *endptr;
> int i;
> double contentlength;
> char buff[10000];
> const char *len1 = getenv("CONTENT_LENGTH");
> contentlength=strtol(len1, &endptr, 10);
> fread(buff, contentlength, 1, stdin);
> }
>
>
>
> To be specific:
>
> 1. I do not get why the first example uses only
> lenstr = getenv("CONTENT_LENGTH");
>
> while the second example goes through all of that conversion of the
> getenv("CONTENT_LENGTH") result from string to decimal number:
> const char *len1 = getenv("CONTENT_LENGTH");
> contentlength=strtol(len1, &endptr, 10);
> fread(buff, contentlength, 1, stdin);
look closer (first example):
if(lenstr == NULL || sscanf(lenstr,"%ld",&len)!=1 || len > MAXLEN)
both convert the string to a number.
both examples use datatypes that i don't really like. use something like
size_t for length.
use something like strtonum/sscanf to convert a string to a number.
make sure length makes sense. -1 does not, 4,294,967,296 probably
doesn't either.
also make sure that your buffers are large enough for all possible
circumstances.
>
>
>
> 2. In the CGI context, do fgets(input, len+1, stdin) and
> fread(buff, contentlength, 1, stdin) make a difference?
fgets terminates buff with a '\0', wich is imho better than plain
fread. otoh, both are ok if buff is large enough(!) and you know
what you're doing.
>
>
> 3. Is the code
> if(lenstr == NULL || sscanf(lenstr,"%ld",&len)!=1 || len > MAXLEN)
> printf("<P>Error in invocation - blah blah");
> else {
> FILE *f;
> fgets(input, len+1, stdin);
> <.....>
>
> enough to prevent from the httpd buffer overflow attacks on the default
> OpenBSD httpd?
yes ;) if there is a buffer overflow, it's in your cgi, not in httpd.
httpd's chroot can prevent an attacker from getting a shell and do more
harm. Depending on your application, he can still do a lot of damage to
your application or to other clients (XSS attacks for example).
> I do understand that this question in particular is a
> broad one, but still - any comments or ideas would help as I am new to
> this.
>
>
>
> Reading httpd src or manuals did not explained the differences in the logic
> of differences in those two code snippets (well at least so far).
>
>
> Any help would be really appreciated.
read the superb manpages of the functions you want to use. there are
often examples and pointers to things you should do/not do.
>
>
>
> Vladas
>
>
I'm sure i forgot tons of stuff :)
Tobias