aboutsummaryrefslogtreecommitdiff
path: root/src/config.c
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2007-08-23 16:17:47 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2007-08-23 16:17:47 +0000
commit766d41f8bf91a6d209c66e8fd12dbd6688ce2739 (patch)
tree12552a0788d42ac73e7260b883aa84a8045e957a /src/config.c
parentc7e791e9563b7805fc7a375bc7e616b4252a9c57 (diff)
downloadwydawca-766d41f8bf91a6d209c66e8fd12dbd6688ce2739.tar.gz
wydawca-766d41f8bf91a6d209c66e8fd12dbd6688ce2739.tar.bz2
Improve safety checks; implement symlink/rmsymlink/archive directives; Fix directive signature verification.
git-svn-id: file:///svnroot/wydawca/trunk@286 6bb4bd81-ecc2-4fd4-a2d4-9571d19c0d33
Diffstat (limited to 'src/config.c')
-rw-r--r--src/config.c54
1 files changed, 44 insertions, 10 deletions
diff --git a/src/config.c b/src/config.c
index ae7c974..8c4afd1 100644
--- a/src/config.c
+++ b/src/config.c
@@ -1,4 +1,4 @@
-/* wydawca - FTP release synchronisation daemon
+/* wydawca - FTP release synchronization daemon
Copyright (C) 2007 Sergey Poznyakoff
This program is free software; you can redistribute it and/or modify it
@@ -26,6 +26,8 @@ static struct access_method default_gpg_key_method;
#define skip_ws(s) while (*(s) && isspace (*(s))) (s)++;
#define skip_word(s) while (*(s) && !isspace (*(s))) (s)++;
+/* Return a pointer to the next word from *PSTR. Advanse *PSTR to the beginning
+ of next word, or to the terminating \0, whichever comes first. */
static char *
get_word (char **pstr)
{
@@ -49,6 +51,8 @@ get_word (char **pstr)
return word;
}
+/* Convert a boolean from STR into its C representation. If STR is a valid
+ boolean, store the result in *PVAL and return 0. Otherwise, return 1 */
static int
get_bool (char *str, int *pval)
{
@@ -77,6 +81,7 @@ get_bool (char *str, int *pval)
/home/user/../smith --> /home/smith
/home/user/../.. --> /
+ ../file --> NULL
*/
char *
safe_file_name (char *file_name)
@@ -96,32 +101,49 @@ safe_file_name (char *file_name)
/* delete trailing delimiter if any */
if (len && file_name[len-1] == '/')
file_name[len-1] = 0;
-
- /* Eliminate any /../ */
+
+ /* Eliminate any ./ and /../ */
for (p = strchr (file_name, '.'); p; p = strchr (p, '.'))
{
- if (p > file_name && p[-1] == '/')
+ if (p[1] == '/' && (p == file_name || p[-1] == '/'))
{
- if (p[1] == '.' && (p[2] == 0 || p[2] == '/'))
+ char *q, *s;
+
+ s = p + 2;
+ q = p;
+ while ((*q++ = *s++))
+ ;
+ continue;
+ }
+ else if (p[1] == '.' && (p[2] == 0 || p[2] == '/'))
+ {
+ if (p == file_name)
+ return NULL;
+ if (p[-1] == '/')
/* found */
{
char *q, *s;
+ s = p + 2;
+
/* Find previous delimiter */
for (q = p-2; *q != '/' && q >= file_name; q--)
;
if (q < file_name)
- break;
+ {
+ q = file_name;
+ s++;
+ }
+
/* Copy stuff */
- s = p + 2;
p = q;
while ((*q++ = *s++))
;
continue;
}
}
-
+
p++;
}
@@ -134,10 +156,15 @@ safe_file_name (char *file_name)
return file_name;
}
+/* Same as safe_file_name, but returns an allocated copy. */
char *
safe_file_name_alloc (const char *file_name)
{
- return safe_file_name (xstrdup (file_name));
+ char *s = xstrdup (file_name);
+ char *ns = safe_file_name (s);
+ if (!ns)
+ free (s);
+ return ns;
}
@@ -329,6 +356,13 @@ cfg_archive (gsc_config_file_t *file, char *kw, char *val, void *data)
return;
}
dp->archive.name = safe_file_name (xstrdup (word));
+ if (!dp->archive.name)
+ {
+ file->error_msg (file->file_name, file->line,
+ "invalid archive name: %s", word);
+ file->error_count++;
+ return;
+ }
word = get_word (&val);
@@ -544,7 +578,7 @@ cfg_tar_program (gsc_config_file_t *file, char *kw, char *val, void *unused)
{
char *word = safe_file_name (get_word (&val));
- if (word[0] != '/')
+ if (!word || word[0] != '/')
{
file->error_msg (file->file_name, file->line,
"must be an absolute file name");

Return to:

Send suggestions and report system problems to the System administrator.