- backport symlink patch in hard version to 1.4.11

git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-1.4.11-ssl-fixes@1281 152afb58-edef-0310-8abb-c4023f1b3aa9
This commit is contained in:
Marcus Rückert 2006-09-07 11:00:02 +00:00
parent d5c9873255
commit 657a024d53
9 changed files with 144 additions and 15 deletions

View File

@ -440,7 +440,7 @@ case $host_os in
esac
AC_CHECK_FUNCS([dup2 getcwd inet_ntoa inet_ntop memset mmap munmap strchr \
strdup strerror strstr strtol sendfile getopt socket \
strdup strerror strstr strtol sendfile getopt socket lstat \
gethostbyname poll sigtimedwait epoll_ctl getrlimit chroot \
getuid select signal pathconf madvise posix_fadvise posix_madvise \
writev sigaction sendfile64 send_file kqueue port_create localtime_r])

View File

@ -86,7 +86,8 @@ typedef enum { T_CONFIG_UNSET,
T_CONFIG_BOOLEAN,
T_CONFIG_ARRAY,
T_CONFIG_LOCAL,
T_CONFIG_DEPRECATED
T_CONFIG_DEPRECATED,
T_CONFIG_UNSUPPORTED
} config_values_type_t;
typedef enum { T_CONFIG_SCOPE_UNSET,
@ -206,6 +207,10 @@ typedef struct {
time_t stat_ts;
#ifdef HAVE_LSTAT
char is_symlink;
#endif
#ifdef HAVE_FAM_H
int dir_version;
int dir_ndx;
@ -572,7 +577,8 @@ typedef struct server {
server_config srvconf;
int config_deprecated;
short int config_deprecated;
short int config_unsupported;
connections *conns;
connections *joblist;

View File

@ -118,6 +118,12 @@ int config_insert_values_internal(server *srv, array *ca, const config_values_t
break;
case T_CONFIG_LOCAL:
case T_CONFIG_UNSET:
break;
case T_CONFIG_UNSUPPORTED:
log_error_write(srv, __FILE__, __LINE__, "ssss", "ERROR: found unsupported key:", cv[i].key, "-", (char *)(cv[i].destination));
srv->config_unsupported = 1;
break;
case T_CONFIG_DEPRECATED:
log_error_write(srv, __FILE__, __LINE__, "ssss", "ERROR: found deprecated key:", cv[i].key, "-", (char *)(cv[i].destination));

View File

@ -54,7 +54,14 @@ static int config_insert(server *srv) {
{ "server.max-write-idle", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 21 */
{ "server.error-handler-404", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 22 */
{ "server.max-fds", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER }, /* 23 */
#ifdef HAVE_LSTAT
{ "server.follow-symlink", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 24 */
#else
{ "server.follow-symlink",
"Your system lacks lstat(). We can not differ symlinks from files."
"Please remove server.follow-symlinks from your config.",
T_CONFIG_UNSUPPORTED, T_CONFIG_SCOPE_UNSET }, /* 24 */
#endif
{ "server.kbytes-per-second", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 25 */
{ "connection.kbytes-per-second", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 26 */
{ "mimetype.use-xattr", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 27 */
@ -150,7 +157,9 @@ static int config_insert(server *srv) {
s->is_ssl = 0;
s->ssl_use_sslv2 = 1;
s->use_ipv6 = 0;
#ifdef HAVE_LSTAT
s->follow_symlink = 1;
#endif
s->kbytes_per_second = 0;
s->allow_http11 = 1;
s->range_requests = 1;
@ -175,7 +184,9 @@ static int config_insert(server *srv) {
cv[20].destination = &(s->max_read_idle);
cv[21].destination = &(s->max_write_idle);
cv[22].destination = s->error_handler;
#ifdef HAVE_LSTAT
cv[24].destination = &(s->follow_symlink);
#endif
/* 23 -> max-fds */
cv[25].destination = &(s->global_kbytes_per_second);
cv[26].destination = &(s->kbytes_per_second);
@ -238,7 +249,9 @@ int config_setup_connection(server *srv, connection *con) {
PATCH(use_xattr);
PATCH(error_handler);
PATCH(errorfile_prefix);
#ifdef HAVE_LSTAT
PATCH(follow_symlink);
#endif
PATCH(server_tag);
PATCH(kbytes_per_second);
PATCH(global_kbytes_per_second);
@ -314,8 +327,10 @@ int config_patch_connection(server *srv, connection *con, comp_key_t comp) {
PATCH(ssl_cipher_list);
} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.engine"))) {
PATCH(is_ssl);
#ifdef HAVE_LSTAT
} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.follow-symlink"))) {
PATCH(follow_symlink);
#endif
} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.name"))) {
buffer_copy_string_buffer(con->server_name, s->server_name);
} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.tag"))) {

View File

@ -397,6 +397,19 @@ URIHANDLER_FUNC(mod_staticfile_subrequest) {
}
/* we only handline regular files */
#ifdef HAVE_LSTAT
if ((sce->is_symlink == 1) && !con->conf.follow_symlink) {
con->http_status = 403;
if (con->conf.log_request_handling) {
log_error_write(srv, __FILE__, __LINE__, "s", "-- access denied due symlink restriction");
log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
}
buffer_reset(con->physical.path);
return HANDLER_FINISHED;
}
#endif
if (!S_ISREG(sce->st.st_mode)) {
con->http_status = 404;

View File

@ -451,7 +451,7 @@ handler_t http_response_prepare(server *srv, connection *con) {
log_error_write(srv, __FILE__, __LINE__, "s", "-- handling physical path");
log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
}
if (HANDLER_ERROR != stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
/* file exists */
@ -459,7 +459,19 @@ handler_t http_response_prepare(server *srv, connection *con) {
log_error_write(srv, __FILE__, __LINE__, "s", "-- file found");
log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
}
#ifdef HAVE_LSTAT
if ((sce->is_symlink != 0) && !con->conf.follow_symlink) {
con->http_status = 403;
if (con->conf.log_request_handling) {
log_error_write(srv, __FILE__, __LINE__, "s", "-- access denied due symlink restriction");
log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
}
buffer_reset(con->physical.path);
return HANDLER_FINISHED;
};
#endif
if (S_ISDIR(sce->st.st_mode)) {
if (con->physical.path->ptr[con->physical.path->used - 2] != '/') {
/* redirect to .../ */
@ -468,7 +480,11 @@ handler_t http_response_prepare(server *srv, connection *con) {
return HANDLER_FINISHED;
}
#ifdef HAVE_LSTAT
} else if (!S_ISREG(sce->st.st_mode) && !sce->is_symlink) {
#else
} else if (!S_ISREG(sce->st.st_mode)) {
#endif
/* any special handling of non-reg files ?*/

View File

@ -861,22 +861,29 @@ int main (int argc, char **argv) {
}
}
}
if (srv->config_unsupported) {
log_error_write(srv, __FILE__, __LINE__, "s",
"Configuration contains unsupported keys. Going down.");
}
if (srv->config_deprecated) {
log_error_write(srv, __FILE__, __LINE__, "s",
"Configuration contains deprecated keys. Going down.");
}
if (srv->config_unsupported || srv->config_deprecated) {
plugins_free(srv);
network_close(srv);
server_free(srv);
return -1;
}
if (-1 == log_error_open(srv)) {
log_error_write(srv, __FILE__, __LINE__, "s",
"opening errorlog failed, dying");
plugins_free(srv);
network_close(srv);
server_free(srv);

View File

@ -39,7 +39,7 @@
#define lstat stat
#endif
#if 0
#if 1
/* enables debug code for testing if all nodes in the stat-cache as accessable */
#define DEBUG_STAT_CACHE
#endif
@ -328,6 +328,20 @@ static int buffer_copy_dirname(buffer *dst, buffer *file) {
}
#endif
#ifdef HAVE_LSTAT
static int stat_cache_lstat(server *srv, char *dname, struct stat *lst) {
if (lstat(dname, lst) == 0) {
return S_ISLNK(lst->st_mode) ? 0 : 1;
}
else {
log_error_write(srv, __FILE__, __LINE__, "sss",
"lstat failed for:",
dname, strerror(errno));
};
return -1;
}
#endif
/***
*
*
@ -450,10 +464,9 @@ handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_
/*
* *lol*
* - open() + fstat() on a named-pipe results in a (intended) hang.
* - stat() if regualar file + open() to see if we can read from it is better
* - stat() if regular file + open() to see if we can read from it is better
*
* */
if (-1 == stat(name->ptr, &st)) {
return HANDLER_ERROR;
}
@ -509,11 +522,52 @@ handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_
* and keeping the file open for the rest of the time. But this can
* only be done at network level.
*
+ * per default it is not a symlink
* */
if (S_ISLNK(st.st_mode) && !con->conf.follow_symlink) {
return HANDLER_ERROR;
#ifdef HAVE_LSTAT
sce->is_symlink = 0;
struct stat lst;
if (stat_cache_lstat(srv, name->ptr, &lst) == 0) {
#ifdef DEBUG_STAT_CACHE
log_error_write(srv, __FILE__, __LINE__, "sb",
"found symlink", name);
#endif
sce->is_symlink = 1;
}
/*
* we assume "/" can not be symlink, so
* skip the symlink stuff if our path is /
**/
else if ((name->used > 2)) {
char *dname, *s_cur;
dname = strndup(name->ptr, name->used);
while ((s_cur = strrchr(dname,'/'))) {
*s_cur = '\0';
if (dname == s_cur) {
#ifdef DEBUG_STAT_CACHE
log_error_write(srv, __FILE__, __LINE__, "s", "reached /");
#endif
break;
}
#ifdef DEBUG_STAT_CACHE
log_error_write(srv, __FILE__, __LINE__, "sss",
"checking if", dname, "is a symlink");
#endif
if (stat_cache_lstat(srv, dname, &lst) == 0) {
sce->is_symlink = 1;
#ifdef DEBUG_STAT_CACHE
log_error_write(srv, __FILE__, __LINE__, "ss",
"found symlink", dname);
#endif
break;
};
};
free(dname);
};
#endif
if (S_ISREG(st.st_mode)) {
/* determine mimetype */
buffer_reset(sce->content_type);

View File

@ -147,6 +147,18 @@ $HTTP["host"] == "zzz.example.org" {
server.name = "zzz.example.org"
}
$HTTP["host"] == "symlink.example.org" {
server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
server.name = "symlink.example.org"
server.follow-symlink = "enable"
}
$HTTP["host"] == "nosymlink.example.org" {
server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
server.name = "symlink.example.org"
server.follow-symlink = "disable"
}
$HTTP["host"] == "no-simple.example.org" {
server.document-root = "@SRCDIR@/tmp/lighttpd/servers/123.example.org/pages/"
server.name = "zzz.example.org"