Michael Halstead [Wed, 14 Nov 2012 20:41:01 +0000 (12:41 -0800)]
Format git diff headers correctly when adding or removing files.
Copying the output of cgit and using it in patches now works when adding
files to or removing files from the repository. This is helpful for people
who use cgit in their patch workflow.
By not quoting the argument, an attacker with the ability to add files
to the repository could pass arbitrary arguments to the highlight
command, in particular, the --plug-in argument which can lead to
arbitrary command execution.
Tobias Bieniek [Tue, 9 Oct 2012 18:53:29 +0000 (20:53 +0200)]
ui-repolist: Add "section-sort" flag to control section sorting.
Flag which, when set to "1", will sort the sections on the repository
listing by name. Set this flag to "0" if the order in the cgitrc file
should be preserved. Default value: "1".
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
- gitweb.category maps to the cgit repo config key "section"
- gitweb.description maps to the cgit repo config key "desc"
- gitweb.owner maps to the cgit repo config key "owner"
- cgit.* maps to all cgit repo config keys
This option can be enabled with "enable-git-config=1", and replaces
all previous "enable-gitweb-*" config keys.
The order of operations is as follows:
- git config settings are applied in the order that they exist in
the git config file
- if the owner is not set from git config, get the owner using the
usual getpwuid call
- if the description is not set from git config, look inside the
static $path/description file
- if section-from-path=1, override whatever previous settings were
inside of git config using the section-from-path logic
- parse $path/cgitrc for local repo.* settings, that override all
previous settings
repo_config: do not let globals override repo settings
This makes it possible to activate the enable_commit_graph,
enable_log_filecount, and enable_log_linecount for individual
repositories, even if the global setting is "0" (default).
The commit that introduced the broken behavior was e189344, and the
commit message of that makes it clear that this wasn't the intended
behavior.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Ferry Huberts [Tue, 9 Oct 2012 11:10:48 +0000 (13:10 +0200)]
syntax-highlight: when the file has no extension, assume text
There are 2 situations:
1- empty extension: assuming text is better than highlight
producing no output because of a missing argument.
2- no extension at all: assuming text is better than setting
the extension to the filename, which is what now happens.
Jim Meyering [Mon, 23 Apr 2012 20:06:35 +0000 (22:06 +0200)]
do not write outside heap buffer
* parsing.c (substr): Handle tail < head.
This started when I noticed some cgit segfaults on savannah.gnu.org.
Finding the offending URL/commit and then constructing a stand-alone
reproducer were far more time-consuming than writing the actual patch.
The problem arises with a commit like this, in which the user name
part of the "Author" field is empty:
(this is due to buf=malloc(0); strncpy (buf, head, -1);
where "head" may point to plenty of attacker-specified non-NUL bytes,
so we can overwrite a zero-length heap buffer with arbitrary data)
Invalid write of size 1
at 0x4A09361: strncpy (mc_replace_strmem.c:463)
by 0x408977: substr (parsing.c:61)
by 0x4089EF: parse_user (parsing.c:73)
by 0x408D10: cgit_parse_commit (parsing.c:153)
by 0x40A540: cgit_mk_refinfo (shared.c:171)
by 0x40A581: cgit_refs_cb (shared.c:181)
by 0x43DEB3: do_for_each_ref (refs.c:690)
by 0x41075E: cgit_print_branches (ui-refs.c:191)
by 0x416EF2: cgit_print_summary (ui-summary.c:56)
by 0x40780A: summary_fn (cmd.c:120)
by 0x40667A: process_request (cgit.c:544)
by 0x404078: cache_process (cache.c:322)
Address 0x4c718d0 is 0 bytes after a block of size 0 alloc'd
at 0x4A0884D: malloc (vg_replace_malloc.c:263)
by 0x455C85: xmalloc (wrapper.c:35)
by 0x40894C: substr (parsing.c:60)
by 0x4089EF: parse_user (parsing.c:73)
by 0x408D10: cgit_parse_commit (parsing.c:153)
by 0x40A540: cgit_mk_refinfo (shared.c:171)
by 0x40A581: cgit_refs_cb (shared.c:181)
by 0x43DEB3: do_for_each_ref (refs.c:690)
by 0x41075E: cgit_print_branches (ui-refs.c:191)
by 0x416EF2: cgit_print_summary (ui-summary.c:56)
by 0x40780A: summary_fn (cmd.c:120)
by 0x40667A: process_request (cgit.c:544)
Invalid write of size 1
at 0x4A09400: strncpy (mc_replace_strmem.c:463)
by 0x408977: substr (parsing.c:61)
by 0x4089EF: parse_user (parsing.c:73)
by 0x408D10: cgit_parse_commit (parsing.c:153)
by 0x40A540: cgit_mk_refinfo (shared.c:171)
by 0x40A581: cgit_refs_cb (shared.c:181)
by 0x43DEB3: do_for_each_ref (refs.c:690)
by 0x41075E: cgit_print_branches (ui-refs.c:191)
by 0x416EF2: cgit_print_summary (ui-summary.c:56)
by 0x40780A: summary_fn (cmd.c:120)
by 0x40667A: process_request (cgit.c:544)
by 0x404078: cache_process (cache.c:322)
Address 0x4c7192b is not stack'd, malloc'd or (recently) free'd
Invalid write of size 1
at 0x4A0940E: strncpy (mc_replace_strmem.c:463)
by 0x408977: substr (parsing.c:61)
by 0x4089EF: parse_user (parsing.c:73)
by 0x408D10: cgit_parse_commit (parsing.c:153)
by 0x40A540: cgit_mk_refinfo (shared.c:171)
by 0x40A581: cgit_refs_cb (shared.c:181)
by 0x43DEB3: do_for_each_ref (refs.c:690)
by 0x41075E: cgit_print_branches (ui-refs.c:191)
by 0x416EF2: cgit_print_summary (ui-summary.c:56)
by 0x40780A: summary_fn (cmd.c:120)
by 0x40667A: process_request (cgit.c:544)
by 0x404078: cache_process (cache.c:322)
Address 0x4c7192d is not stack'd, malloc'd or (recently) free'd
Process terminating with default action of signal 11 (SIGSEGV)
Access not within mapped region at address 0x502F000
at 0x4A09400: strncpy (mc_replace_strmem.c:463)
by 0x408977: substr (parsing.c:61)
by 0x4089EF: parse_user (parsing.c:73)
by 0x408D10: cgit_parse_commit (parsing.c:153)
by 0x40A540: cgit_mk_refinfo (shared.c:171)
by 0x40A581: cgit_refs_cb (shared.c:181)
by 0x43DEB3: do_for_each_ref (refs.c:690)
by 0x41075E: cgit_print_branches (ui-refs.c:191)
by 0x416EF2: cgit_print_summary (ui-summary.c:56)
by 0x40780A: summary_fn (cmd.c:120)
by 0x40667A: process_request (cgit.c:544)
by 0x404078: cache_process (cache.c:322)
This happens when tail - head == -1 here:
(parsing.c)
char *parse_user(char *t, char **name, char **email, unsigned long *date)
{
char *p = t;
int mode = 1;
while (p && *p) {
if (mode == 1 && *p == '<') {
*name = substr(t, p - 1);
t = p;
mode++;
} else if (mode == 1 && *p == '\n') {
The fix is to handle the case of (tail < head) before calling xmalloc,
thus avoiding passing an invalid value to xmalloc.
And here's the reproducer:
It was tricky to reproduce, because git prohibits use of an empty "name"
in a commit ID. To construct the offending commit, I had to resort to
using "git hash-object".
git init -q foo &&
( cd foo &&
echo a > j && git add . && git ci -q --author='au <T at h.or>' -m. . &&
h=$(git cat-file commit HEAD|sed 's/au //' \
|git hash-object -t commit -w --stdin) &&
git co -q -b test $h &&
git br -q -D master &&
git br -q -m test master)
git clone -q --bare foo foo.git
AFAICS, this is not exploitable thanks (ironically) to the use of strncpy.
Since that -1 translates to SIZE_MAX and this is strncpy, not only does it
copy whatever is in "head" (up to first NUL), but it also writes
SIZE_MAX - strlen(head) NUL bytes into the destination buffer, and that
latter is guaranteed to evoke a segfault. Since cgit is single-threaded,
AFAICS, there is no way that the buffer clobbering can be turned into
an exploit.
ui-snapshot: pass -n to gzip, to suppress timestamp
Since cgit snapshots of tags are often used for releases, we don't
want the rarely used feature of the gzip compressor that includes
an embedded timestamp into the archive, since this makes each tarball
of the same (potentially signed) tag different.
This commit refactors the archive handling code a bit so that each
different format is able to run with an arbitrary argv for the filter.
ui-repolist: Case insensitive sorting and age sort
Add two options, one for doing the ordinary name sorts in a
case-insensitive manner, and another for choosing to sort repos in each
section by age instead of by name.
Jamie Couture [Thu, 12 Jan 2012 03:38:49 +0000 (22:38 -0500)]
use correct type for sizeof
**L would have worked well too. Depending on the distribution sizeof *L
may return 8 instead of 4. **L is preferable, but since we don't expect
this datatype to change very often, sizeof int is less subtle and easier
to understand.
John Keeping [Thu, 24 Nov 2011 11:54:47 +0000 (11:54 +0000)]
Fix segmentation fault in empty repository
When a repository is empty, the ATOM feed link is written in the header,
but this involves formatting ctx->qry.head which is NULL in this case.
With glibc, vsnprintf formats "%s" with a NULL input as "(null)" but on
Solaris this results in a segmentation fault. Since we don't have a
meaningful head for the atom feed in an empty repository, it's simplest
not to write out the link element at all.
Tim Chen [Tue, 3 Jan 2012 16:09:59 +0000 (16:09 +0000)]
ui-ssdiff.c: set correct diffmode in "control panel"
When side-by-side-diffs=1 was set in cgitrc, specifying 'ss=0' in the
querystring would not set the 'unified' option as active in the dropdown
box used to select diffmode.
Tim Chen [Tue, 3 Jan 2012 16:02:14 +0000 (16:02 +0000)]
Fix diff mode switching when side-by-side-diffs=1
When side-by-side-diffs=1 was set in cgitrc, specyfing 'ss=0' in the query-
string would not switch to unified diffs. This patch fixes the issue by
introducing a separate variable to track the occurrence of "ss" in the
querystring.
When the repolist is paged, the page-links are missing the sort parameter,
causing the initial page to be custom sorted, but any clicked page will
then be with the default sort order again.
Some setenv() implementations (e.g. the one in OpenBSD's stdlib)
segfault if we pass a NULL value. Only set environment variables if the
corresponding settings are defined to avoid this.
Note that this is a minor behaviour change as environment variables were
supposed to be set to an empty string if a setting was undefined. Given
that this feature isn't part of any official release yet, there's no
need to worry about backwards compatibility, really. Change the
documentation accordingly.
The file name displayed in the rename hint should be escaped to avoid
XSS. Note that this vulnerability is only applicable when an attacker
has gained push access to the repository.
Signed-off-by: Lukas Fleischer <cgit@cryptocrack.de> Signed-off-by: Lars Hjemli <hjemli@gmail.com>
Some tests would otherwise fail because commands such as
cd trash/repos/foo && git rev-list --reverse HEAD | head -1
would return 2 lines instead of 1: the 'cd' command also
prints the path when CDPATH is set.
Signed-off-by: Ferry Huberts <ferry.huberts@pelagic.nl> Signed-off-by: Lars Hjemli <hjemli@gmail.com>
Lars Hjemli [Tue, 19 Jul 2011 09:34:18 +0000 (09:34 +0000)]
ui-repolist.c: fallback to "master" if no default branch is specified
When looking for the modtime of a repo we used to rely on repo.defbranch
having a value. This is no longer true so this patch provides a default
value when needed.
ui_plain: automatically lookup mimetype when mimetype-file is set
For sites that do not want to configure mime types by hand but
still want the correct mime type for 'plain' blobs, configuring
a mime type file is made possible. This is handy since such a
file is normally already provided (at least on Linux systems).
Also, this reflects the gitweb option '$mimetypes_file'
Signed-off-by: Ferry Huberts <ferry.huberts@pelagic.nl> Signed-off-by: Lars Hjemli <hjemli@gmail.com>
Lars Hjemli [Mon, 20 Jun 2011 22:52:51 +0000 (22:52 +0000)]
cgit.c: use resolve_ref() to guess_defbranch()
The resolve_ref() function handles reading of git- and filesystem
symbolic links (including proper whitespace trimming) and packed refs.
There's no point in reimplementing this function in cgit.
Julius Plenz [Thu, 7 Apr 2011 10:59:24 +0000 (12:59 +0200)]
guess default branch from HEAD
This is a saner alternative than hardcoding the default branch to be
"master". The add_repo() function will now check for a symbolic ref in
repo_path/HEAD. If there is a suitable one, overwrite repo->defbranch
with it. Note that you'll need to strip the newline from the file (->
len-17).
If HEAD is a symbolic link pointing directly to a branch below
refs/heads/, do a readlink() instead to find the ref name.
Signed-off-by: Julius Plenz <plenz@cis.fu-berlin.de> Signed-off-by: Lars Hjemli <hjemli@gmail.com>
Lars Hjemli [Sat, 18 Jun 2011 12:32:43 +0000 (14:32 +0200)]
cgit.c: improve error message when git repo cannot be accessed
The current 'Not a git repository' error message is not very helpful,
since it doesn't state the cause of the problem.
This patch uses errno to provide a hint of the underlying problem. It
would have been even better to give the exact cause (e.g. for ENOENT it
would be nice to know which file/directory is missing), but that would
require reimplementing setup_git_directory_gently() which seems a bit
overkill.
Lars Hjemli [Wed, 15 Jun 2011 08:13:15 +0000 (10:13 +0200)]
Do not provide a default value for `module-link`
The old default value was an abomination which never should have been
allowed to see the light of day.
This patch removes the default, which is a backwards incompatible change
with low probability of causing anyone any real trouble (a repo with
submodules, displayed by cgit using the default value of `module-link`,
is very unlikely to actually generate working links).
Lars Hjemli [Wed, 15 Jun 2011 08:10:41 +0000 (10:10 +0200)]
ui-plain.c: add support for path-selected submodule links
In ui-plain.c, the links generated for submodule entry ignored the fact
that the entry was in fact a submodule. This patch adds proper submodule
links to the plain directory listings.
Lars Hjemli [Wed, 15 Jun 2011 08:04:13 +0000 (10:04 +0200)]
ui-tree.c: add support for path-selected submodule links
The current 'repo.module-link' option is sufficient when all gitlinks
in a repository can be converted to commit links in a uniform way, but
not when different submodules/paths needs different settings.
This patch adds support for 'repo.module-link.<path>', which will be
used for linking to submodules at paths matching one such entry.
Lars Hjemli [Mon, 6 Jun 2011 20:49:13 +0000 (20:49 +0000)]
cgit.c: add 'clone-url' setting with support for macro expansion
The current 'clone-prefix' setting has some known issues:
* All repos get the same 'clone-prefix' value since the setting is not
adopted during repo registration (in cgitrc, or during scan-path traversal),
but only when the setting is used.
* The generated clone-urls for a repo is a combination of 'clone-prefix', a
slash and the repo url. This doesn't work well with e.g. ssh-style urls
like 'git@example.org:repo.git', since the inserted slash will make the
repo relative to the filesystem root.
* If 'remove-suffix' is enabled, the generated clone-urls will not work for
cloning (except for http-urls to cgit itself) since they miss the '.git'
suffix.
The new 'clone-url' setting is designed to avoid the mentioned issues:
* Each repo adopts the default 'clone-url' when the repo is defined. This
allows different groups of repos to adopt different values.
* The clone-urls for a repo is generated by expanding environment variables
in a string template without inserting arbitrary characters, hence any
kind of clone-url can be generated.
* Macro expansion also eases the 'remove-suffix' pain since it's now
possible to define e.g. 'clone-url=git://foo.org/$CGIT_REPO_URL.git' for
a set of repos. A furter improvement would be to define e.g.
$CGIT_REPO_SUFFIX to '.git' for all repos which had their url prettified,
or to store the original $CGIT_REPO_URL in e.g. $CGIT_REPO_REAL_URL before
suffix removal.
Reviewed-by: Ferry Huberts <mailings@hupie.com> Signed-off-by: Lars Hjemli <hjemli@gmail.com>
When cgit learned to setup environment variables for certain repo
settings before invoking a filter process, the setup occurred inside
cgit_open_filter().
This patch moves the setup out of cgit_open_filter() and into
prepare_repo_cmd() to prepare for additional uses of these variables.
Reviewed-by: Ferry Huberts <mailings@hupie.com> Signed-off-by: Lars Hjemli <hjemli@gmail.com>
Lars Hjemli [Mon, 13 Jun 2011 22:34:13 +0000 (22:34 +0000)]
cgitrc.5.txt: reformat the "FILTER API" section
This patch makes the generated man-page for the filer api section more
similar to the other sections. Also, the bulleted list of environment
variables wasn't rendered correctly (with asciidoc 8.5.2), without an
empty line before the first item.
Lars Hjemli [Sun, 12 Jun 2011 20:49:35 +0000 (20:49 +0000)]
ui-plain.c: fix html and links generated by print_dir() and print_dir_entry()
This patch fixes the following issues:
* the base argument usually isn't zero-terminated, so printing base
without considering baselen will usually generate random garbage
* when the current url represents a directory but doesn't end in a slash,
relative urls would be incorrect
* using unescaped paths allows XSS
Lukas Fleischer [Tue, 24 May 2011 18:38:40 +0000 (20:38 +0200)]
Properly escape ampersands inside HTML attributes
Ampersands ("&") appearing inside HTML attributes need to be translated
to "&". Otherwise, invalid XHTML will be generated at various
places, such as at tree views containing links to submodules.
Signed-off-by: Lukas Fleischer <cgit@cryptocrack.de> Signed-off-by: Lars Hjemli <hjemli@gmail.com>