- 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:
parent
d5c9873255
commit
657a024d53
|
@ -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])
|
||||
|
|
10
src/base.h
10
src/base.h
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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"))) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 ?*/
|
||||
|
||||
|
||||
|
|
17
src/server.c
17
src/server.c
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue