LinuxQuestions.org
Help answer threads with 0 replies.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 04-05-2016, 12:52 PM   #16
KarenWest
Member
 
Registered: Jun 2011
Location: North Easton,MA
Distribution: currently Ubuntu Linux on my netbook while job searching, but also use Cygwin GNU tools on MSXP nb
Posts: 33

Original Poster
Rep: Reputation: Disabled

I only saw local host with the following status from netstat while running the server:
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address Foreign Address State

tcp 0 0 localhost:http-alt localhost:55424 TIME_WAIT

I know to talk to the server, in the client browser, I did:
http://localhost:8080/home/karen/dev...est/index.html

I have another more involved project that I was hoping to do to learn more on this subject, but given I'm
stuck here on this one, I'll set that aside until I know where I"m going wrong! Thanks for your help.
 
Old 04-05-2016, 06:02 PM   #17
jpollard
Senior Member
 
Registered: Dec 2012
Location: Washington DC area
Distribution: Fedora, CentOS, Slackware
Posts: 4,912

Rep: Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513
That may be part of what is going wrong.

The root directory for a web server is whereever the document home is specified to be, and I think that is /home/karen/dev/webServerInC/pset6/public (or maybe including the /test). Thus the URL would be //localhost:8080/test/index.html, or //localhost:8080/index.html.

The path used by the system is generated by the web server itself, for its own use, not the client browser.
 
Old 04-06-2016, 12:08 PM   #18
KarenWest
Member
 
Registered: Jun 2011
Location: North Easton,MA
Distribution: currently Ubuntu Linux on my netbook while job searching, but also use Cygwin GNU tools on MSXP nb
Posts: 33

Original Poster
Rep: Reputation: Disabled
I'll try fixing that today and see if it corrects the problem. Thanks!
 
Old 04-06-2016, 01:02 PM   #19
KarenWest
Member
 
Registered: Jun 2011
Location: North Easton,MA
Distribution: currently Ubuntu Linux on my netbook while job searching, but also use Cygwin GNU tools on MSXP nb
Posts: 33

Original Poster
Rep: Reputation: Disabled
You fixed the problem - I thank you!
So when I started my web server passing it the public directory, from the client browser, I only pass the http://localhost:8080/test/index.html,
since those directories fall below the public directory that I started with my server. Thank you for your help!
 
Old 04-06-2016, 02:38 PM   #20
jpollard
Senior Member
 
Registered: Dec 2012
Location: Washington DC area
Distribution: Fedora, CentOS, Slackware
Posts: 4,912

Rep: Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513
You still need to check for why you were getting messages like "num bytes written to client browser = 0".

Personally, I still think there are some improper if conditional expressions in there. I saw a good number after I saw the one I reported.
 
Old 04-06-2016, 02:42 PM   #21
KarenWest
Member
 
Registered: Jun 2011
Location: North Easton,MA
Distribution: currently Ubuntu Linux on my netbook while job searching, but also use Cygwin GNU tools on MSXP nb
Posts: 33

Original Poster
Rep: Reputation: Disabled
I'm working on refining it now - thanks for your help.
 
Old 04-12-2016, 01:01 PM   #22
KarenWest
Member
 
Registered: Jun 2011
Location: North Easton,MA
Distribution: currently Ubuntu Linux on my netbook while job searching, but also use Cygwin GNU tools on MSXP nb
Posts: 33

