lighttpd 1.4.x https://www.lighttpd.net/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1291 lines
35 KiB

#include "first.h"
#include "base.h"
#include "fdevent.h"
#include "log.h"
#include "buffer.h"
#include "http_etag.h"
#include "http_header.h"
#include "stat_cache.h"
#include "plugin.h"
#include "response.h"
#include "mod_ssi.h"
#include "sys-socket.h"
#include "sys-time.h"
#include <sys/types.h>
#include <sys/stat.h>
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
fallback to lseek()/read() if mmap() fails (#fixes 2666) fallback to lseek()/read() if mmap() fails (#fixes 2666) e.g. when mmap() is used on lighttpd-controlled temporary files used POST request body (mod_cgi) and PUT file upload (mod_webdav) replace use of stream_open() on potentially untrusted files (protect against SIGBUS if a file is modified while map is read) Note: stream.[ch] may be removed in a future release For now, stream.[ch] will read entire file into memory if mmap fails and so it should only be used on trusted files, e.g. config files. http_auth basic and digest files are typically small and so buffered stdio fopen(), fgets(), fclose() will likely be approximately as fast as mmap. mod_dirlisting header and readme files are typically small and so open(), read(), close() will typically be approximately as fast as mmap mod_ssi will likely be much faster, now buffering SSI page construction rather than a potentially huge number of file open() calls, one for each tiny chunk of text between SSI directives. mod_webdav COPY and MOVE may be slower due to removal of mmap, but are now more resilient to partial writes. x-ref: &#34;handle filesystems without mmap() support&#34; https://redmine.lighttpd.net/issues/2666 &#34;WebDAV upload-&gt; mmap failed: operation not permitted&#34; https://redmine.lighttpd.net/issues/962 &#34;Lighttpd 1.4.20 Crash (SIGBUS in mod_compress)&#34; https://redmine.lighttpd.net/issues/1879 &#34;Crash SIGBUS&#34; https://redmine.lighttpd.net/issues/2391 github: closes #57
6 years ago
#include <fcntl.h>
#include <unistd.h>
#ifdef HAVE_PWD_H
# include <pwd.h>
#endif
#ifdef HAVE_SYS_FILIO_H
# include <sys/filio.h>
#endif
static handler_ctx * handler_ctx_init(plugin_data *p, log_error_st *errh) {
handler_ctx *hctx = calloc(1, sizeof(*hctx));
force_assert(hctx);
hctx->errh = errh;
hctx->timefmt = p->timefmt;
hctx->stat_fn = p->stat_fn;
hctx->ssi_vars = p->ssi_vars;
hctx->ssi_cgi_env = p->ssi_cgi_env;
memcpy(&hctx->conf, &p->conf, sizeof(plugin_config));
return hctx;
}
static void handler_ctx_free(handler_ctx *hctx) {
free(hctx);
}
/* The newest modified time of included files for include statement */
static volatile time_t include_file_last_mtime = 0;
INIT_FUNC(mod_ssi_init) {
plugin_data *p;
p = calloc(1, sizeof(*p));
force_assert(p);
p->timefmt = buffer_init();
p->stat_fn = buffer_init();
p->ssi_vars = array_init(8);
p->ssi_cgi_env = array_init(32);
return p;
}
FREE_FUNC(mod_ssi_free) {
plugin_data *p = p_d;
array_free(p->ssi_vars);
array_free(p->ssi_cgi_env);
buffer_free(p->timefmt);
buffer_free(p->stat_fn);
}
static void mod_ssi_merge_config_cpv(plugin_config * const pconf, const config_plugin_value_t * const cpv) {
switch (cpv->k_id) { /* index into static config_plugin_keys_t cpk[] */
case 0: /* ssi.extension */
pconf->ssi_extension = cpv->v.a;
break;
case 1: /* ssi.content-type */
pconf->content_type = cpv->v.b;
break;
case 2: /* ssi.conditional-requests */
pconf->conditional_requests = cpv->v.u;
break;
case 3: /* ssi.exec */
pconf->ssi_exec = cpv->v.u;
break;
case 4: /* ssi.recursion-max */
pconf->ssi_recursion_max = cpv->v.shrt;
break;
default:/* should not happen */
return;
}
}
static void mod_ssi_merge_config(plugin_config * const pconf, const config_plugin_value_t *cpv) {
do {
mod_ssi_merge_config_cpv(pconf, cpv);
} while ((++cpv)->k_id != -1);
}
static void mod_ssi_patch_config(request_st * const r, plugin_data * const p) {
memcpy(&p->conf, &p->defaults, sizeof(plugin_config));
for (int i = 1, used = p->nconfig; i < used; ++i) {
if (config_check_cond(r, (uint32_t)p->cvlist[i].k_id))
mod_ssi_merge_config(&p->conf, p->cvlist + p->cvlist[i].v.u2[0]);
}
}
SETDEFAULTS_FUNC(mod_ssi_set_defaults) {
static const config_plugin_keys_t cpk[] = {
{ CONST_STR_LEN("ssi.extension"),
T_CONFIG_ARRAY_VLIST,
T_CONFIG_SCOPE_CONNECTION }
,{ CONST_STR_LEN("ssi.content-type"),
T_CONFIG_STRING,
T_CONFIG_SCOPE_CONNECTION }
,{ CONST_STR_LEN("ssi.conditional-requests"),
T_CONFIG_BOOL,
T_CONFIG_SCOPE_CONNECTION }
,{ CONST_STR_LEN("ssi.exec"),
T_CONFIG_BOOL,
T_CONFIG_SCOPE_CONNECTION }
,{ CONST_STR_LEN("ssi.recursion-max"),
T_CONFIG_SHORT,
T_CONFIG_SCOPE_CONNECTION }
,{ NULL, 0,
T_CONFIG_UNSET,
T_CONFIG_SCOPE_UNSET }
};
plugin_data * const p = p_d;
if (!config_plugin_values_init(srv, p, cpk, "mod_ssi"))
return HANDLER_ERROR;
p->defaults.ssi_exec = 1;
/* initialize p->defaults from global config context */
if (p->nconfig > 0 && p->cvlist->v.u2[1]) {
const config_plugin_value_t *cpv = p->cvlist + p->cvlist->v.u2[0];
if (-1 != cpv->k_id)
mod_ssi_merge_config(&p->defaults, cpv);
}
return HANDLER_GO_ON;
}
fallback to lseek()/read() if mmap() fails (#fixes 2666) fallback to lseek()/read() if mmap() fails (#fixes 2666) e.g. when mmap() is used on lighttpd-controlled temporary files used POST request body (mod_cgi) and PUT file upload (mod_webdav) replace use of stream_open() on potentially untrusted files (protect against SIGBUS if a file is modified while map is read) Note: stream.[ch] may be removed in a future release For now, stream.[ch] will read entire file into memory if mmap fails and so it should only be used on trusted files, e.g. config files. http_auth basic and digest files are typically small and so buffered stdio fopen(), fgets(), fclose() will likely be approximately as fast as mmap. mod_dirlisting header and readme files are typically small and so open(), read(), close() will typically be approximately as fast as mmap mod_ssi will likely be much faster, now buffering SSI page construction rather than a potentially huge number of file open() calls, one for each tiny chunk of text between SSI directives. mod_webdav COPY and MOVE may be slower due to removal of mmap, but are now more resilient to partial writes. x-ref: &#34;handle filesystems without mmap() support&#34; https://redmine.lighttpd.net/issues/2666 &#34;WebDAV upload-&gt; mmap failed: operation not permitted&#34; https://redmine.lighttpd.net/issues/962 &#34;Lighttpd 1.4.20 Crash (SIGBUS in mod_compress)&#34; https://redmine.lighttpd.net/issues/1879 &#34;Crash SIGBUS&#34; https://redmine.lighttpd.net/issues/2391 github: closes #57
6 years ago
static int ssi_env_add(void *venv, const char *key, size_t klen, const char *val, size_t vlen) {
array_set_key_value((array *)venv, key, klen, val, vlen);
return 0;
}
static int build_ssi_cgi_vars(request_st * const r, handler_ctx * const p) {
http_cgi_opts opts = { 0, 0, NULL, NULL };
/* temporarily remove Authorization from request headers
* so that Authorization does not end up in SSI environment */
buffer *vb_auth = http_header_request_get(r, HTTP_HEADER_AUTHORIZATION, CONST_STR_LEN("Authorization"));
buffer b_auth;
if (vb_auth) {
memcpy(&b_auth, vb_auth, sizeof(buffer));
memset(vb_auth, 0, sizeof(buffer));
}
array_reset_data_strings(p->ssi_cgi_env);
[mod_ssi] Add SSI vars SCRIPT_{URI,URL} and REQUEST_SCHEME (fixes #2721) This is a proposal to add to lighttpd the famous SSI variables SCRIPT_URI and SCRIPT_URL (known to Apache users), as well as a bonus ENV variable called REQUEST_SCHEME. SCRIPT_URI and SCRIPT_URL will be available as SSI variables from within documents handled by mod_ssi. They can be used like any other SSI var with the &#34;#echo var&#34; command: &lt;!--#echo var=&#34;SCRIPT_URI&#34;--&gt; &lt;!--#echo var=&#34;SCRIPT_URL&#34;--&gt; Webmasters willing to display links to the W3C Validator will be able to use: &lt;a href=&#34;http://validator.w3.org/check?uri=&lt;!--#echo var=&#34;SCRIPT_URI&#34;--&gt;&#34;&gt;…&lt;/a&gt; instead of the generic http://validator.w3.org/check?uri=referer link which does not work on some (most?) browsers which do not send referers when the link itself resides in a document sent through https. REQUEST_SCHEME will be available both as an environment variable. It is defined as &#34;http&#34; or &#34;https&#34;, depending on the scheme of the connection. It is safe to use this name as it does not conflict with any existing variable on Apache or Nginx. This is slightly different from the HTTPS var which is often added by webadmins on their server&#39;s configuration. EDIT: Some Apache modules also define REQUEST_SCHEME with the same possible values as this proposal. From: fbrosson &lt;fbrosson@users.noreply.github.com&gt; git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-1.4.x@3124 152afb58-edef-0310-8abb-c4023f1b3aa9
6 years ago
if (0 != http_cgi_headers(r, &opts, ssi_env_add, p->ssi_cgi_env)) {
r->http_status = 400;
return -1;
[mod_ssi] Add SSI vars SCRIPT_{URI,URL} and REQUEST_SCHEME (fixes #2721) This is a proposal to add to lighttpd the famous SSI variables SCRIPT_URI and SCRIPT_URL (known to Apache users), as well as a bonus ENV variable called REQUEST_SCHEME. SCRIPT_URI and SCRIPT_URL will be available as SSI variables from within documents handled by mod_ssi. They can be used like any other SSI var with the &#34;#echo var&#34; command: &lt;!--#echo var=&#34;SCRIPT_URI&#34;--&gt; &lt;!--#echo var=&#34;SCRIPT_URL&#34;--&gt; Webmasters willing to display links to the W3C Validator will be able to use: &lt;a href=&#34;http://validator.w3.org/check?uri=&lt;!--#echo var=&#34;SCRIPT_URI&#34;--&gt;&#34;&gt;…&lt;/a&gt; instead of the generic http://validator.w3.org/check?uri=referer link which does not work on some (most?) browsers which do not send referers when the link itself resides in a document sent through https. REQUEST_SCHEME will be available both as an environment variable. It is defined as &#34;http&#34; or &#34;https&#34;, depending on the scheme of the connection. It is safe to use this name as it does not conflict with any existing variable on Apache or Nginx. This is slightly different from the HTTPS var which is often added by webadmins on their server&#39;s configuration. EDIT: Some Apache modules also define REQUEST_SCHEME with the same possible values as this proposal. From: fbrosson &lt;fbrosson@users.noreply.github.com&gt; git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-1.4.x@3124 152afb58-edef-0310-8abb-c4023f1b3aa9
6 years ago
}
if (vb_auth) {
memcpy(vb_auth, &b_auth, sizeof(buffer));
}
return 0;
}
static int mod_ssi_process_file(request_st *r, handler_ctx *p, struct stat *st);
static int process_ssi_stmt(request_st * const r, handler_ctx * const p, const char ** const l, size_t n, struct stat * const st) {
fallback to lseek()/read() if mmap() fails (#fixes 2666) fallback to lseek()/read() if mmap() fails (#fixes 2666) e.g. when mmap() is used on lighttpd-controlled temporary files used POST request body (mod_cgi) and PUT file upload (mod_webdav) replace use of stream_open() on potentially untrusted files (protect against SIGBUS if a file is modified while map is read) Note: stream.[ch] may be removed in a future release For now, stream.[ch] will read entire file into memory if mmap fails and so it should only be used on trusted files, e.g. config files. http_auth basic and digest files are typically small and so buffered stdio fopen(), fgets(), fclose() will likely be approximately as fast as mmap. mod_dirlisting header and readme files are typically small and so open(), read(), close() will typically be approximately as fast as mmap mod_ssi will likely be much faster, now buffering SSI page construction rather than a potentially huge number of file open() calls, one for each tiny chunk of text between SSI directives. mod_webdav COPY and MOVE may be slower due to removal of mmap, but are now more resilient to partial writes. x-ref: &#34;handle filesystems without mmap() support&#34; https://redmine.lighttpd.net/issues/2666 &#34;WebDAV upload-&gt; mmap failed: operation not permitted&#34; https://redmine.lighttpd.net/issues/962 &#34;Lighttpd 1.4.20 Crash (SIGBUS in mod_compress)&#34; https://redmine.lighttpd.net/issues/1879 &#34;Crash SIGBUS&#34; https://redmine.lighttpd.net/issues/2391 github: closes #57
6 years ago
/**
* <!--#element attribute=value attribute=value ... -->
*
* config DONE
* errmsg -- missing
* sizefmt DONE
* timefmt DONE
* echo DONE
* var DONE
* encoding -- missing
* exec DONE
* cgi -- never
* cmd DONE
* fsize DONE
* file DONE
* virtual DONE
* flastmod DONE
* file DONE
* virtual DONE
* include DONE
* file DONE
* virtual DONE
* printenv DONE
* set DONE
* var DONE
* value DONE
*
* if DONE
* elif DONE
* else DONE
* endif DONE
*
*
* expressions
* AND, OR DONE
* comp DONE
* ${...} -- missing
* $... DONE
* '...' DONE
* ( ... ) DONE
*
*
*
* ** all DONE **
* DATE_GMT
* The current date in Greenwich Mean Time.
* DATE_LOCAL
* The current date in the local time zone.
* DOCUMENT_NAME
* The filename (excluding directories) of the document requested by the user.
* DOCUMENT_URI
* The (%-decoded) URL path of the document requested by the user. Note that in the case of nested include files, this is not then URL for the current document.
* LAST_MODIFIED
* The last modification date of the document requested by the user.
* USER_NAME
* Contains the owner of the file which included it.
*
*/
size_t i, ssicmd = 0;
char buf[255];
buffer *tb = NULL;
static const struct {
const char *var;
enum { SSI_UNSET, SSI_ECHO, SSI_FSIZE, SSI_INCLUDE, SSI_FLASTMOD,
SSI_CONFIG, SSI_PRINTENV, SSI_SET, SSI_IF, SSI_ELIF,
SSI_ELSE, SSI_ENDIF, SSI_EXEC, SSI_COMMENT } type;
} ssicmds[] = {
{ "echo", SSI_ECHO },
{ "include", SSI_INCLUDE },
{ "flastmod", SSI_FLASTMOD },
{ "fsize", SSI_FSIZE },
{ "config", SSI_CONFIG },
{ "printenv", SSI_PRINTENV },
{ "set", SSI_SET },
{ "if", SSI_IF },
{ "elif", SSI_ELIF },
{ "endif", SSI_ENDIF },
{ "else", SSI_ELSE },
{ "exec", SSI_EXEC },
{ "comment", SSI_COMMENT },
{ NULL, SSI_UNSET }
};
for (i = 0; ssicmds[i].var; i++) {
if (0 == strcmp(l[1], ssicmds[i].var)) {
ssicmd = ssicmds[i].type;
break;
}
}
chunkqueue * const cq = &r->write_queue;
switch(ssicmd) {
case SSI_ECHO: {
/* echo */
int var = 0;
/* int enc = 0; */
const char *var_val = NULL;
static const struct {
const char *var;
[mod_ssi] Add SSI vars SCRIPT_{URI,URL} and REQUEST_SCHEME (fixes #2721) This is a proposal to add to lighttpd the famous SSI variables SCRIPT_URI and SCRIPT_URL (known to Apache users), as well as a bonus ENV variable called REQUEST_SCHEME. SCRIPT_URI and SCRIPT_URL will be available as SSI variables from within documents handled by mod_ssi. They can be used like any other SSI var with the &#34;#echo var&#34; command: &lt;!--#echo var=&#34;SCRIPT_URI&#34;--&gt; &lt;!--#echo var=&#34;SCRIPT_URL&#34;--&gt; Webmasters willing to display links to the W3C Validator will be able to use: &lt;a href=&#34;http://validator.w3.org/check?uri=&lt;!--#echo var=&#34;SCRIPT_URI&#34;--&gt;&#34;&gt;…&lt;/a&gt; instead of the generic http://validator.w3.org/check?uri=referer link which does not work on some (most?) browsers which do not send referers when the link itself resides in a document sent through https. REQUEST_SCHEME will be available both as an environment variable. It is defined as &#34;http&#34; or &#34;https&#34;, depending on the scheme of the connection. It is safe to use this name as it does not conflict with any existing variable on Apache or Nginx. This is slightly different from the HTTPS var which is often added by webadmins on their server&#39;s configuration. EDIT: Some Apache modules also define REQUEST_SCHEME with the same possible values as this proposal. From: fbrosson &lt;fbrosson@users.noreply.github.com&gt; git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-1.4.x@3124 152afb58-edef-0310-8abb-c4023f1b3aa9
6 years ago
enum {
SSI_ECHO_UNSET,
SSI_ECHO_DATE_GMT,
SSI_ECHO_DATE_LOCAL,
SSI_ECHO_DOCUMENT_NAME,
SSI_ECHO_DOCUMENT_URI,
SSI_ECHO_LAST_MODIFIED,
SSI_ECHO_USER_NAME,
SSI_ECHO_SCRIPT_URI,
SSI_ECHO_SCRIPT_URL,
} type;
} echovars[] = {
{ "DATE_GMT", SSI_ECHO_DATE_GMT },
{ "DATE_LOCAL", SSI_ECHO_DATE_LOCAL },
{ "DOCUMENT_NAME", SSI_ECHO_DOCUMENT_NAME },
{ "DOCUMENT_URI", SSI_ECHO_DOCUMENT_URI },
{ "LAST_MODIFIED", SSI_ECHO_LAST_MODIFIED },
{ "USER_NAME", SSI_ECHO_USER_NAME },
[mod_ssi] Add SSI vars SCRIPT_{URI,URL} and REQUEST_SCHEME (fixes #2721) This is a proposal to add to lighttpd the famous SSI variables SCRIPT_URI and SCRIPT_URL (known to Apache users), as well as a bonus ENV variable called REQUEST_SCHEME. SCRIPT_URI and SCRIPT_URL will be available as SSI variables from within documents handled by mod_ssi. They can be used like any other SSI var with the &#34;#echo var&#34; command: &lt;!--#echo var=&#34;SCRIPT_URI&#34;--&gt; &lt;!--#echo var=&#34;SCRIPT_URL&#34;--&gt; Webmasters willing to display links to the W3C Validator will be able to use: &lt;a href=&#34;http://validator.w3.org/check?uri=&lt;!--#echo var=&#34;SCRIPT_URI&#34;--&gt;&#34;&gt;…&lt;/a&gt; instead of the generic http://validator.w3.org/check?uri=referer link which does not work on some (most?) browsers which do not send referers when the link itself resides in a document sent through https. REQUEST_SCHEME will be available both as an environment variable. It is defined as &#34;http&#34; or &#34;https&#34;, depending on the scheme of the connection. It is safe to use this name as it does not conflict with any existing variable on Apache or Nginx. This is slightly different from the HTTPS var which is often added by webadmins on their server&#39;s configuration. EDIT: Some Apache modules also define REQUEST_SCHEME with the same possible values as this proposal. From: fbrosson &lt;fbrosson@users.noreply.github.com&gt; git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-1.4.x@3124 152afb58-edef-0310-8abb-c4023f1b3aa9
6 years ago
{ "SCRIPT_URI", SSI_ECHO_SCRIPT_URI },
{ "SCRIPT_URL", SSI_ECHO_SCRIPT_URL },
{ NULL, SSI_ECHO_UNSET }
};
/*
static const struct {
const char *var;
enum { SSI_ENC_UNSET, SSI_ENC_URL, SSI_ENC_NONE, SSI_ENC_ENTITY } type;
} encvars[] = {
{ "url", SSI_ENC_URL },
{ "none", SSI_ENC_NONE },
{ "entity", SSI_ENC_ENTITY },
{ NULL, SSI_ENC_UNSET }
};
*/
for (i = 2; i < n; i += 2) {
if (0 == strcmp(l[i], "var")) {
int j;
var_val = l[i+1];
for (j = 0; echovars[j].var; j++) {
if (0 == strcmp(l[i+1], echovars[j].var)) {
var = echovars[j].type;
break;
}
}
} else if (0 == strcmp(l[i], "encoding")) {
/*
int j;
for (j = 0; encvars[j].var; j++) {
if (0 == strcmp(l[i+1], encvars[j].var)) {
enc = encvars[j].type;
break;
}
}
*/
} else {
log_error(r->conf.errh, __FILE__, __LINE__,
"ssi: unknown attribute for %s %s", l[1], l[i]);
}
}
if (p->if_is_false) break;
if (!var_val) {
log_error(r->conf.errh, __FILE__, __LINE__,
"ssi: %s var is missing", l[1]);
break;
}
switch(var) {
case SSI_ECHO_USER_NAME: {
tb = r->tmp_buf;
buffer_clear(tb);
#ifdef HAVE_PWD_H
struct passwd *pw;
fallback to lseek()/read() if mmap() fails (#fixes 2666) fallback to lseek()/read() if mmap() fails (#fixes 2666) e.g. when mmap() is used on lighttpd-controlled temporary files used POST request body (mod_cgi) and PUT file upload (mod_webdav) replace use of stream_open() on potentially untrusted files (protect against SIGBUS if a file is modified while map is read) Note: stream.[ch] may be removed in a future release For now, stream.[ch] will read entire file into memory if mmap fails and so it should only be used on trusted files, e.g. config files. http_auth basic and digest files are typically small and so buffered stdio fopen(), fgets(), fclose() will likely be approximately as fast as mmap. mod_dirlisting header and readme files are typically small and so open(), read(), close() will typically be approximately as fast as mmap mod_ssi will likely be much faster, now buffering SSI page construction rather than a potentially huge number of file open() calls, one for each tiny chunk of text between SSI directives. mod_webdav COPY and MOVE may be slower due to removal of mmap, but are now more resilient to partial writes. x-ref: &#34;handle filesystems without mmap() support&#34; https://redmine.lighttpd.net/issues/2666 &#34;WebDAV upload-&gt; mmap failed: operation not permitted&#34; https://redmine.lighttpd.net/issues/962 &#34;Lighttpd 1.4.20 Crash (SIGBUS in mod_compress)&#34; https://redmine.lighttpd.net/issues/1879 &#34;Crash SIGBUS&#34; https://redmine.lighttpd.net/issues/2391 github: closes #57
6 years ago
if (NULL == (pw = getpwuid(st->st_uid))) {
buffer_append_int(tb, st->st_uid);
} else {
buffer_copy_string(tb, pw->pw_name);
}
#else
buffer_append_int(tb, st->st_uid);
#endif
chunkqueue_append_mem(cq, CONST_BUF_LEN(tb));
break;
}
case SSI_ECHO_LAST_MODIFIED:
case SSI_ECHO_DATE_LOCAL:
case SSI_ECHO_DATE_GMT: {
struct tm tm;
time_t t = (var == SSI_ECHO_LAST_MODIFIED)
? st->st_mtime
: time(NULL);
uint32_t len = strftime(buf, sizeof(buf), p->timefmt->ptr,
(var != SSI_ECHO_DATE_GMT)
? localtime_r(&t, &tm)
: gmtime_r(&t, &tm));
if (len)
chunkqueue_append_mem(cq, buf, len);
else
chunkqueue_append_mem(cq, CONST_STR_LEN("(none)"));
break;
}
case SSI_ECHO_DOCUMENT_NAME: {
char *sl;
if (NULL == (sl = strrchr(r->physical.path.ptr, '/'))) {
chunkqueue_append_mem(cq, CONST_BUF_LEN(&r->physical.path));
} else {
chunkqueue_append_mem(cq, sl + 1, strlen(sl + 1));
}
break;
}
case SSI_ECHO_DOCUMENT_URI: {
chunkqueue_append_mem(cq, CONST_BUF_LEN(&r->uri.path));
break;
}
[mod_ssi] Add SSI vars SCRIPT_{URI,URL} and REQUEST_SCHEME (fixes #2721) This is a proposal to add to lighttpd the famous SSI variables SCRIPT_URI and SCRIPT_URL (known to Apache users), as well as a bonus ENV variable called REQUEST_SCHEME. SCRIPT_URI and SCRIPT_URL will be available as SSI variables from within documents handled by mod_ssi. They can be used like any other SSI var with the &#34;#echo var&#34; command: &lt;!--#echo var=&#34;SCRIPT_URI&#34;--&gt; &lt;!--#echo var=&#34;SCRIPT_URL&#34;--&gt; Webmasters willing to display links to the W3C Validator will be able to use: &lt;a href=&#34;http://validator.w3.org/check?uri=&lt;!--#echo var=&#34;SCRIPT_URI&#34;--&gt;&#34;&gt;…&lt;/a&gt; instead of the generic http://validator.w3.org/check?uri=referer link which does not work on some (most?) browsers which do not send referers when the link itself resides in a document sent through https. REQUEST_SCHEME will be available both as an environment variable. It is defined as &#34;http&#34; or &#34;https&#34;, depending on the scheme of the connection. It is safe to use this name as it does not conflict with any existing variable on Apache or Nginx. This is slightly different from the HTTPS var which is often added by webadmins on their server&#39;s configuration. EDIT: Some Apache modules also define REQUEST_SCHEME with the same possible values as this proposal. From: fbrosson &lt;fbrosson@users.noreply.github.com&gt; git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-1.4.x@3124 152afb58-edef-0310-8abb-c4023f1b3aa9
6 years ago
case SSI_ECHO_SCRIPT_URI: {
if (!buffer_string_is_empty(&r->uri.scheme) && !buffer_string_is_empty(&r->uri.authority)) {
chunkqueue_append_mem(cq, CONST_BUF_LEN(&r->uri.scheme));
chunkqueue_append_mem(cq, CONST_STR_LEN("://"));
chunkqueue_append_mem(cq, CONST_BUF_LEN(&r->uri.authority));
chunkqueue_append_mem(cq, CONST_BUF_LEN(&r->target));
if (!buffer_string_is_empty(&r->uri.query)) {
chunkqueue_append_mem(cq, CONST_STR_LEN("?"));
chunkqueue_append_mem(cq, CONST_BUF_LEN(&r->uri.query));
[mod_ssi] Add SSI vars SCRIPT_{URI,URL} and REQUEST_SCHEME (fixes #2721) This is a proposal to add to lighttpd the famous SSI variables SCRIPT_URI and SCRIPT_URL (known to Apache users), as well as a bonus ENV variable called REQUEST_SCHEME. SCRIPT_URI and SCRIPT_URL will be available as SSI variables from within documents handled by mod_ssi. They can be used like any other SSI var with the &#34;#echo var&#34; command: &lt;!--#echo var=&#34;SCRIPT_URI&#34;--&gt; &lt;!--#echo var=&#34;SCRIPT_URL&#34;--&gt; Webmasters willing to display links to the W3C Validator will be able to use: &lt;a href=&#34;http://validator.w3.org/check?uri=&lt;!--#echo var=&#34;SCRIPT_URI&#34;--&gt;&#34;&gt;…&lt;/a&gt; instead of the generic http://validator.w3.org/check?uri=referer link which does not work on some (most?) browsers which do not send referers when the link itself resides in a document sent through https. REQUEST_SCHEME will be available both as an environment variable. It is defined as &#34;http&#34; or &#34;https&#34;, depending on the scheme of the connection. It is safe to use this name as it does not conflict with any existing variable on Apache or Nginx. This is slightly different from the HTTPS var which is often added by webadmins on their server&#39;s configuration. EDIT: Some Apache modules also define REQUEST_SCHEME with the same possible values as this proposal. From: fbrosson &lt;fbrosson@users.noreply.github.com&gt; git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-1.4.x@3124 152afb58-edef-0310-8abb-c4023f1b3aa9
6 years ago
}
}
break;
}
case SSI_ECHO_SCRIPT_URL: {
chunkqueue_append_mem(cq, CONST_BUF_LEN(&r->target));
if (!buffer_string_is_empty(&r->uri.query)) {
chunkqueue_append_mem(cq, CONST_STR_LEN("?"));
chunkqueue_append_mem(cq, CONST_BUF_LEN(&r->uri.query));
[mod_ssi] Add SSI vars SCRIPT_{URI,URL} and REQUEST_SCHEME (fixes #2721) This is a proposal to add to lighttpd the famous SSI variables SCRIPT_URI and SCRIPT_URL (known to Apache users), as well as a bonus ENV variable called REQUEST_SCHEME. SCRIPT_URI and SCRIPT_URL will be available as SSI variables from within documents handled by mod_ssi. They can be used like any other SSI var with the &#34;#echo var&#34; command: &lt;!--#echo var=&#34;SCRIPT_URI&#34;--&gt; &lt;!--#echo var=&#34;SCRIPT_URL&#34;--&gt; Webmasters willing to display links to the W3C Validator will be able to use: &lt;a href=&#34;http://validator.w3.org/check?uri=&lt;!--#echo var=&#34;SCRIPT_URI&#34;--&gt;&#34;&gt;…&lt;/a&gt; instead of the generic http://validator.w3.org/check?uri=referer link which does not work on some (most?) browsers which do not send referers when the link itself resides in a document sent through https. REQUEST_SCHEME will be available both as an environment variable. It is defined as &#34;http&#34; or &#34;https&#34;, depending on the scheme of the connection. It is safe to use this name as it does not conflict with any existing variable on Apache or Nginx. This is slightly different from the HTTPS var which is often added by webadmins on their server&#39;s configuration. EDIT: Some Apache modules also define REQUEST_SCHEME with the same possible values as this proposal. From: fbrosson &lt;fbrosson@users.noreply.github.com&gt; git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-1.4.x@3124 152afb58-edef-0310-8abb-c4023f1b3aa9
6 years ago
}
break;
}
default: {
const data_string *ds;
/* check if it is a cgi-var or a ssi-var */
if (NULL != (ds = (const data_string *)array_get_element_klen(p->ssi_cgi_env, var_val, strlen(var_val))) ||
NULL != (ds = (const data_string *)array_get_element_klen(p->ssi_vars, var_val, strlen(var_val)))) {
chunkqueue_append_mem(cq, CONST_BUF_LEN(&ds->value));
} else {
chunkqueue_append_mem(cq, CONST_STR_LEN("(none)"));
}
break;
}
}
break;
}
case SSI_INCLUDE:
case SSI_FLASTMOD:
case SSI_FSIZE: {
const char * file_path = NULL, *virt_path = NULL;
fallback to lseek()/read() if mmap() fails (#fixes 2666) fallback to lseek()/read() if mmap() fails (#fixes 2666) e.g. when mmap() is used on lighttpd-controlled temporary files used POST request body (mod_cgi) and PUT file upload (mod_webdav) replace use of stream_open() on potentially untrusted files (protect against SIGBUS if a file is modified while map is read) Note: stream.[ch] may be removed in a future release For now, stream.[ch] will read entire file into memory if mmap fails and so it should only be used on trusted files, e.g. config files. http_auth basic and digest files are typically small and so buffered stdio fopen(), fgets(), fclose() will likely be approximately as fast as mmap. mod_dirlisting header and readme files are typically small and so open(), read(), close() will typically be approximately as fast as mmap mod_ssi will likely be much faster, now buffering SSI page construction rather than a potentially huge number of file open() calls, one for each tiny chunk of text between SSI directives. mod_webdav COPY and MOVE may be slower due to removal of mmap, but are now more resilient to partial writes. x-ref: &#34;handle filesystems without mmap() support&#34; https://redmine.lighttpd.net/issues/2666 &#34;WebDAV upload-&gt; mmap failed: operation not permitted&#34; https://redmine.lighttpd.net/issues/962 &#34;Lighttpd 1.4.20 Crash (SIGBUS in mod_compress)&#34; https://redmine.lighttpd.net/issues/1879 &#34;Crash SIGBUS&#34; https://redmine.lighttpd.net/issues/2391 github: closes #57
6 years ago
struct stat stb;
for (i = 2; i < n; i += 2) {
if (0 == strcmp(l[i], "file")) {
file_path = l[i+1];
} else if (0 == strcmp(l[i], "virtual")) {
virt_path = l[i+1];
} else {
log_error(r->conf.errh, __FILE__, __LINE__,
"ssi: unknown attribute for %s %s", l[1], l[i]);
}
}
if (!file_path && !virt_path) {
log_error(r->conf.errh, __FILE__, __LINE__,
"ssi: %s file or virtual is missing", l[1]);
break;
}
if (file_path && virt_path) {
log_error(r->conf.errh, __FILE__, __LINE__,
"ssi: %s only one of file and virtual is allowed here", l[1]);
break;
}
if (p->if_is_false) break;
tb = r->tmp_buf;
if (file_path) {
/* current doc-root */
char *sl = strrchr(r->physical.path.ptr, '/');
if (NULL == sl) break; /*(not expected)*/
buffer_copy_string_len(p->stat_fn, r->physical.path.ptr, sl - r->physical.path.ptr + 1);
buffer_copy_string(tb, file_path);
buffer_urldecode_path(tb);
if (!buffer_is_valid_UTF8(tb)) {
log_error(r->conf.errh, __FILE__, __LINE__,
"SSI invalid UTF-8 after url-decode: %s", tb->ptr);
break;
}
buffer_path_simplify(tb, tb);
buffer_append_path_len(p->stat_fn, CONST_BUF_LEN(tb));
} else {
/* virtual */
if (virt_path[0] == '/') {
buffer_copy_string(tb, virt_path);
} else {
/* there is always a / */
const char * const sl = strrchr(r->uri.path.ptr, '/');
buffer_copy_string_len(tb, r->uri.path.ptr, sl - r->uri.path.ptr + 1);
buffer_append_string(tb, virt_path);
}
buffer_urldecode_path(tb);
if (!buffer_is_valid_UTF8(tb)) {
log_error(r->conf.errh, __FILE__, __LINE__,
"SSI invalid UTF-8 after url-decode: %s", tb->ptr);
break;
}
buffer_path_simplify(tb, tb);
/* we have an uri */
/* Destination physical path (similar to code in mod_webdav.c)
* src r->physical.path might have been remapped with mod_alias, mod_userdir.
* (but neither modifies r->physical.rel_path)
* Find matching prefix to support relative paths to current physical path.
* Aliasing of paths underneath current r->physical.basedir might not work.
* Likewise, mod_rewrite URL rewriting might thwart this comparison.
* Use mod_redirect instead of mod_alias to remap paths *under* this basedir.
* Use mod_redirect instead of mod_rewrite on *any* parts of path to basedir.
* (Related, use mod_auth to protect this basedir, but avoid attempting to
* use mod_auth on paths underneath this basedir, as target path is not
* validated with mod_auth)
*/
/* find matching URI prefix
* check if remaining r->physical.rel_path matches suffix
* of r->physical.basedir so that we can use it to
* remap Destination physical path */
{
const char *sep, *sep2;
sep = r->uri.path.ptr;
sep2 = tb->ptr;
for (i = 0; sep[i] && sep[i] == sep2[i]; ++i) ;
while (i != 0 && sep[--i] != '/') ; /* find matching directory path */
}
if (r->conf.force_lowercase_filenames) {
buffer_to_lower(tb);
}
uint32_t remain = buffer_string_length(&r->uri.path) - i;
if (!r->conf.force_lowercase_filenames
? buffer_is_equal_right_len(&r->physical.path, &r->physical.rel_path, remain)
:(buffer_string_length(&r->physical.path) >= remain
&& buffer_eq_icase_ssn(r->physical.path.ptr+buffer_string_length(&r->physical.path)-remain, r->physical.rel_path.ptr+i, remain))) {
buffer_copy_string_len(p->stat_fn, r->physical.path.ptr, buffer_string_length(&r->physical.path)-remain);
buffer_append_path_len(p->stat_fn, tb->ptr+i, buffer_string_length(tb)-i);
} else {
/* unable to perform physical path remap here;
* assume doc_root/rel_path and no remapping */
buffer_copy_buffer(p->stat_fn, &r->physical.doc_root);
buffer_append_path_len(p->stat_fn, CONST_BUF_LEN(tb));
}
}
if (!r->conf.follow_symlink
&& 0 != stat_cache_path_contains_symlink(p->stat_fn, r->conf.errh)) {
break;
}
int fd = stat_cache_open_rdonly_fstat(p->stat_fn, &stb, r->conf.follow_symlink);
if (fd >= 0) {
fallback to lseek()/read() if mmap() fails (#fixes 2666) fallback to lseek()/read() if mmap() fails (#fixes 2666) e.g. when mmap() is used on lighttpd-controlled temporary files used POST request body (mod_cgi) and PUT file upload (mod_webdav) replace use of stream_open() on potentially untrusted files (protect against SIGBUS if a file is modified while map is read) Note: stream.[ch] may be removed in a future release For now, stream.[ch] will read entire file into memory if mmap fails and so it should only be used on trusted files, e.g. config files. http_auth basic and digest files are typically small and so buffered stdio fopen(), fgets(), fclose() will likely be approximately as fast as mmap. mod_dirlisting header and readme files are typically small and so open(), read(), close() will typically be approximately as fast as mmap mod_ssi will likely be much faster, now buffering SSI page construction rather than a potentially huge number of file open() calls, one for each tiny chunk of text between SSI directives. mod_webdav COPY and MOVE may be slower due to removal of mmap, but are now more resilient to partial writes. x-ref: &#34;handle filesystems without mmap() support&#34; https://redmine.lighttpd.net/issues/2666 &#34;WebDAV upload-&gt; mmap failed: operation not permitted&#34; https://redmine.lighttpd.net/issues/962 &#34;Lighttpd 1.4.20 Crash (SIGBUS in mod_compress)&#34; https://redmine.lighttpd.net/issues/1879 &#34;Crash SIGBUS&#34; https://redmine.lighttpd.net/issues/2391 github: closes #57
6 years ago
time_t t = stb.st_mtime;
switch (ssicmd) {
case SSI_FSIZE:
buffer_clear(tb);
if (p->sizefmt) {
int j = 0;
const char *abr[] = { " B", " kB", " MB", " GB", " TB", NULL };
fallback to lseek()/read() if mmap() fails (#fixes 2666) fallback to lseek()/read() if mmap() fails (#fixes 2666) e.g. when mmap() is used on lighttpd-controlled temporary files used POST request body (mod_cgi) and PUT file upload (mod_webdav) replace use of stream_open() on potentially untrusted files (protect against SIGBUS if a file is modified while map is read) Note: stream.[ch] may be removed in a future release For now, stream.[ch] will read entire file into memory if mmap fails and so it should only be used on trusted files, e.g. config files. http_auth basic and digest files are typically small and so buffered stdio fopen(), fgets(), fclose() will likely be approximately as fast as mmap. mod_dirlisting header and readme files are typically small and so open(), read(), close() will typically be approximately as fast as mmap mod_ssi will likely be much faster, now buffering SSI page construction rather than a potentially huge number of file open() calls, one for each tiny chunk of text between SSI directives. mod_webdav COPY and MOVE may be slower due to removal of mmap, but are now more resilient to partial writes. x-ref: &#34;handle filesystems without mmap() support&#34; https://redmine.lighttpd.net/issues/2666 &#34;WebDAV upload-&gt; mmap failed: operation not permitted&#34; https://redmine.lighttpd.net/issues/962 &#34;Lighttpd 1.4.20 Crash (SIGBUS in mod_compress)&#34; https://redmine.lighttpd.net/issues/1879 &#34;Crash SIGBUS&#34; https://redmine.lighttpd.net/issues/2391 github: closes #57
6 years ago
off_t s = stb.st_size;
for (j = 0; s > 1024 && abr[j+1]; s /= 1024, j++);
buffer_append_int(tb, s);
buffer_append_string(tb, abr[j]);
} else {
buffer_append_int(tb, stb.st_size);
}
chunkqueue_append_mem(cq, CONST_BUF_LEN(tb));
break;
case SSI_FLASTMOD: {
struct tm tm;
uint32_t len = (uint32_t)strftime(buf, sizeof(buf), p->timefmt->ptr, localtime_r(&t, &tm));
if (len)
chunkqueue_append_mem(cq, buf, len);
else
chunkqueue_append_mem(cq, CONST_STR_LEN("(none)"));
break;
}
case SSI_INCLUDE:
/* Keep the newest mtime of included files */
fallback to lseek()/read() if mmap() fails (#fixes 2666) fallback to lseek()/read() if mmap() fails (#fixes 2666) e.g. when mmap() is used on lighttpd-controlled temporary files used POST request body (mod_cgi) and PUT file upload (mod_webdav) replace use of stream_open() on potentially untrusted files (protect against SIGBUS if a file is modified while map is read) Note: stream.[ch] may be removed in a future release For now, stream.[ch] will read entire file into memory if mmap fails and so it should only be used on trusted files, e.g. config files. http_auth basic and digest files are typically small and so buffered stdio fopen(), fgets(), fclose() will likely be approximately as fast as mmap. mod_dirlisting header and readme files are typically small and so open(), read(), close() will typically be approximately as fast as mmap mod_ssi will likely be much faster, now buffering SSI page construction rather than a potentially huge number of file open() calls, one for each tiny chunk of text between SSI directives. mod_webdav COPY and MOVE may be slower due to removal of mmap, but are now more resilient to partial writes. x-ref: &#34;handle filesystems without mmap() support&#34; https://redmine.lighttpd.net/issues/2666 &#34;WebDAV upload-&gt; mmap failed: operation not permitted&#34; https://redmine.lighttpd.net/issues/962 &#34;Lighttpd 1.4.20 Crash (SIGBUS in mod_compress)&#34; https://redmine.lighttpd.net/issues/1879 &#34;Crash SIGBUS&#34; https://redmine.lighttpd.net/issues/2391 github: closes #57
6 years ago
if (stb