Exemplo n.º 1
0
char_t *websCalcDigest(webs_t wp)
{
#ifdef DIGEST_ACCESS_SUPPORT
	char_t	*digest, *a1, *a1prime, *a2, *a2prime, *preDigest, *method;

	a_assert(wp);
	digest = NULL;

/*
 *	Calculate first portion of digest H(A1)
 */
	a1 = NULL;
	fmtAlloc(&a1, 255, T("%s:%s:%s"), wp->userName, wp->realm, wp->password);
	a_assert(a1);
	a1prime = websMD5(a1);
	bfreeSafe(B_L, a1);
/*
 *	Calculate second portion of digest H(A2)
 */
	method = websGetVar(wp, T("REQUEST_METHOD"), NULL);
	a_assert(method);
	a2 = NULL;
	fmtAlloc(&a2, 255, T("%s:%s"), method, wp->uri);
	a_assert(a2);
	a2prime = websMD5(a2);
	bfreeSafe(B_L, a2);
/*
 *	Construct final digest KD(H(A1):nonce:H(A2))
 */
	a_assert(a1prime);
	a_assert(a2prime);
	a_assert(wp->nonce);

	preDigest = NULL;
	if (!wp->qop) {
		fmtAlloc(&preDigest, 255, T("%s:%s:%s"), a1prime, wp->nonce, a2prime);
	} else {
		fmtAlloc(&preDigest, 255, T("%s:%s:%s:%s:%s:%s"), 
			a1prime, 
			wp->nonce,
			wp->nc,
			wp->cnonce,
			wp->qop,
			a2prime);
	}

	a_assert(preDigest);
	digest = websMD5(preDigest);
/*
 *	Now clean up
 */
	bfreeSafe(B_L, a1prime);
	bfreeSafe(B_L, a2prime);
	bfreeSafe(B_L, preDigest);
	return digest;
#else
	return NULL;
#endif /* DIGEST_ACCESS_SUPPORT */
}
Exemplo n.º 2
0
char_t *websCalcUrlDigest(webs_t wp)
{
	char_t	*digest, *a1, *a1prime, *a2, *a2prime, *preDigest, *method;

	a_assert(wp);
	digest = NULL;

/*
 *	Calculate first portion of digest H(A1)
 */
	a1 = NULL;
	fmtAlloc(&a1, 255, T("%s:%s:%s"), wp->userName, wp->realm, wp->password);
	a_assert(a1);
	a1prime = websMD5(a1);
	bfreeSafe(B_L, a1);
/*
 *	Calculate second portion of digest H(A2)
 */
	method = websGetVar(wp, T("REQUEST_METHOD"), NULL);
	a_assert(method);
	/* Fixes by Richard Laing, 2003/7/15 */
	a2 = balloc(B_L, (gstrlen(method) +2 + gstrlen(wp->url) ) * sizeof(char_t));
	a_assert(a2);
	gsprintf(a2, T("%s:%s"), method, wp->url);
	a2prime = websMD5(a2);
	bfreeSafe(B_L, a2);
/*
 *	Construct final digest KD(H(A1):nonce:H(A2))
 */
	a_assert(a1prime);
	a_assert(a2prime);
	a_assert(wp->nonce);

	preDigest = NULL;
	if (!wp->qop) {
		fmtAlloc(&preDigest, 255, T("%s:%s:%s"), a1prime, wp->nonce, a2prime);
	} else {
		fmtAlloc(&preDigest, 255, T("%s:%s:%s:%s:%s:%s"), 
			a1prime, 
			wp->nonce,
			wp->nc,
			wp->cnonce,
			wp->qop,
			a2prime);
	}

	a_assert(preDigest);
	digest = websMD5(preDigest);
/*
 *	Now clean up
 */
	bfreeSafe(B_L, a1prime);
	bfreeSafe(B_L, a2prime);
	bfreeSafe(B_L, preDigest);
	return digest;
}
Exemplo n.º 3
0
char_t *websCalcNonce(webs_t wp)
{
	char_t		*nonce, *prenonce;
	time_t		longTime;
#if defined(WIN32)
	char_t		buf[26];
	errno_t	error;
	struct tm	newtime;
#else
	struct tm	*newtime;
#endif

	a_assert(wp);
/*
 *	Get time as long integer.
 */
	time(&longTime);
/*
 *	Convert to local time.
 */
#if !defined(WIN32)
	newtime = localtime(&longTime);
#else
	
	error = localtime_s(&newtime, &longTime);
#endif
/*
 *	Create prenonce string.
 */
#if !defined(WIN32)
	prenonce = NULL;
	fmtAlloc(&prenonce, 256, T("%s:%s:%s"), RANDOMKEY, gasctime(newtime),
		wp->realm); 
#else
	asctime_s(buf, elementsof(buf), &newtime);
	fmtAlloc(&prenonce, 256, T("%s:%s:%s"), RANDOMKEY, buf, 
		RANDOMKEY); 
#endif

	a_assert(prenonce);
/*
 *	Create the nonce
 */
    nonce = websMD5(prenonce);
/*
 *	Cleanup
 */
	bfreeSafe(B_L, prenonce);

	return nonce;
}
Exemplo n.º 4
0
static int dbWriteKeyValue(int fd, char_t *key, char_t *value)
{
    int		rc;
    int		len;
    char_t	*pLineOut;

    a_assert(key && *key);
    a_assert(value);

    fmtAlloc(&pLineOut, BUF_MAX, T("%s=%s\n"), key, value);

    if (pLineOut) {
        len = gstrlen(pLineOut);
#ifdef CE
        rc = writeUniToAsc(fd, pLineOut, len);
#else
        rc = gwrite(fd, pLineOut, len);
#endif
        bfree(B_L, pLineOut);
    } else {
        rc = -1;
    }

    return rc;
}
Exemplo n.º 5
0
/*********************************************************************************************************
** 函数名称: websGetCgiCommName
** 功能描述: Returns a pointer to an allocated qualified unique temporary file name.
**           This filename must eventually be deleted with bfree();
** 输 入  : ...
** 输 出  :
** 全局变量:
** 调用模块:
*********************************************************************************************************/
char_t *websGetCgiCommName()
{
    char_t *tname, buf[FNAMESIZE];

    fmtAlloc(&tname, FNAMESIZE, T("%s/%s"), ggetcwd(buf, FNAMESIZE), tmpnam(NULL));
    return tname;
}
Exemplo n.º 6
0
void error( E_ARGS_DEC, int etype, char_t* fmt, ... )
{
    va_list 	args;
    char_t*		fmtBuf, *buf;
    va_start( args, fmt );
    fmtValloc( &fmtBuf, E_MAX_ERROR, fmt, args );

    if ( etype == E_LOG )
    {
        fmtAlloc( &buf, E_MAX_ERROR, T( "%s\n" ), fmtBuf );
        /*#ifdef DEV*/
    }

    else if ( etype == E_ASSERT )
    {
        fmtAlloc( &buf, E_MAX_ERROR,
                  T( "Assertion %s, failed at %s %d\n" ), fmtBuf, E_ARGS );
        /*#endif*/
    }

    else if ( etype == E_USER )
    {
        fmtAlloc( &buf, E_MAX_ERROR, T( "%s\n" ), fmtBuf );
    }

    /*
     * bugfix -- if etype is not E_LOG, E_ASSERT, or E_USER, the call to
     * bfreeSafe(B_L, buf) below will fail, because 'buf' is randomly
     * initialized. To be nice, we format a message saying that this is an
     * unknown message type, and in doing so give buf a valid value. Thanks
     * to Simon Byholm.
     */
    else
    {
        fmtAlloc( &buf, E_MAX_ERROR, T( "Unknown error" ) );
    }

    va_end( args );
    bfree( B_L, fmtBuf );

    if ( errorHandler )
    {
        errorHandler( etype, buf );
    }

    bfreeSafe( B_L, buf );
}
Exemplo n.º 7
0
char_t *websCalcNonce(webs_t wp)
{
	char_t		*nonce, *prenonce;
	struct tm	*newtime;
	time_t		longTime;

	a_assert(wp);
/*
 *	Get time as long integer.
 */
	time(&longTime);
/*
 *	Convert to local time.
 */
	newtime = localtime(&longTime);
/*
 *	Create prenonce string.
 */
	prenonce = NULL;
#ifdef DIGEST_ACCESS_SUPPORT
	fmtAlloc(&prenonce, 256, T("%s:%s:%s"), RANDOMKEY, gasctime(newtime),
		wp->realm); 
#else
	fmtAlloc(&prenonce, 256, T("%s:%s:%s"), RANDOMKEY, gasctime(newtime), 
		RANDOMKEY); 
#endif
	a_assert(prenonce);
/*
 *	Create the nonce
 */
    nonce = websMD5(prenonce);
/*
 *	Cleanup
 */
	bfreeSafe(B_L, prenonce);

	return nonce;
}
Exemplo n.º 8
0
int websDefaultHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg,
						char_t *url, char_t *path, char_t *query)
{
	websStatType	sbuf;
	char_t			*lpath, *tmp, *date;
	int				bytes, flags, nchars;

	a_assert(websValid(wp));
	a_assert(url && *url);
	a_assert(path);
	a_assert(query);

/*
 *	Validate the URL and ensure that ".."s don't give access to unwanted files
 */
	flags = websGetRequestFlags(wp);

	if (websValidateUrl(wp, path) < 0) {
		websError(wp, 500, T("Invalid URL %s"), url);
		return 1;
	}
	lpath = websGetRequestLpath(wp);
	nchars = gstrlen(lpath) - 1;
	if (lpath[nchars] == '/' || lpath[nchars] == '\\') {
		lpath[nchars] = '\0';
	}

/*
 *	If the file is a directory, redirect using the nominated default page
 */
	if (websPageIsDirectory(lpath)) {
		nchars = gstrlen(path);
		if (path[nchars-1] == '/' || path[nchars-1] == '\\') {
			path[--nchars] = '\0';
		}
		nchars += gstrlen(websDefaultPage) + 2;
		fmtAlloc(&tmp, nchars, T("%s/%s"), path, websDefaultPage);
		websRedirect(wp, tmp);
		bfreeSafe(B_L, tmp);
		return 1;
	}

/*
 *	Open the document. Stat for later use.
 */
	if (websPageOpen(wp, lpath, path, SOCKET_RDONLY | SOCKET_BINARY,
		0666) < 0) {
		websError(wp, 400, T("Cannot open URL <b>%s</b>"), url);
		return 1;
	}

	if (websPageStat(wp, lpath, path, &sbuf) < 0) {
		websError(wp, 400, T("Cannot stat page for URL <b>%s</b>"), url);
		return 1;
	}

/*
 *	If the page has not been modified since the user last received it and it
 *	is not dynamically generated each time (ASP), then optimize request by
 *	sending a 304 Use local copy response
 */
	websStats.localHits++;
#ifdef WEBS_IF_MODIFIED_SUPPORT
	if (flags & WEBS_IF_MODIFIED && !(flags & WEBS_ASP)) {
		if (sbuf.mtime <= wp->since) {
			websWrite(wp, T("HTTP/1.0 304 Use local copy\r\n"));

/*
 *			by license terms the following line of code must
 *			not be modified.
 */
			websWrite(wp, T("Server: %s\r\n"), WEBS_NAME);

			if (flags & WEBS_KEEP_ALIVE) {
				websWrite(wp, T("Connection: keep-alive\r\n"));
			}
			websWrite(wp, T("\r\n"));
			websSetRequestFlags(wp, flags |= WEBS_HEADER_DONE);
			websDone(wp, 304);
			return 1;
		}
	}
#endif

/*
 *	Output the normal HTTP response header
 */
	if ((date = websGetDateString(NULL)) != NULL) {
		websWrite(wp, T("HTTP/1.0 200 OK\r\nDate: %s\r\n"), date);

/*
 *		By license terms the following line of code must not be modified.
 */
		websWrite(wp, T("Server: %s\r\n"), WEBS_NAME);
		bfree(B_L, date);
	}
	flags |= WEBS_HEADER_DONE;

/*
 *	If this is an ASP request, ensure the remote browser doesn't cache it.
 *	Send back both HTTP/1.0 and HTTP/1.1 cache control directives
 */
	if (flags & WEBS_ASP) {
		bytes = 0;
		websWrite(wp, T("Pragma: no-cache\r\nCache-Control: no-cache\r\n"));

	} else {
		if ((date = websGetDateString(&sbuf)) != NULL) {
			websWrite(wp, T("Last-modified: %s\r\n"), date);
			bfree(B_L, date);
		}
		bytes = sbuf.size;
	}

	if (bytes) {
		websWrite(wp, T("Content-length: %d\r\n"), bytes);
		websSetRequestBytes(wp, bytes);
	}
	websWrite(wp, T("Content-type: %s\r\n"), websGetRequestType(wp));

	if ((flags & WEBS_KEEP_ALIVE) && !(flags & WEBS_ASP)) {
		websWrite(wp, T("Connection: keep-alive\r\n"));
	}
	websWrite(wp, T("\r\n"));

/*
 *	All done if the browser did a HEAD request
 */
	if (flags & WEBS_HEAD_REQUEST) {
		websDone(wp, 200);
		return 1;
	}

/*
 *	Evaluate ASP requests
 */
	if (flags & WEBS_ASP) {
		if (websAspRequest(wp, lpath) < 0) {
			return 1;
		}
		websDone(wp, 200);
		return 1;
	}

#ifdef WEBS_SSL_SUPPORT
	if (wp->flags & WEBS_SECURE) {
		websDefaultWriteEvent(wp);
	} else {
		websSetRequestSocketHandler(wp, SOCKET_WRITABLE, websDefaultWriteEvent);
	}
#else
/*
 *	For normal web documents, return the data via background write
 */
	websSetRequestSocketHandler(wp, SOCKET_WRITABLE, websDefaultWriteEvent);
#endif
	return 1;
}
Exemplo n.º 9
0
/*
 *	LINUX, MACOSX, ETC: Build whitelist
 */
#else /* !WIN */
static int websBuildWhitelistRecursive(char *_path, fileNode_t *dir, int level)
{
	struct dirent	*findData, *result;
	DIR				*fh;
	fileNode_t		*cnode, *nnode; /* current node, next node */
	int		firstTime;
	char	path[PATH_MAX];
	char	tmppath[PATH_MAX];

	firstTime = 1;
	cnode = dir;
	/* On some platforms such as Solaris, struct dirent includes only one
	 * byte for d_name field, meaning we would overflow the field when
	 * readdir_r is called.  So we check for this here.
	 * Another potential issue is if somehow a filesystem is mounted or linked
	 * in a subdirectory or file that has name longer than PATH_MAX.  We 
	 * ignore that possibility here, and leave it to the user to ensure that
	 * the wwwroot directory does not contain this configuration.
	 * http://womble.decadentplace.org.uk/readdir_r-advisory.html
	 */ 
	if (sizeof(struct dirent) > PATH_MAX) {
		findData = balloc(B_L, sizeof(struct dirent));
	} else {
		findData = balloc(B_L, sizeof(struct dirent) + PATH_MAX);
	}
	websMakePath(path, _path, NULL, 0);
	if ((fh = opendir(path)) == NULL) {
		bfree(B_L, findData);
		return -1;	/* Likely no permission to access this directory */
	}
	while ((readdir_r(fh, findData, &result) == 0) && result) {
		if ((strcmp(findData->d_name, ".") == 0) ||
				(strcmp(findData->d_name, "..") == 0) ||
				(findData->d_type != DT_REG && findData->d_type != DT_DIR)) {
			continue;
		}
		nnode = balloc(B_L, sizeof(fileNode_t));
		memset(nnode, 0x0, sizeof(fileNode_t));
		if (findData->d_type == DT_DIR) {
			fmtAlloc(&(nnode->name), PATH_MAX, "%s/", findData->d_name);
			nnode->flags |= WHITELIST_DIR;
		} else {
			nnode->name = bstrdup(B_L, findData->d_name);
		}
		if (firstTime) {
			cnode->child = nnode;
			firstTime = 0;
		} else {
			cnode->next = nnode;
		}
		cnode = nnode;
		if (strncmp(path + strlen(websDefaultDir), "/" CGI_BIN, 
				strlen(CGI_BIN) + 1) == 0) {
			cnode->flags |= WHITELIST_CGI;
		}
#ifdef WEBS_SSL_SUPPORT
		sslList_t	*l;
		for (l = sslList; l != NULL; l = l->next) {
			if (strncmp(path + strlen(websDefaultDir), l->url, 
					strlen(l->url)) == 0) {
				cnode->flags |= WHITELIST_SSL;
				break;
			}
		}
#endif /* WEBS_SSL_SUPPORT */
		if (findData->d_type == DT_DIR) {
			websMakePath(tmppath, path, findData->d_name, 0);
			if (level < MAX_URL_DEPTH) {
				if (websBuildWhitelistRecursive(tmppath, cnode, level + 1) < 0){
					cnode->flags |= WHITELIST_BLOCKED;
				}
			}
		}
	}
	bfree(B_L, findData);
	closedir(fh);
	return 0;
}
Exemplo n.º 10
0
int websDefaultHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg,
						char_t *url, char_t *path, char_t *query)
{
	websStatType	sbuf;
	char_t			*lpath, *tmp, *date;
	int				bytes, flags, nchars, rc;

	a_assert(websValid(wp));
	a_assert(url && *url);
	a_assert(path);
	a_assert(query);

	flags = websGetRequestFlags(wp);
/*
 *	We do whitelist validation in addition to standard URL validation.
 *	The whitelist should really catch anything invalid first.
 *	If the whitelist check fails, rebuild the list and try again.
 *	Also validate if we are not on a secure connection, but the whitelist
 *	entry has the SSL flag set, do not serve the page.
 */
#ifdef WEBS_WHITELIST_SUPPORT
printf ("wp->url: (%s)\n", wp->url);
	if ((rc = websWhitelistCheck(wp->url)) < 0) {
		websBuildWhitelist();
		if ((rc = websWhitelistCheck(wp->url)) < 0) {
			websError(wp, 404, T("Cannot open URL: type 1"));
			return 1;
		}
	}
	if (!(flags & WEBS_SECURE) && (rc & WHITELIST_SSL)) {
		websError(wp, 500, T("HTTPS access required"));
		return 1;
	}
#endif /* WEBS_WHITELIST_SUPPORT */
/*
 *	Validate the URL and ensure that ".."s don't give access to unwanted files
 */
	if (websValidateUrl(wp, path) < 0) {
      /* 
       * preventing a cross-site scripting exploit -- you may restore the
       * following line of code to revert to the original behavior...
		websError(wp, 500, T("Invalid URL %s"), url);
       */
		websError(wp, 500, T("Invalid URL"));
		websBuildWhitelist();
		return 1;
	}
	lpath = websGetRequestLpath(wp);
	nchars = gstrlen(lpath) - 1;
	if (lpath[nchars] == '/' || lpath[nchars] == '\\') {
		lpath[nchars] = '\0';
	}

/*
 *	If the file is a directory, redirect using the nominated default page
 */
	if (websPageIsDirectory(lpath)) {
		nchars = gstrlen(path);
		if (path[nchars-1] == '/' || path[nchars-1] == '\\') {
			path[--nchars] = '\0';
		}
		nchars += gstrlen(websDefaultPage) + 2;
		fmtAlloc(&tmp, nchars, T("%s/%s"), path, websDefaultPage);
printf ("websDefaultHandler: tmp(%s)\n", tmp);
		websRedirect(wp, tmp);
		bfreeSafe(B_L, tmp);
		return 1;
	}

printf ("we now open the web pages\n");
printf ("lpath(%s), path(%s)\n", lpath, path);

/*
 *	Open the document. Stat for later use.
 */
	if (websPageOpen(wp, lpath, path, O_RDONLY | O_BINARY, 
		0666) < 0) 
   {
      /* 10 Dec 02 BgP -- according to 
       * <http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html>, 
       * the proper code to return here is NOT 400 (old code), which is used
       * to indicate a malformed request. Here, the request is good, but the
       * error we need to tell the client about is 404 (Not Found).
       */
      /* 
       * 17 Mar 03 BgP -- prevent a cross-site scripting exploit
		websError(wp, 404, T("Cannot open URL %s"), url);
       */
      
		websError(wp, 404, T("Cannot open URL, type 2"));
		websBuildWhitelist();
		return 1;
	} 

printf ("lpath(%s), path(%s)\n", lpath, path);
	if (websPageStat(wp, lpath, path, &sbuf) < 0) {
      /*
       * 17 Mar 03 BgP
       * prevent a cross-site scripting exploit
		websError(wp, 400, T("Cannot stat page for URL %s"), url);
       */
		websError(wp, 400, T("Cannot stat page for URL"));
		websBuildWhitelist();
		return 1;
	}

/*
 *	If the page has not been modified since the user last received it and it
 *	is not dynamically generated each time (ASP), then optimize request by
 *	sending a 304 Use local copy response
 */
	websStats.localHits++;
#ifdef WEBS_IF_MODIFIED_SUPPORT
	if (flags & WEBS_IF_MODIFIED && !(flags & WEBS_ASP)) {
		if (sbuf.mtime <= wp->since) {
			websWrite(wp, T("HTTP/1.0 304 Use local copy\r\n"));

/*
 *			by license terms the following line of code must
 *			not be modified.
 */
			websWrite(wp, T("Server: %s\r\n"), WEBS_NAME);

			if (flags & WEBS_KEEP_ALIVE) {
				websWrite(wp, T("Connection: keep-alive\r\n"));
			}
			websWrite(wp, T("\r\n"));
			websSetRequestFlags(wp, flags |= WEBS_HEADER_DONE);
			websDone(wp, 304);
			return 1;
		}
	}
#endif

/*
 *	Output the normal HTTP response header
 */
	if ((date = websGetDateString(NULL)) != NULL) {
		websWrite(wp, T("HTTP/1.0 200 OK\r\nDate: %s\r\n"), date);
/*
 *		The Server HTTP header below must not be modified unless
 *		explicitly allowed by licensing terms.
 */
#ifdef WEBS_SSL_SUPPORT
		websWrite(wp, T("Server: %s/%s %s/%s\r\n"), 
			WEBS_NAME, WEBS_VERSION, SSL_NAME, SSL_VERSION);
#else
		websWrite(wp, T("Server: %s/%s\r\n"), WEBS_NAME, WEBS_VERSION);
#endif
		bfree(B_L, date);
	}
	flags |= WEBS_HEADER_DONE;

/*
 *	If this is an ASP request, ensure the remote browser doesn't cache it.
 *	Send back both HTTP/1.0 and HTTP/1.1 cache control directives
 */
	if (flags & WEBS_ASP) {
		bytes = 0;
		websWrite(wp, T("Pragma: no-cache\r\nCache-Control: no-cache\r\n"));

	} else {
		if ((date = websGetDateString(&sbuf)) != NULL) {
			websWrite(wp, T("Last-modified: %s\r\n"), date);
			bfree(B_L, date);
		}
		bytes = sbuf.size;
	}

	if (bytes) {
		websWrite(wp, T("Content-length: %d\r\n"), bytes);
		websSetRequestBytes(wp, bytes);
	}
	websWrite(wp, T("Content-type: %s\r\n"), websGetRequestType(wp));

	if ((flags & WEBS_KEEP_ALIVE) && !(flags & WEBS_ASP)) {
		websWrite(wp, T("Connection: keep-alive\r\n"));
	}
	websWrite(wp, T("\r\n"));

/*
 *	All done if the browser did a HEAD request
 */
	if (flags & WEBS_HEAD_REQUEST) {
		websDone(wp, 200);
		return 1;
	}

/*
 *	Evaluate ASP requests
 */
	if (flags & WEBS_ASP) {
		if (websAspRequest(wp, lpath) < 0) {
			return 1;
		}
		websDone(wp, 200);
		return 1;
	}
/*
 *	Return the data via background write
 */
	websSetRequestSocketHandler(wp, SOCKET_WRITABLE, websDefaultWriteEvent);
	return 1;
}
Exemplo n.º 11
0
static int websBuildWhitelistRecursive(char *_path, fileNode_t *dir, int level)
{
	WIN32_FIND_DATA	findData;
	HANDLE	fh;
	fileNode_t	*cnode, *nnode; /* current node, next node */
#ifdef WEBS_SSL_SUPPORT
	sslList_t	*l;
#endif
	int		rc = 0;
	int		firstTime;
	char	path[MAX_PATH];
	char	tmppath[MAX_PATH];

	firstTime = 1;
	cnode = dir;
	websMakePath(path, _path, NULL, 1);
	fh = FindFirstFile((LPCSTR)path, &findData);
	while (fh != INVALID_HANDLE_VALUE) {
		if ((strcmp(findData.cFileName, ".") == 0) ||
				(strcmp(findData.cFileName, "..") == 0) ||
				(findData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) ||
				(findData.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)) {
			goto nextFile;
		}
		nnode = balloc(B_L, sizeof(fileNode_t));
		memset(nnode, 0x0, sizeof(fileNode_t));
		if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
			fmtAlloc(&(nnode->name), MAX_PATH, "%s/", findData.cFileName);
			nnode->flags |= WHITELIST_DIR;
		} else {
			nnode->name = bstrdup(B_L, findData.cFileName);
		}
		if (firstTime) {
			cnode->child = nnode;
			firstTime = 0;
		} else {
			cnode->next = nnode;
		}
		cnode = nnode;
		if (strncmp(path + strlen(websDefaultDir), "/" CGI_BIN, 
				strlen(CGI_BIN) + 1) == 0) {
			cnode->flags |= WHITELIST_CGI;
		}
#ifdef WEBS_SSL_SUPPORT
		for (l = sslList; l != NULL; l = l->next) {
			if (strncmp(path + strlen(websDefaultDir), l->url, 
					strlen(l->url)) == 0) {
				cnode->flags |= WHITELIST_SSL;
			}
		}
#endif /* WEBS_SSL_SUPPORT */
		if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
			websMakePath(tmppath, path, findData.cFileName, 1);
			if (level < MAX_URL_DEPTH) {
				if (websBuildWhitelistRecursive(tmppath, cnode, level + 1) < 0){
					cnode->flags |= WHITELIST_BLOCKED;
				}
			}
		}
