예제 #1
0
static ret_t
remove_old_socket (const char *path)
{
	int         re;
	struct stat info;

	/* It might not exist
	 */
	re = cherokee_stat (path, &info);
	if (re != 0) {
		return ret_ok;
	}

	/* If exist, it must be a socket
	 */
	if (! S_ISSOCK(info.st_mode)) {
		PRINT_MSG ("ERROR: Something happens; '%s' isn't a socket.\n", path);
		return ret_error;
	}

	/* Remove it
	 */
	re = unlink (path);
	if (re != 0) {
		PRINT_MSG ("ERROR: Couldn't remove unix socket '%s'.\n", path);
		return ret_error;
	}

	return ret_ok;
}
예제 #2
0
파일: buffer.c 프로젝트: Daniel15/webserver
ret_t
cherokee_buffer_read_file (cherokee_buffer_t *buf, char *filename)
{
	int r, f;
	ret_t ret;
	struct stat info;

	/* Stat() the file
	 */
	r = cherokee_stat (filename, &info);
	if (r != 0)
		return ret_error;

	/* Is a regular file?
	 */
	if (S_ISREG(info.st_mode) == 0)
		return ret_error;

	/* Maybe get memory
	 */
	ret = cherokee_buffer_ensure_size (buf, buf->len + info.st_size + 1);
	if (unlikely (ret != ret_ok))
		return ret;

	/* Open the file
	 */
	f = cherokee_open (filename, O_RDONLY | O_BINARY, 0);
	if (f < 0) {
		LOG_ERRNO(errno, cherokee_err_error, CHEROKEE_ERROR_BUFFER_OPEN_FILE, filename);
		return ret_error;
	}

	cherokee_fd_set_closexec (f);

	/* Read the content
	 */
	r = read (f, buf->buf + buf->len, info.st_size);
	if (r < 0) {
		buf->buf[buf->len] = '\0';

		cherokee_fd_close(f);
		return ret_error;
	}

	/* Close it and exit
	 */
	cherokee_fd_close(f);

	buf->len += r;
	buf->buf[buf->len] = '\0';

	return ret_ok;
}
예제 #3
0
static ret_t
cherokee_bind_local (cherokee_socket_t *sock, cherokee_buffer_t *listen_to)
{
#ifdef HAVE_SOCKADDR_UN
	int         re;
	struct stat buf;

	/* Sanity check
	 */
	if ((listen_to->len <= 0) ||
	    (listen_to->len >= sizeof(SOCKET_SUN_PATH(sock))))
		return ret_error;

	/* Remove the socket if it already exists
	 */
	re = cherokee_stat (listen_to->buf, &buf);
	if (re == 0) {
		if (! S_ISSOCK(buf.st_mode)) {
			LOG_CRITICAL (CHEROKEE_ERROR_SOCKET_NO_SOCKET, listen_to->buf);
			return ret_error;
		}

		re = cherokee_unlink (listen_to->buf);
		if (re != 0) {
			LOG_ERRNO (errno, cherokee_err_error,
				   CHEROKEE_ERROR_SOCKET_REMOVE, listen_to->buf);
			return ret_error;
		}
	}

	/* Create the socket
	 */
	memcpy (SOCKET_SUN_PATH(sock), listen_to->buf, listen_to->len + 1);
	sock->client_addr_len = sizeof(SOCKET_ADDR_UNIX(sock)->sun_family) + listen_to->len;

	re = bind (SOCKET_FD(sock),
	           (const struct sockaddr *)SOCKET_ADDR_UNIX(sock),
	           sock->client_addr_len);
	if (re != 0) return ret_error;

	return ret_ok;
#else
	return ret_no_sys;
#endif
}
예제 #4
0
static ret_t
init (cherokee_handler_ssi_t *hdl,
          cherokee_buffer_t      *local_path)
{
	int                    re;
	ret_t                  ret;
	cherokee_connection_t *conn = HANDLER_CONN(hdl);

	/* Stat the file
	 */
	re = cherokee_stat (local_path->buf, &hdl->cache_info);
	if (re < 0) {
		switch (errno) {
		case ENOENT:
			conn->error_code = http_not_found;
			break;
		case EACCES:
			conn->error_code = http_access_denied;
			break;
		default:
			conn->error_code = http_internal_error;
		}
		return ret_error;
	}

	/* Read the file
	 */
	ret = cherokee_buffer_read_file (&hdl->source, local_path->buf);
	if (ret != ret_ok)
		return ret_error;

	/* Render
	 */
	ret = parse (hdl, &hdl->source, &hdl->render);
	if (ret != ret_ok)
		return ret;

	return ret_ok;
}
예제 #5
0
static ret_t
parse (cherokee_handler_ssi_t *hdl,
       cherokee_buffer_t      *in,
       cherokee_buffer_t      *out)
{
	ret_t              ret;
	char              *p, *q;
	char              *begin;
	int                re;
	cuint_t            len;
	operations_t       op;
	path_type_t        path;
	struct stat        info;
	cherokee_boolean_t ignore;
	cherokee_buffer_t  key     = CHEROKEE_BUF_INIT;
	cherokee_buffer_t  val     = CHEROKEE_BUF_INIT;
	cherokee_buffer_t  pair    = CHEROKEE_BUF_INIT;
	cherokee_buffer_t  fpath   = CHEROKEE_BUF_INIT;

	q = in->buf;

	while (true) {
		begin = q;

		/* Check the end
		 */
		if (q >= in->buf + in->len)
			break;

		/* Find next SSI tag
		 */
		p = strstr (q, "<!--#");
		if (p == NULL) {
			cherokee_buffer_add (out, begin, (in->buf + in->len) - begin);
			ret = ret_ok;
			goto out;
		}

		q = strstr (p + 5, "-->");
		if (q == NULL) {
			ret = ret_error;
			goto out;
		}

		len = q - p;
		len -= 5;

		cherokee_buffer_clean (&key);
		cherokee_buffer_add (&key, p+5, len);
		cherokee_buffer_trim (&key);

		q += 3;
		TRACE(ENTRIES, "Found key '%s'\n", key.buf);

		/* Add the previous chunk
		 */
		cherokee_buffer_add (out, begin, p - begin);

		/* Check element
		 */
		op     = op_none;
		ignore = false;

		if (strncmp (key.buf, "include", 7) == 0) {
			op  = op_include;
			len = 7;
		} else if (strncmp (key.buf, "fsize", 5) == 0) {
			op  = op_size;
			len = 5;
		} else if (strncmp (key.buf, "flastmod", 8) == 0) {
			op  = op_lastmod;
			len = 8;
		} else {
			LOG_ERROR (CHEROKEE_ERROR_HANDLER_SSI_PROPERTY, key.buf);
		}

		/* Deeper parsing
		 */
		path = path_none;

		switch (op) {
		case op_size:
		case op_include:
		case op_lastmod:
			/* Read a property key
			 */
			cherokee_buffer_move_to_begin (&key, len);
			cherokee_buffer_trim (&key);

			cherokee_buffer_clean (&pair);
			get_pair (&key, &pair);

			cherokee_buffer_drop_ending (&key, pair.len);
			cherokee_buffer_trim (&key);

			/* Parse the property
			 */
			if (strncmp (pair.buf, "file=", 5) == 0) {
				path = path_file;
				len  = 5;
			} else if (strncmp (pair.buf, "virtual=", 8) == 0) {
				path = path_virtual;
				len  = 8;
			}

			cherokee_buffer_clean (&val);
			get_val (pair.buf + len, &val);

			cherokee_buffer_clean (&fpath);

			switch (path) {
			case path_file:
				cherokee_buffer_add_buffer (&fpath, &hdl->dir);
				cherokee_buffer_add_char   (&fpath, '/');
				cherokee_buffer_add_buffer (&fpath, &val);

				TRACE(ENTRIES, "Path: file '%s'\n", fpath.buf);
				break;
			case path_virtual:
				cherokee_buffer_add_buffer (&fpath, &HANDLER_VSRV(hdl)->root);
				cherokee_buffer_add_char   (&fpath, '/');
				cherokee_buffer_add_buffer (&fpath, &val);

				TRACE(ENTRIES, "Path: virtual '%s'\n", fpath.buf);
				break;
			default:
				ignore = true;
				SHOULDNT_HAPPEN;
			}

			/* Path security check: ensure that the file
			 * to include is inside the document root.
			 */
			if (! cherokee_buffer_is_empty (&fpath)) {
				cherokee_path_short (&fpath);

				if (fpath.len < HANDLER_VSRV(hdl)->root.len) {
					ignore = true;

				}  else {
					re = strncmp (fpath.buf,
					              HANDLER_VSRV(hdl)->root.buf,
					              HANDLER_VSRV(hdl)->root.len);
					if (re != 0) {
						ignore = true;
					}
				}
			}

			/* Perform the operation
			 */
			if (! ignore) {
				switch (op) {
				case op_include: {
					cherokee_buffer_t file_content = CHEROKEE_BUF_INIT;

					ret = cherokee_buffer_read_file (&file_content, fpath.buf);
					if (unlikely (ret != ret_ok)) {
						cherokee_buffer_mrproper (&file_content);
						ret = ret_error;
						goto out;
					}

					TRACE(ENTRIES, "Including file '%s'\n", fpath.buf);

					ret = parse (hdl, &file_content, out);
					if (unlikely (ret != ret_ok)) {
						cherokee_buffer_mrproper (&file_content);
						ret = ret_error;
						goto out;
					}

					cherokee_buffer_mrproper (&file_content);
					break;
				}

				case op_size:
					TRACE(ENTRIES, "Including file size '%s'\n", fpath.buf);
					re = cherokee_stat (fpath.buf, &info);
					if (re >=0) {
						cherokee_buffer_add_ullong10 (out, info.st_size);
					}
					break;

				case op_lastmod:
					TRACE(ENTRIES, "Including file modification date '%s'\n", fpath.buf);
					re = cherokee_stat (fpath.buf, &info);
					if (re >= 0) {
						struct tm *ltime;
						struct tm  ltime_buf;
						char       tmp[50];

						ltime = cherokee_localtime (&info.st_mtime, &ltime_buf);
						if (ltime != NULL) {
							strftime (tmp, sizeof(tmp), "%d-%b-%Y %H:%M", ltime);
							cherokee_buffer_add (out, tmp, strlen(tmp));
						}
					}
					break;
				default:
					SHOULDNT_HAPPEN;
				}
			} /* !ignore */

			break;
		default:
			SHOULDNT_HAPPEN;
		} /* switch(op) */
	} /* while */

	ret = ret_ok;

out:
	cherokee_buffer_mrproper (&key);
	cherokee_buffer_mrproper (&val);
	cherokee_buffer_mrproper (&pair);
	cherokee_buffer_mrproper (&fpath);

	return ret;
}
예제 #6
0
static NORETURN void
manage_child_cgi_process (cherokee_handler_cgi_t *cgi, int pipe_cgi[2], int pipe_server[2])
{
	/* Child process
	 */
	int                          re;
	char                        *script;
	cherokee_connection_t       *conn          = HANDLER_CONN(cgi);
	cherokee_handler_cgi_base_t *cgi_base      = HDL_CGI_BASE(cgi);
	char                        *absolute_path = cgi_base->executable.buf;
	char                        *argv[2]       = { NULL, NULL };

#ifdef TRACE_ENABLED
	TRACE(ENTRIES, "About to execute: '%s'\n", absolute_path);

	if (! cherokee_buffer_is_empty (&conn->effective_directory))
		TRACE(ENTRIES, "Effective directory: '%s'\n", conn->effective_directory.buf);
	else
		TRACE(ENTRIES, "No Effective directory %s", "\n");
#endif

	/* Close useless sides
	 */
	cherokee_fd_close (pipe_cgi[0]);
	cherokee_fd_close (pipe_server[1]);

	/* Change stdin and out
	 */
	cherokee_fd_close (STDIN_FILENO);
	re = dup2 (pipe_server[0], STDIN_FILENO);
	cherokee_fd_close (pipe_server[0]);

	if (unlikely (re != 0)) {
		printf ("Status: 500" CRLF_CRLF);
		printf ("X-Debug: file=%s line=%d" CRLF_CRLF, __FILE__, __LINE__);
		exit(1);
	}

	cherokee_fd_close (STDOUT_FILENO);
	re |= dup2 (pipe_cgi[1], STDOUT_FILENO);
	cherokee_fd_close (pipe_cgi[1]);

	/* Redirect the stderr
	 */
	if ((CONN_VSRV(conn)->error_writer != NULL) &&
	    (CONN_VSRV(conn)->error_writer->fd != -1))
	{
		cherokee_fd_close (STDERR_FILENO);
		dup2 (CONN_VSRV(conn)->error_writer->fd, STDERR_FILENO);
	}

# if 0
	/* Set unbuffered
	 */
	setvbuf (stdin,  NULL, _IONBF, 0);
	setvbuf (stdout, NULL, _IONBF, 0);
# endif

	/* Enable blocking mode
	 */
	_fd_set_properties (STDIN_FILENO,  0, O_NONBLOCK);
	_fd_set_properties (STDOUT_FILENO, 0, O_NONBLOCK);
	_fd_set_properties (STDERR_FILENO, 0, O_NONBLOCK);

	/* Sets the new environ.
	 */
	add_environment (cgi, conn);

	/* Change the directory
	 */
	if (! cherokee_buffer_is_empty (&conn->effective_directory)) {
		re = chdir (conn->effective_directory.buf);
	} else {
		char *file = strrchr (absolute_path, '/');

		*file = '\0';
		re = chdir (absolute_path);
		*file = '/';
	}

	if (re < 0) {
		printf ("Status: 500" CRLF_CRLF);
		printf ("X-Debug: file=%s line=%d" CRLF_CRLF, __FILE__, __LINE__);
		exit(1);
	}

	/* Build de argv array
	 */
	script  = absolute_path;
	argv[0] = absolute_path;

	/* Change the execution user?
	 */
	if (HANDLER_CGI_PROPS(cgi_base)->change_user) {
		struct stat info;

		re = cherokee_stat (script, &info);
		if (re >= 0) {
			re = setuid (info.st_uid);
			if (re != 0) {
				LOG_ERROR (CHEROKEE_ERROR_HANDLER_CGI_SETID, script, info.st_uid);
			}
		}
	}

	/* Reset the server-wide signal handlers
	 */
	cherokee_reset_signals();

	/* Lets go.. execute it!
	 */
	do {
		re = execve (absolute_path, argv, cgi->envp);
	} while ((re == -1) && (errno == EINTR));

	if (re < 0) {
		int err = errno;
		char buferr[ERROR_MAX_BUFSIZE];

		switch (err) {
		case ENOENT:
			printf ("Status: 404" CRLF_CRLF);
			break;
		default:
			printf ("Status: 500" CRLF_CRLF);
			printf ("X-Debug: file=%s line=%d cmd=%s: %s" CRLF_CRLF,
				__FILE__, __LINE__, absolute_path, strerror(err));
		}

		/* Don't use the logging system (concurrency issues)
		 */
		LOG_ERROR (CHEROKEE_ERROR_HANDLER_CGI_EXECUTE,
			   absolute_path, cherokee_strerror_r(err, buferr, sizeof(buferr)));
		exit(1);
	}

	/* There is no way, it could reach this point.
	 */
	SHOULDNT_HAPPEN;
	exit(2);
}