Ejemplo n.º 1
0
static int websTidyUrl(webs_t wp)
{
	char_t	*parts[64];					/* Array of ptr's to URL parts */
	char_t	*token, *url, *tidyurl;
	int		i, len, npart;

	a_assert(websValid(wp));

/*
 *	Copy the string so we don't destroy the original (yet)
 */
	url = bstrdup(B_L, wp->url);
	websDecodeUrl(url, url, gstrlen(url));

	len = npart = 0;
	parts[0] = NULL;
	token = gstrtok(url, T("/"));

/*
 *	Look at each directory segment and process "." and ".." segments
 *	Don't allow the browser to pop outside the root web. 
 */
	while (token != NULL) {
		if (gstrcmp(token, T("..")) == 0) {
			if (npart > 0) {
				npart--;
			}

		} else if (gstrcmp(token, T(".")) != 0) {
			parts[npart] = token;
			len += gstrlen(token) + 1;
			npart++;
		}
		token = gstrtok(NULL, T("/"));
	}

/*
 *	Re-construct URL. Need extra space all "/" and null.
 */
	if (npart || (gstrcmp(url, T("/")) == 0) || (url[0] == '\0')) {
		tidyurl = balloc(B_L, (len + 2) * sizeof(char_t));
		*tidyurl = '\0';

		for (i = 0; i < npart; i++) {
			gstrcat(tidyurl, T("/"));
			gstrcat(tidyurl, parts[i]);
		}

		bfree(B_L, url);

		bfree(B_L, wp->url);
		wp->url = tidyurl;
		return 0;
	} else {
		bfree(B_L, url);
		return -1;
	}
}
Ejemplo n.º 2
0
int sent_xmsg_stats(User *usr, XMsg *x, char *name) {
	switch(x->type) {
		case XMSG_X:
			usr->xsent++;
			user_dirty(usr, "xsent");
			update_stats(usr);
			inc_stats(STATS_XSENT);
			break;

		case XMSG_EMOTE:
			usr->esent++;
			user_dirty(usr, "esent");
			update_stats(usr);
			inc_stats(STATS_ESENT);
			break;

		case XMSG_FEELING:
			usr->fsent++;
			user_dirty(usr, "fsent");
			update_stats(usr);
			inc_stats(STATS_FSENT);
			break;

		case XMSG_QUESTION:
			usr->qsent++;
			user_dirty(usr, "qsent");
			update_stats(usr);
			inc_stats(STATS_QSENT);
			break;

		case XMSG_ANSWER:
			usr->qansw++;
			user_dirty(usr, "qansw");
			update_stats(usr);
			inc_stats(STATS_QANSW);
			break;

		default:
			;
	}
	if (name != NULL) {							/* add to talked_to list */
		if (usr->talked_to.len <= 0)
			gstrcpy(&(usr->talked_to), name);
		else {
			if (!cstrfind(usr->talked_to.str, name, ',')) {
				gstrcat(&(usr->talked_to), ",");
				gstrcat(&(usr->talked_to), name);
			}
		}
	}
	return 0;
}
Ejemplo n.º 3
0
int write_IOBuf(IOBuf *ob, void *data, int len) {
int n;

	if (ob->redirect != NULL) {
/*
	NB. output redirection may not work correctly when data contains a 0-byte
	In practice, this never happens because it works with strings and strlen() all the way
*/
		return gstrcat(ob->redirect, (char *)data);
	}
	if (len <= 0)
		return 0;

	if (len > OUTPUTBUF_SIZE) {			/* too much data to hold in IOBuf structure */
		if (flush_IOBuf(ob) == -1)
			return -1;

/* too much data, simply write it out directly without buffering in between */
		while(len > 0) {
			n = write(ob->fd, data, len);
			if (n == -1) {
				if (errno == EINTR)
					continue;
/*
	the write() would block; we can wait for it
*/
				if (errno == EAGAIN || errno == EWOULDBLOCK) {
					if (wait_fd_write(ob->fd, NULL) == -1) {
						ob->out_idx = -1;
						return -1;
					}
					continue;			/* retry write() */
				}
				return -1;		/* some kind of error, probably EBADF ? */
			}
			len -= n;
		}
		return 0;
	}
	if (ob->out_idx + len > OUTPUTBUF_SIZE) {
		if (flush_IOBuf(ob) == -1)
			return -1;
	}
	memcpy(ob->outbuf + ob->out_idx, data, len);		/* buffer data */
	ob->out_idx += len;
	return 0;
}
Ejemplo n.º 4
0
int websValidateUrl(webs_t wp, char_t *path)
{
	char_t	*parts[64];					/* Array of ptr's to URL parts */
	char_t	*token, *dir, *lpath;
	int		i, len, npart;

	a_assert(websValid(wp));
	a_assert(path);

	dir = websGetRequestDir(wp);
	if (dir == NULL || *dir == '\0') {
		return -1;
	}

/*
 *	Copy the string so we don't destroy the original
 */
	path = bstrdup(B_L, path);
	websDecodeUrl(path, path, gstrlen(path));

	len = npart = 0;
	parts[0] = NULL;

   /*
    * 22 Jul 02 -- there were reports that a directory traversal exploit was
    * possible in the WebServer running under Windows if directory paths
    * outside the server's specified root web were given by URL-encoding the
    * backslash character, like:
    *
    *  GoAhead is vulnerable to a directory traversal bug. A request such as
    *
    *  GoAhead-server/../../../../../../../ results in an error message
    *  'Cannot open URL'.

    *  However, by encoding the '/' character, it is possible to break out of
    *  the
    *  web root and read arbitrary files from the server.
    *  Hence a request like:
    *
    *  GoAhead-server/..%5C..%5C..%5C..%5C..%5C..%5C/winnt/win.ini returns the
    *  contents of the win.ini file.
    * (Note that the description uses forward slashes (0x2F), but the example
    * uses backslashes (0x5C). In my tests, forward slashes are correctly
    * trapped, but backslashes are not. The code below substitutes forward
    * slashes for backslashes before attempting to validate that there are no
    * unauthorized paths being accessed.
    */
   token = gstrchr(path, '\\');
   while (token != NULL)
   {
      *token = '/';
      token = gstrchr(token, '\\');
   }

	token = gstrtok(path, T("/"));

/*
 *	Look at each directory segment and process "." and ".." segments
 *	Don't allow the browser to pop outside the root web.
 */
	while (token != NULL) {
		if (gstrcmp(token, T("..")) == 0) {
			if (npart > 0) {
				npart--;
			}

		} else if (gstrcmp(token, T(".")) != 0) {
			parts[npart] = token;
			len += gstrlen(token) + 1;
			npart++;
		}
		token = gstrtok(NULL, T("/"));
	}

/*
 *	Create local path for document. Need extra space all "/" and null.
 */
	if (npart || (gstrcmp(path, T("/")) == 0) || (path[0] == '\0')) {
		lpath = balloc(B_L, (gstrlen(dir) + 1 + len + 1) * sizeof(char_t));
		gstrcpy(lpath, dir);

		for (i = 0; i < npart; i++) {
			gstrcat(lpath, T("/"));
			gstrcat(lpath, parts[i]);
		}
		websSetRequestLpath(wp, lpath);
		bfree(B_L, path);
		bfree(B_L, lpath);

	} else {
		bfree(B_L, path);
		return -1;
	}
	return 0;
}
Ejemplo n.º 5
0
int websValidateUrl(webs_t wp, char_t *path)
{
   /*
     Thanks to Dhanwa T ([email protected]) for this fix -- previously,
     if an URL was requested having more than (the hardcoded) 64 parts,
     the webServer would experience a hard crash as it attempted to
     write past the end of the array 'parts'.
	 Also fixes: http://www.securiteam.com/securitynews/5MP0C1580W.html
    */
	char_t	*parts[MAX_URL_DEPTH];	/* Array of ptr's to URL parts */
	char_t	*token, *dir, *lpath; 
	int	      i, len, npart;

	a_assert(websValid(wp));
	a_assert(path);

	dir = websGetRequestDir(wp);
	if (dir == NULL || *dir == '\0') {
		return -1;
	}

/*
 *	Copy the string so we don't destroy the original
 */
	path = bstrdup(B_L, path);
	websDecodeUrl(path, path, gstrlen(path));

	len = npart = 0;
	parts[0] = NULL;

   /*
    * Fixed by Matt Moore, 22 Jul 02
	* http://www.securiteam.com/securitynews/5RP0I007PG.html
	* http://www.securiteam.com/securitynews/5QP010U3FS.html
	* 
	* There were reports that a directory traversal exploit was
    * possible in the WebServer running under Windows if directory paths
    * outside the server's specified root web were given by URL-encoding the
    * backslash character, like:
    *
    *  GoAhead is vulnerable to a directory traversal bug. A request such as
    *  
    *  GoAhead-server/../../../../../../../ results in an error message
    *  'Cannot open URL'.
    *  However, by encoding the '/' character, it is possible to break out of
    *  the web root and read arbitrary files from the server.
    *  Hence a request like:
    * 
    *  GoAhead-server/..%5C..%5C..%5C..%5C..%5C..%5C/winnt/win.ini returns the
    *  contents of the win.ini file.
    * (Note that the description uses forward slashes (0x2F), but the example
    * uses backslashes (0x5C). In my tests, forward slashes are correctly
    * trapped, but backslashes are not. The code below substitutes forward
    * slashes for backslashes before attempting to validate that there are no
    * unauthorized paths being accessed.
    */
	token = gstrchr(path, '\\');
	while (token != NULL) {
		*token = '/';
		token = gstrchr(token, '\\');
	}
	token = gstrtok(path, T("/"));

/*
 *	Look at each directory segment and process "." and ".." segments
 *	Don't allow the browser to pop outside the root web. 
 */
	while (token != NULL) 
   {
      if (npart >= MAX_URL_DEPTH)
      {
         /*
          * malformed URL -- too many parts for us to process.
          */
         bfree(B_L, path);
         return -1;
      }
		if (gstrcmp(token, T("..")) == 0) 
      {
			if (npart > 0) 
         {
				npart--;
			}
		} else if (gstrcmp(token, T(".")) != 0) {
			parts[npart] = token;
			len += gstrlen(token) + 1;
			npart++;
		}
		token = gstrtok(NULL, T("/"));
	}

#ifdef WIN32
   if (isBadWindowsPath(parts, npart))
   {
      bfree(B_L, path);
      return -1;
   }

#endif

/*
 *	Create local path for document. Need extra space all "/" and null.
 */
	if (npart || (gstrcmp(path, T("/")) == 0) || (path[0] == '\0')) {
		lpath = balloc(B_L, (gstrlen(dir) + 1 + len + 1) * sizeof(char_t));
		gstrcpy(lpath, dir);

		for (i = 0; i < npart; i++) {
			gstrcat(lpath, T("/"));
			gstrcat(lpath, parts[i]);
		}
		websSetRequestLpath(wp, lpath);
		bfree(B_L, path);
		bfree(B_L, lpath);
	} else {
		bfree(B_L, path);
		return -1;
	}
	return 0;
}
Ejemplo n.º 6
0
int websLaunchCgiProc( char_t* cgiPath, char_t** argp, char_t** envp,
                       char_t* stdIn, char_t* stdOut )
{
    STARTUPINFO			newinfo;
    SECURITY_ATTRIBUTES security;
    PROCESS_INFORMATION	procinfo;		/*  Information about created proc   */
    DWORD				dwCreateFlags;
    char_t*				cmdLine;
    char_t**				pArgs;
    BOOL				bReturn;
    int					i, nLen;
    unsigned char*		pEnvData;
    /*
     *	Replace directory delimiters with Windows-friendly delimiters
     */
    nLen = gstrlen( cgiPath );

    for ( i = 0; i < nLen; i++ )
    {
        if ( cgiPath[i] == '/' )
        {
            cgiPath[i] = '\\';
        }
    }

    /*
     *	Calculate length of command line
     */
    nLen = 0;
    pArgs = argp;

    while ( pArgs && *pArgs &&** pArgs )
    {
        nLen += gstrlen( *pArgs ) + 1;
        pArgs++;
    }

    /*
     *	Construct command line
     */
    cmdLine = balloc( B_L, sizeof( char_t ) * nLen );
    a_assert( cmdLine );
    gstrcpy( cmdLine, "" );
    pArgs = argp;

    while ( pArgs && *pArgs &&** pArgs )
    {
        gstrcat( cmdLine, *pArgs );
        gstrcat( cmdLine, T( " " ) );
        pArgs++;
    }

    /*
    *	Create the process start-up information
    */
    memset( &newinfo, 0, sizeof( newinfo ) );
    newinfo.cb          = sizeof( newinfo );
    newinfo.dwFlags     = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
    newinfo.wShowWindow = SW_HIDE;
    newinfo.lpTitle     = NULL;
    /*
     *	Create file handles for the spawned processes stdin and stdout files
     */
    security.nLength = sizeof( SECURITY_ATTRIBUTES );
    security.lpSecurityDescriptor = NULL;
    security.bInheritHandle = TRUE;
    /*
     *	Stdin file should already exist.
     */
    newinfo.hStdInput = CreateFile( stdIn, GENERIC_READ,
                                    FILE_SHARE_READ, &security, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
    /*
     *	Stdout file is created and file pointer is reset to start.
     */
    newinfo.hStdOutput = CreateFile( stdOut, GENERIC_READ | GENERIC_WRITE,
                                     FILE_SHARE_READ + FILE_SHARE_WRITE, &security, OPEN_ALWAYS,
                                     FILE_ATTRIBUTE_NORMAL, NULL );
    SetFilePointer( newinfo.hStdOutput, 0, NULL, FILE_END );
    /*
     *	Stderr file is set to Stdout.
     */
    newinfo.hStdError =	newinfo.hStdOutput;
    dwCreateFlags = CREATE_NEW_CONSOLE;
    pEnvData = tableToBlock( envp );
    /*
     *	CreateProcess returns errors sometimes, even when the process was
     *	started correctly.  The cause is not evident.  For now: we detect
     *	an error by checking the value of procinfo.hProcess after the call.
     */
    procinfo.hProcess = NULL;
    bReturn = CreateProcess(
                  NULL,				/*  Name of executable module        */
                  cmdLine,			/*  Command line string              */
                  NULL,				/*  Process security attributes      */
                  NULL,				/*  Thread security attributes       */
                  TRUE,				/*  Handle inheritance flag          */
                  dwCreateFlags,		/*  Creation flags                   */
                  pEnvData,			/*  New environment block            */
                  NULL,				/*  Current directory name           */
                  &newinfo,			/*  STARTUPINFO                      */
                  &procinfo );			/*  PROCESS_INFORMATION              */

    if ( procinfo.hThread != NULL )
    {
        CloseHandle( procinfo.hThread );
    }

    if ( newinfo.hStdInput )
    {
        CloseHandle( newinfo.hStdInput );
    }

    if ( newinfo.hStdOutput )
    {
        CloseHandle( newinfo.hStdOutput );
    }

    bfree( B_L, pEnvData );
    bfree( B_L, cmdLine );

    if ( bReturn == 0 )
    {
        return -1;
    }

    else
    {
        return ( int ) procinfo.hProcess;
    }
}