nextFile:
		if (FindNextFile(fh, &findData) == 0) {
			if (GetLastError() != ERROR_NO_MORE_FILES) {
				rc = -1;
			}
			break;
		}
	}
	FindClose(fh);
	return rc;
}
Exemplo n.º 12
0
/*
 *	Process a form request. Returns 1 always to indicate it handled the URL
 */
int websCgiHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg, 
		char_t *url, char_t *path, char_t* query)
{
	cgiRec		*cgip;
	sym_t		*s;
	char_t		cgiBuf[FNAMESIZE], *stdIn, *stdOut, cwd[FNAMESIZE];
	char_t		*cp, *cgiName, *cgiPath, **argp, **envp, **ep;
	int			n, envpsize, argpsize, pHandle, cid;
	a_assert(websValid(wp));
	a_assert(url && *url);
	a_assert(path && *path == '/');
	websStats.cgiHits++;
/*
 *	Extract the form name and then build the full path name.  The form
 *	name will follow the first '/' in path.
 */
	gstrncpy(cgiBuf, path, TSZ(cgiBuf));
	if ((cgiName = gstrchr(&cgiBuf[1], '/')) == NULL) {
		websError(wp, 200, T("Missing CGI name"));
		return 1;
	}
	cgiName++;
	if ((cp = gstrchr(cgiName, '/')) != NULL) {
		*cp = '\0';
	}
	fmtAlloc(&cgiPath, FNAMESIZE, T("%s/%s/%s"), websGetDefaultDir(),
		CGI_BIN, cgiName);
#ifndef VXWORKS
/*
 *	See if the file exists and is executable.  If not error out.
 *	Don't do this step for VxWorks, since the module may already
 *	be part of the OS image, rather than in the file system.
 */
	{
		gstat_t		sbuf;
		if (gstat(cgiPath, &sbuf) != 0 || (sbuf.st_mode & S_IFREG) == 0) {
			websError(wp, 200, T("CGI process file does not exist"));
			bfree(B_L, cgiPath);
			return 1;
		}
#if (defined (WIN) || defined (CE))
		if (gstrstr(cgiPath, T(".exe")) == NULL &&
			gstrstr(cgiPath, T(".bat")) == NULL) {
#elif (defined (NW))
			if (gstrstr(cgiPath, T(".nlm")) == NULL) {
#else
		if (gaccess(cgiPath, X_OK) != 0) {
#endif /* WIN || CE */
			websError(wp, 200, T("CGI process file is not executable"));
			bfree(B_L, cgiPath);
			return 1;
		}
	}
#endif /* ! VXWORKS */

         
/*
 *	Get the CWD for resetting after launching the child process CGI
 */
	ggetcwd(cwd, FNAMESIZE);
/*
 *	Retrieve the directory of the child process CGI
 */
	if ((cp = gstrrchr(cgiPath, '/')) != NULL) {
		*cp = '\0';
		gchdir(cgiPath);
		*cp = '/';
	}

/*
 *	Build command line arguments.  Only used if there is no non-encoded
 *	= character.  This is indicative of a ISINDEX query.  POST separators
 *	are & and others are +.  argp will point to a balloc'd array of 
 *	pointers.  Each pointer will point to substring within the
 *	query string.  This array of string pointers is how the spawn or 
 *	exec routines expect command line arguments to be passed.  Since 
 *	we don't know ahead of time how many individual items there are in
 *	the query string, the for loop includes logic to grow the array 
 *	size via brealloc.
 */

	argpsize = 10;
	argp = balloc(B_L, argpsize * sizeof(char_t *));
	*argp = cgiPath;

	n = 1;
	if (gstrchr(query, '=') == NULL) {

		websDecodeUrl(query, query, gstrlen(query));
		for (cp = gstrtok(query, T(" ")); cp != NULL; ) {
			*(argp+n) = cp;
			n++;

			if (n >= argpsize) {
				argpsize *= 2;
				argp = brealloc(B_L, argp, argpsize * sizeof(char_t *));

			}
			cp = gstrtok(NULL, T(" "));

		}
	}
	*(argp+n) = NULL;

/*
 *	Add all CGI variables to the environment strings to be passed
 *	to the spawned CGI process.  This includes a few we don't 
 *	already have in the symbol table, plus all those that are in
 *	the cgiVars symbol table.  envp will point to a balloc'd array of 
 *	pointers.  Each pointer will point to a balloc'd string containing
 *	the keyword value pair in the form keyword=value.  Since we don't
 *	know ahead of time how many environment strings there will be the
 *	for loop includes logic to grow the array size via brealloc.
 */

	envpsize = WEBS_SYM_INIT;
	envp = balloc(B_L, envpsize * sizeof(char_t *));
	n = 0;
	fmtAlloc(envp+n, FNAMESIZE, T("%s=%s"),T("PATH_TRANSLATED"), cgiPath);
	n++;
	fmtAlloc(envp+n, FNAMESIZE, T("%s=%s/%s"),T("SCRIPT_NAME"),
		CGI_BIN, cgiName);
	n++;
	fmtAlloc(envp+n, FNAMESIZE, T("%s=%s"),T("REMOTE_USER"), wp->userName);
	n++;
	fmtAlloc(envp+n, FNAMESIZE, T("%s=%s"),T("AUTH_TYPE"), wp->authType);

	n++;
	for (s = symFirst(wp->cgiVars); s != NULL; s = symNext(wp->cgiVars)) {

		if (s->content.valid && s->content.type == string &&
			gstrcmp(s->name.value.string, T("REMOTE_HOST")) != 0 &&
			gstrcmp(s->name.value.string, T("HTTP_AUTHORIZATION")) != 0) {
			fmtAlloc(envp+n, FNAMESIZE, T("%s=%s"), s->name.value.string,
				s->content.value.string);

			n++;
			if (n >= envpsize) {

				envpsize *= 2;
				envp = brealloc(B_L, envp, envpsize * sizeof(char_t *));
			}
		}
	}


	if (wp->flags & WEBS_CGI_UPLOAD){
		// set filename into enviornment variables 
		fmtAlloc(envp+n, FNAMESIZE, T("%s=%s"), T("UPLOAD_FILENAME"), wp->cgiStdin);
		n++;
	}


	*(envp+n) = NULL;
/*
 *	Create temporary file name(s) for the child's stdin and stdout.
 *	For POST data the stdin temp file (and name) should already exist.
 */

	if (wp->cgiStdin == NULL) {
		wp->cgiStdin = websGetCgiCommName(wp);
	} 
	stdIn = wp->cgiStdin;
	stdOut = websGetCgiCommName(wp);

/*
 *	Now launch the process.  If not successful, do the cleanup of resources.
 *	If successful, the cleanup will be done after the process completes.
 */
	if ((pHandle = websLaunchCgiProc(cgiPath, argp, envp, stdIn, stdOut)) 
		== -1) {
		websError(wp, 200, T("failed to spawn CGI task"));
		for (ep = envp; *ep != NULL; ep++) {
			bfreeSafe(B_L, *ep);
		}
		bfreeSafe(B_L, cgiPath);
		bfreeSafe(B_L, argp);
		bfreeSafe(B_L, envp);
		bfreeSafe(B_L, stdOut);
	} else {
/*
 *		If the spawn was successful, put this wp on a queue to be
 *		checked for completion.
 */
		cid = hAllocEntry((void***) &cgiList, &cgiMax, sizeof(cgiRec));
		cgip = cgiList[cid];
		cgip->handle = pHandle;
		cgip->stdIn = stdIn;
		cgip->stdOut = stdOut;
		cgip->cgiPath = cgiPath;
		cgip->argp = argp;
		cgip->envp = envp;
		cgip->wp = wp;
		cgip->fplacemark = 0;
		websTimeoutCancel(wp);
	}
/*
 *	Restore the current working directory after spawning child CGI
 */
 	gchdir(cwd);
	return 1;
}



/******************************************************************************/
/*
 *	Any entry in the cgiList need to be checked to see if it has
 */
void websCgiGatherOutput (cgiRec *cgip)
{
	gstat_t	sbuf;
	char_t	cgiBuf[FNAMESIZE];
	if ((gstat(cgip->stdOut, &sbuf) == 0) && 
		(sbuf.st_size > cgip->fplacemark)) {
		int fdout;
		fdout = gopen(cgip->stdOut, O_RDONLY | O_BINARY, 0444 );
/*
 *		Check to see if any data is available in the
 *		output file and send its contents to the socket.
 */
		if (fdout >= 0) {
			webs_t	wp = cgip->wp;
			int		nRead;
/*
 *			Write the HTTP header on our first pass
 */
			if (cgip->fplacemark == 0) {
				websWrite(wp, T("HTTP/1.0 200 OK\r\n"));
			}
			glseek(fdout, cgip->fplacemark, SEEK_SET);
			while ((nRead = gread(fdout, cgiBuf, FNAMESIZE)) > 0) {
				websWriteBlock(wp, cgiBuf, nRead);
				cgip->fplacemark += nRead;
			}
			gclose(fdout);
		}
	}
}


/******************************************************************************/
/*
 *	Any entry in the cgiList need to be checked to see if it has
 *	completed, and if so, process its output and clean up.
 */
void websCgiCleanup()
{
	cgiRec	*cgip;
	webs_t	wp;
	char_t	**ep;
	int		cid, nTries;
	for (cid = 0; cid < cgiMax; cid++) {
		if ((cgip = cgiList[cid]) != NULL) {
			int exit_status;
			wp = cgip->wp;
			websCgiGatherOutput (cgip);
			if ( websCheckCgiProc(cgip->handle, &exit_status) == 0) {
/*
 *				We get here if the CGI process has terminated.  Clean up.
 */
				nTries = 0;
/*				
 *				Make sure we didn't miss something during a task switch.
 *				Maximum wait is 100 times 10 msecs (1 second).
 */
				while ((cgip->fplacemark == 0) && (nTries < 100)) {
					websCgiGatherOutput(cgip);
/*					
 *					There are some cases when we detect app exit 
 *					before the file is ready. 
 */
					if (cgip->fplacemark == 0) {
#ifdef WIN
						Sleep(10);
#endif /* WIN*/
					}
					nTries++;
				}
				if (cgip->fplacemark == 0) {
					websError(wp, 200, T("CGI generated no output"));
				} else {
					websDone(wp, 200);
				}
/*
 *				Remove the temporary re-direction files
 */
				gunlink(cgip->stdIn);
				gunlink(cgip->stdOut);
/*
 *				Free all the memory buffers pointed to by cgip.
 *				The stdin file name (wp->cgiStdin) gets freed as
 *				part of websFree().
 */
				cgiMax = hFree((void***) &cgiList, cid);
				for (ep = cgip->envp; ep != NULL && *ep != NULL; ep++) {
					bfreeSafe(B_L, *ep);
				}
				bfreeSafe(B_L, cgip->cgiPath);
				bfreeSafe(B_L, cgip->argp);
				bfreeSafe(B_L, cgip->envp);
				bfreeSafe(B_L, cgip->stdOut);
				bfreeSafe(B_L, cgip);
#if 0 //DAVIDM - we do not want this, netflash does it for us
				if(wp->has_firmware_upload_clean){
					if (WIFEXITED(exit_status) && WEXITSTATUS(exit_status) != 0)
						return;
					sync();
					doSystem("sleep 3 && reboot &");
				}
#endif
			}
		}
	}
}
Exemplo n.º 13
0
int dbLoad(int did, char_t *filename, int flags)
{
    gstat_t		sbuf;
    char_t		*buf, *keyword, *value, *path, *ptr;
    char_t		*tablename;
    int			fd, tid, row;
    dbTable_t	*pTable;

    a_assert(did >= 0);

    fmtAlloc(&path, FNAMESIZE, T("%s/%s"), basicGetProductDir(), filename);
    trace(4, T("DB: About to read data file <%s>\n"), path);

    if (gstat(path, &sbuf) < 0) {
        trace(3, T("DB: Failed to stat persistent data file.\n"));
        bfree(B_L, path);
        return -1;
    }

    fd = gopen(path, O_RDONLY | O_BINARY, 0666);
    bfree(B_L, path);

    if (fd < 0) {
        trace(3, T("DB: No persistent data file present.\n"));
        return -1;
    }

    if (sbuf.st_size <= 0) {
        trace(3, T("DB: Persistent data file is empty.\n"));
        gclose(fd);
        return -1;
    }
    /*
     *	Read entire file into temporary buffer
     */
    buf = balloc(B_L, sbuf.st_size + 1);
#ifdef CE
    if (readAscToUni(fd, &buf, sbuf.st_size) != (int)sbuf.st_size) {
#else
    if (gread(fd, buf, sbuf.st_size) != (int)sbuf.st_size) {
#endif
        trace(3, T("DB: Persistent data read failed.\n"));
        bfree(B_L, buf);
        gclose(fd);
        return -1;
    }

    gclose(fd);
    *(buf + sbuf.st_size) = '\0';

    row = -1;
    tid = -1;
    pTable = NULL;
    ptr = gstrtok(buf, T("\n"));
    tablename = NULL;

    do {
        if (crack(ptr, &keyword, &value) < 0) {
            trace(5, T("DB: Failed to crack line %s\n"), ptr);
            continue;
        }

        a_assert(keyword && *keyword);

        if (gstrcmp(keyword, KEYWORD_TABLE) == 0) {
            /*
             *			Table name found, check to see if it's registered
             */
            if (tablename) {
                bfree(B_L, tablename);
            }

            tablename = bstrdup(B_L, value);
            tid = dbGetTableId(did, tablename);

            if (tid >= 0) {
                pTable = dbListTables[tid];
            } else {
                pTable = NULL;
            }

        } else if (gstrcmp(keyword, KEYWORD_ROW) == 0) {
            /*
             *			Row/Record indicator found, add a new row to table
             */
            if (tid >= 0) {
                int nRows = dbGetTableNrow(did, tablename);

                if (dbSetTableNrow(did, tablename, nRows + 1) == 0) {
                    row = nRows;
                }
            }

        } else if (row != -1) {
            /*
             *			some other data found, assume it's a COLUMN=value
             */
            int nColumn = GetColumnIndex(tid, keyword);

            if ((nColumn >= 0) && (pTable != NULL)) {
                int nColumnType = pTable->columnTypes[nColumn];
                if (nColumnType == T_STRING) {
                    dbWriteStr(did, tablename, keyword, row, value);
                } else {
                    dbWriteInt(did, tablename, keyword, row, gstrtoi(value));
                }
            }
        }
    } while ((ptr = gstrtok(NULL, T("\n"))) != NULL);

    if (tablename) {
        bfree(B_L, tablename);
    }

    bfree(B_L, buf);

    return 0;
}

/******************************************************************************/
/*
 *	Return a table id given the table name
 */

int dbGetTableId(int did, char_t *tablename)
{
    int			tid;
    dbTable_t	*pTable;

    a_assert(tablename);

    for (tid = 0; (tid < dbMaxTables); tid++) {
        if ((pTable = dbListTables[tid]) != NULL) {
            if (gstrcmp(tablename, pTable->name) == 0) {
                return tid;
            }
        }
    }

    return -1;
}
Exemplo n.º 14
0
int dbSave(int did, char_t *filename, int flags)
{
    int			row, column, nColumns, nRows, fd, rc;
    int			*colTypes, *pRow, nRet, tid;
    char_t		*path, *tmpFile, *tmpNum;
    char_t		**colNames;
    dbTable_t	*pTable;

    trace(5, T("DB: About to save database to file\n"));

    a_assert(dbMaxTables > 0);

    /*
     *	First write to a temporary file, then switch around later.
     */
    fmtAlloc(&tmpFile, FNAMESIZE, T("%s/data.tmp"), basicGetProductDir());
    if ((fd = gopen(tmpFile,
                    O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, 0666)) < 0) {
        trace(1, T("WARNING: Failed to open file %s\n"), tmpFile);
        bfree(B_L, tmpFile);
        return -1;
    }

    nRet = 0;

    for (tid = 0; (tid < dbMaxTables) && (nRet != -1); tid++) {
        pTable = dbListTables[tid];

        if (pTable) {
            /*
             *			Print the TABLE=tableName directive to the file
             */
            rc = dbWriteKeyValue(fd, KEYWORD_TABLE, pTable->name);

            nColumns = pTable->nColumns;
            nRows = pTable->nRows;

            for (row = 0; (row < nRows) && (nRet == 0); row++) {
                pRow = pTable->rows[row];
                /*
                 *				if row is NULL, the row has been deleted, so don't
                 *				write it out.
                 */
                if ((pRow == NULL) || (pRow[0] == '\0') ||
                        (*(char_t *)(pRow[0]) == '\0')) {
                    continue;
                }
                /*
                 *				Print the ROW=rowNumber directive to the file
                 */
                fmtAlloc(&tmpNum, 20, T("%d"), row);
                rc = dbWriteKeyValue(fd, KEYWORD_ROW, tmpNum);
                bfreeSafe(B_L, tmpNum);

                colNames = pTable->columnNames;
                colTypes = pTable->columnTypes;
                /*
                 *				Print the key-value pairs (COLUMN=value) for data cells
                 */
                for (column = 0; (column < nColumns) && (rc >= 0);
                        column++, colNames++, colTypes++) {
                    if (*colTypes == T_STRING) {
                        rc = dbWriteKeyValue(fd, *colNames,
                                             (char_t *)(pRow[column]));
                    } else {
                        fmtAlloc(&tmpNum, 20, T("%d"), pRow[column]);
                        rc = dbWriteKeyValue(fd, *colNames, tmpNum);
                        bfreeSafe(B_L, tmpNum);
                    }
                }

                if (rc < 0) {
                    trace(1, T("WARNING: Failed to write to file %s\n"),
                          tmpFile);
                    nRet = -1;
                }
            }
        }
    }

    gclose(fd);

    /*
     *	Replace the existing file with the temporary file, if no errors
     */
    if (nRet == 0) {
        fmtAlloc(&path, FNAMESIZE, T("%s/%s"), basicGetProductDir(), filename);

        gunlink(path);
        if (grename(tmpFile, path) != 0) {
            trace(1, T("WARNING: Failed to rename %s to %s\n"), tmpFile, path);
            nRet = -1;
        }

        bfree(B_L, path);
    }

    bfree(B_L, tmpFile);

    return nRet;
}
Exemplo n.º 15
0
int websLaunchCgiProc(char_t *cgiPath, char_t **argp, char_t **envp,
					  char_t *stdIn, char_t *stdOut)
{
	SYM_TYPE	ptype;
	char_t		*p, *basename, *pEntry, *pname, *entryAddr, **pp;
	int			priority, rc, fd;

/*
 *	Determine the basename, which is without path or the extension.
 */
	if ((int)(p = gstrrchr(cgiPath, '/') + 1) == 1) {
		p = cgiPath;
	}
	basename = bstrdup(B_L, p);
	if ((p = gstrrchr(basename, '.')) != NULL) {
		*p = '\0';
	}

/*
 *	Unload the module, if it is already loaded.  Get the current task
 *	priority.
 */
	unld(cgiPath, 0);
	taskPriorityGet(taskIdSelf(), &priority);
	rc = fd = -1;

/*
 *	Set the entry point symbol name as described above.  Look for an already
 *	loaded entry point; if it exists, spawn the task accordingly.
 */
	for (pp = envp, pEntry = NULL; pp != NULL && *pp != NULL; pp++) {
		if (gstrncmp(*pp, T("cgientry="), 9) == 0) {
			pEntry = bstrdup(B_L, *pp + 9);
			break;
		}
	}
	if (pEntry == NULL) {
		fmtAlloc(&pEntry, LF_PATHSIZE, T("%s_%s"), basename, T("cgientry"));
	}

	entryAddr = 0;
	if (symFindByName(sysSymTbl, pEntry, &entryAddr, &ptype) == -1) {
		fmtAlloc(&pname, VALUE_MAX_STRING, T("_%s"), pEntry);
		symFindByName(sysSymTbl, pname, &entryAddr, &ptype);
		bfreeSafe(B_L, pname);
	}
	if (entryAddr != 0) {
		rc = taskSpawn(pEntry, priority, 0, 20000, (void *)vxWebsCgiEntry,
			(int)entryAddr, (int)argp, (int)envp, (int)stdIn, (int)stdOut,
			0, 0, 0, 0, 0);
		goto DONE;
	}

/*
 *	Try to load the module.
 */
	if ((fd = gopen(cgiPath, O_RDONLY | O_BINARY, 0666)) < 0 ||
		loadModule(fd, LOAD_GLOBAL_SYMBOLS) == NULL) {
		goto DONE;
	}
	if ((symFindByName(sysSymTbl, pEntry, &entryAddr, &ptype)) == -1) {
		fmtAlloc(&pname, VALUE_MAX_STRING, T("_%s"), pEntry);
		symFindByName(sysSymTbl, pname, &entryAddr, &ptype);
		bfreeSafe(B_L, pname);
	}
	if (entryAddr != 0) {
		rc = taskSpawn(pEntry, priority, 0, 20000, (void *)vxWebsCgiEntry,
			(int)entryAddr, (int)argp, (int)envp, (int)stdIn, (int)stdOut,
			0, 0, 0, 0, 0);
	}

DONE:
	if (fd != -1) {
		gclose(fd);
	}
	bfree(B_L, basename);
	bfree(B_L, pEntry);
	return rc;
}