Original Poster
Rep: Reputation: Disabled
I have a new question for the web server, when I send it a new php web page request (in the browser, typing: http://localhost:8080/test/index.php)
In the output generated from the code above, the code path for the php request does a popen() followed by load(), instead
of what it did for an html request, which was an fopen() followed by load(), and this seems to fail because in my load function,
the same code that I used to see how much allocated space I needed for the html file request does not work for the php request, since
it was opened with popen() rather than fopen(), and I know popen() forks and execs a process rather than just opens a file.
I am familiar with forking and execing processes, but I've never used popen() before.
It seems to think that the content space needed is zero.
This is the output. I can provide the php code I downloaded, if that would be needed.

In the load() code, for the html file, I had gotten the content size needed this way, but I read when I did a web search
that this was a "coding kluge".
Code:
fseek (file , 0 , SEEK_END);
filesize = ftell (file);
rewind (file);
So I tried this way:

Code:
if (fstat(fileno(file), &sb) == -1) 
{
    perror("stat");
    exit(EXIT_FAILURE);
}
printf("File size from fstat(): %lld bytes\n", (unsigned long long) sb.st_size);
Yet you will see in the output below, that fstat() says my file size needed is zero bytes.
The kluge code file size says -1 bytes are needed.

karen webserverToPhysComp $ ./server public
Using /home/karen/dev/cs410Projects2and3_2015to2016/webserverToPhysComp/public for server's root
Listening on port 8080
checking for client connections
starting infinite loop to look for client browser requests
checking if client has connected
calling accept(): extracts the first connection request on the queue of pending connections for the listening socket (server), sockfd, creates a new connected socket, and returns a new file descriptor referring to that socket (client)
client: addr = 16777343
client has connected - check for request
request: reading message
message from client = GET /test/index.php HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
length = 405
GET /test/index.php HTTP/1.1
parsing request-line from client: line = GET /test/index.php HTTP/1.1

parsing line = GET /test/index.php HTTP/1.1

parsing for the GET method
should be pointing to request-target part of line = /test/index.php HTTP/1.1
start of abs_path = /
pathChars = /test/index.php countAbsPath = 15
len of abs_path = 0 len of pathChars = 15
parse: abs_path = /test/index.php
no query found
parse: query =
are we pointing at HTTP's and it's version? HTTP/1.1
and HTTP/1.1

HTTP/1.1 found - correct version for now
abs_path returned from parse = /test/index.php
query returned from parse =
calling lookup on path = /home/karen/dev/cs410Projects2and3_2015to2016/webserverToPhysComp/public/test/index.php
lookup on path = /home/karen/dev/cs410Projects2and3_2015to2016/webserverToPhysComp/public/test/index.php
pathToPeriod = (null) lastPeriodInPath = php
type = text/x-php
interpret being called with path = /home/karen/dev/cs410Projects2and3_2015to2016/webserverToPhysComp/public/test/index.php and query =
interpret: calling popen() on command = QUERY_STRING="" REDIRECT_STATUS=200 SCRIPT_FILENAME="/home/karen/dev/cs410Projects2and3_2015to2016/webserverToPhysComp/public/test/index.php" php-cgi
interpret: calling load() file popened = 5
load a file into memory file = 5
File size from fstat(): 0 bytes
file size from fseek(): -1 bytes
file size less than READMEGABYTEFROMFILE = 0
numBuffers = 1, numBytesToRead = filesize = 0
*content = 0 before calling realloc
 
Old 04-12-2016, 02:25 PM   #23
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian, Arch
Posts: 3,784

Rep: Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083
Quote:
Originally Posted by KarenWest View Post
I have a new question for the web server, when I send it a new php web page request (in the browser, typing: http://localhost:8080/test/index.php)
In the output generated from the code above, the code path for the php request does a popen() followed by load(), instead
of what it did for an html request, which was an fopen() followed by load(), and this seems to fail because in my load function,
the same code that I used to see how much allocated space I needed for the html file request does not work for the php request, since
it was opened with popen() rather than fopen(), and I know popen() forks and execs a process rather than just opens a file.
I am familiar with forking and execing processes, but I've never used popen() before.
Consider that PHP code can decide to output a random number of bytes every time it runs, so there is no way to know in advance how much space you will need.
 
Old 04-12-2016, 02:59 PM   #24
KarenWest
Member
 
Registered: Jun 2011
Location: North Easton,MA
Distribution: currently Ubuntu Linux on my netbook while job searching, but also use Cygwin GNU tools on MSXP nb
Posts: 33

Original Poster
Rep: Reputation: Disabled
What is happening here in this command? Maybe that would help me understand.
interpret: calling popen() on command = QUERY_STRING="" REDIRECT_STATUS=200 SCRIPT_FILENAME="/home/karen/dev/cs410Projects2and3_2015to2016/webserverToPhysComp/public/test/index.php" php-cgi

I know that popen() forks and then execs a command, but with the above command - I'm not exactly sure what it's doing.

My first thought from your response above, when it said that you do not know the exact size to allocate for a PHP file in load(), is that
when the command is executing, you would need to redirect it's output (dup2) to know how much space is needed. But that happens before the load()
function, perhaps right before the popen() ? and I did not write that code. This is from an online course whose project I just downloaded
to attempt it, and that part of the code was given (interpret's popen()). So if that were needed, they would have done that.

So I'm not sure what to do here.

Perhaps it's time to take a break and go watch some PHP videos, or perhaps it's time to search for code examples of popen() followed by trying to respond
to the client browser?
 
Old 04-12-2016, 03:28 PM   #25
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian, Arch
Posts: 3,784

Rep: Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083
Quote:
Originally Posted by KarenWest View Post
What is happening here in this command? Maybe that would help me understand.
interpret: calling popen() on command = QUERY_STRING="" REDIRECT_STATUS=200 SCRIPT_FILENAME="/home/karen/dev/cs410Projects2and3_2015to2016/webserverToPhysComp/public/test/index.php" php-cgi

I know that popen() forks and then execs a command, but with the above command - I'm not exactly sure what it's doing.
It's running the php interpreter (which will interpret the script), output from the php code is hooked up to a pipe created by popen, and that's what you're reading from when you fread on the FILE* you get from it. Note that the php script is running in parallel to your own code reading the output.

Quote:
My first thought from your response above, when it said that you do not know the exact size to allocate for a PHP file in load(), is that
when the command is executing, you would need to redirect it's output (dup2) to know how much space is needed.
No, you would have make the redirection before executing the command (you can't redirect pipes that already have data flowing through them). e.g. add "> cgi_output.html" to the executed command string and then read from that file, but that's not a very nice solution anyway.

Quote:
So I'm not sure what to do here.
I see you're already using realloc(), so my question for you is: why do you need to know the size in advance at all?

Quote:
Perhaps it's time to take a break and go watch some PHP videos, or perhaps it's time to search for code examples of popen() followed by trying to respond
to the client browser?
It's not specific to PHP.
 
Old 04-12-2016, 03:48 PM   #26
KarenWest
Member
 
Registered: Jun 2011
Location: North Easton,MA
Distribution: currently Ubuntu Linux on my netbook while job searching, but also use Cygwin GNU tools on MSXP nb
Posts: 33

Original Poster
Rep: Reputation: Disabled
So my thought now is, if you have a popen'd php file, then you have to monitor the pipe returned from popen,
in a similar manner to this code below? In the code below, conf->sigChildDone is part of shared mem space.
The forward() function sends the data read from the pipe to the client browser's socket file descriptor.

Code:
ssize_t forward (int src, int dst)
{
    int size = 0;
    if (ioctl (src, FIONREAD, &size) == -1) {
       perror("ioctl");
       return -1;
    }
    ssize_t r = splice (src, NULL, dst, NULL, size, 0);
    if (r == -1) {
        perror ("splice");
        return -1;
    }
    return r;
}

void monitorPipesForOutfile()
{
  BOOL doneMonitoring = FALSE;
  BOOL checkForSigChild = FALSE;


  close(file[1]); (file being the pipe pointer returned from popen())

  FD_ZERO (&rfds);
  FD_ZERO (&wfds);
  FD_ZERO (&efds);

  FD_SET (file[0], &rfds);

  const int m = file[0] + 1;

  while (!doneMonitoring) {

    int r = select (m, &rfds, &wfds, &efds, 0);
    if (r == -1) {
      perror ("select error");
      doneMonitoring = TRUE;
    }
    else {
      if (FD_ISSET (file[0], &rfds)) {
	if (forward (file[0], cfd) == -1) {
	  doneMonitoring = TRUE;
        }
	else
	  {
	    printf("just wrote to outfile\n");
	  }
      }
      else
	{
	  checkForSigChild = TRUE;
	}
    }
    if ((checkForSigChild == TRUE) && (conf->sigChildDone == TRUE))
      {
	  doneMonitoring = TRUE;
      }
    else if ((checkForSigChild == TRUE) && (conf->sigChildDone == FALSE))
      {
	checkForSigChild = FALSE;
      }
  }
  
}
static void sig_child(int signo, siginfo_t *child_sigaction, void *context)
{

    conf->sigChildDone = TRUE;

return;	
}
 
Old 04-12-2016, 04:03 PM   #27
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian, Arch
Posts: 3,784

Rep: Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083
Quote:
Originally Posted by KarenWest View Post
So my thought now is, if you have a popen'd php file, then you have to monitor the pipe returned from popen,
in a similar manner to this code below? In the code below, conf->sigChildDone is part of shared mem space.
The forward() function sends the data read from the pipe to the client browser's socket file descriptor.
Hmm, looks a bit over-engineered. You should be able to just read a chunk from the popen'd pipe (pardon my pedantry, but I wouldn't say you're popen'ing a file, the file is incidental, you're reading the output from a program (the php program happens to be reading the php file, but it reads others too)) and then write that chunk to the socket. And notice that you can do exactly the same thing when doing fopen on a plain file (hence the ftell trick isn't really needed). Using splice optimizes this read-from-pipeA-write-to-pipeB thing, but it's not necessary. You definitely shouldn't need signal handlers or shared memory space.
 
Old 04-12-2016, 08:14 PM   #28
jpollard
Senior Member
 
Registered: Dec 2012
Location: Washington DC area
Distribution: Fedora, CentOS, Slackware
Posts: 4,912

Rep: Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513
You should know that popen is not a secure function - specially when it is given input from a remote connection...

All it takes is something to bypass the command... a suitably placed semicolon along with quotes...
And your system is taken over.

It didn't look like your parsing of the input included traps for shell special characters, so it looks vulnerable.


The usual way to read from a pipe is not to assume the size of the data being read... You can query and find out how many bytes are in the current buffer to be read (FIONREAD ioctl), then ensure that you have at least that many bytes before you read it.

Second, the popen handles the traps. So unless you are replacing popen with a fork+exec (much more secure), you don't need it. Just read until an end of file occurs. When you close the file (using pclose), the child will be reaped.

The reason you don't use "close" to close a file pointer - it doesn't work. popen returns a FILE *, and you have to close it with the pclose function. The reason to use the pclose is that the child forked by the popen is known to the pclose - and it can then reap the child, which has been known to terminate (or be terminated early).

A web server is a very dangerous thing to write unless you understand the security requirements. It is not something you can reliably do when you are still learning what the system itself provides.

Last edited by jpollard; 04-12-2016 at 08:26 PM.
 
Old 04-13-2016, 05:44 AM   #29
KarenWest
Member
 
Registered: Jun 2011
Location: North Easton,MA
Distribution: currently Ubuntu Linux on my netbook while job searching, but also use Cygwin GNU tools on MSXP nb
Posts: 33

Original Poster
Rep: Reputation: Disabled
Thank you for your responses. I'll might get back to this today but more likely on Friday and I will take into account
your comments and responses. It really helps so thank you!
 
Old 04-13-2016, 06:20 AM   #30
KarenWest
Member
 
Registered: Jun 2011
Location: North Easton,MA
Distribution: currently Ubuntu Linux on my netbook while job searching, but also use Cygwin GNU tools on MSXP nb
Posts: 33

Original Poster
Rep: Reputation: Disabled
Also, I forgot to mention that the comment about special characters that can cause traps in web servers,
I had forgotten about those considerations. My software security course focused entirely on those types
of things.
 
  


Reply

Tags
permission, realloc, sockets, webserver, write



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Web server with public IP address not reachable via domain name in the web browser floorripper Linux - Server 11 08-09-2013 09:55 PM
[SOLVED] What topics do I need to study for *web* client server programming - Web service? Aquarius_Girl Programming 9 03-15-2013 09:53 AM
[SOLVED] win7 web client problem with apache2 web server on linux lapinux Linux - Networking 2 03-15-2011 12:21 PM
writing the headers recived from browser to server praveensleeps Linux - Networking 3 11-06-2008 06:50 PM
Help with writing a small web server Diederick Programming 2 08-19-2005 07:46 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 09:34 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration