aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Makefile.am18
-rw-r--r--src/directive.c342
-rw-r--r--src/diskio.c268
-rw-r--r--src/gpg.c31
-rw-r--r--src/process.c2
-rw-r--r--src/sql.c11
-rw-r--r--src/triplet.c9
-rw-r--r--src/verify.c96
-rw-r--r--src/wydawca.h38
9 files changed, 766 insertions, 49 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 7d8c00e..c93b9bd 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,8 +1,26 @@
+# This file is part of GSC
+# Copyright (C) 2007 Sergey Poznyakoff
+#
+# GSC is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GSC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GSC. If not, see <http://www.gnu.org/licenses/>.
+
sbin_PROGRAMS=@MODULE_WYDAWCA@
EXTRA_PROGRAMS=wydawca
wydawca_SOURCES=\
config.c\
+ directive.c\
gpg.c\
+ diskio.c\
method.c\
process.c\
sql.c\
diff --git a/src/directive.c b/src/directive.c
new file mode 100644
index 0000000..9551e9a
--- /dev/null
+++ b/src/directive.c
@@ -0,0 +1,342 @@
+/* wydawca - FTP release synchronisation daemon
+ Copyright (C) 2007 Sergey Poznyakoff
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "wydawca.h"
+
+/* Directive file support */
+
+int
+directive_parse (struct file_register *reg)
+{
+ size_t dcount, i;
+ char *p;
+
+ if (debug_level > 2)
+ logmsg (LOG_DEBUG, "%s: parsing directive blurb: %s",
+ reg->file[file_directive].name, reg->blurb);
+
+ dcount = 0;
+ for (p = reg->blurb; *p; p++)
+ if (*p == '\n')
+ dcount++;
+
+ reg->directive = xcalloc (dcount + 1, sizeof reg->directive[0]);
+ p = reg->blurb;
+ for (i = 0; i < dcount; )
+ {
+ reg->directive[i] = p;
+ p = strchr (p, '\n');
+ if (p)
+ *p++ = 0;
+ if (trim (reg->directive[i]) == 0) /* ignore empty lines */
+ continue;
+ if (strchr (reg->directive[i], ':') == NULL)
+ {
+ logmsg (LOG_ERR, "%s: invalid line: %s",
+ reg->file[file_directive].name, reg->directive[i]);
+ free (reg->directive);
+ reg->directive = NULL;
+ return 1;
+ }
+ i++;
+ if (!p)
+ break;
+ }
+ reg->directive[i] = NULL;
+ return 0;
+}
+
+int
+directive_get_value (struct file_register *reg, const char *key,
+ const char **pval)
+{
+ int keylen = strlen (key);
+ int i;
+
+ for (i = 0; reg->directive[i]; i++)
+ {
+ char *str = reg->directive[i];
+ int len = strlen (str);
+ if (len > keylen && memcmp (str, key, keylen) == 0 && str[keylen] == ':')
+ {
+ str += keylen + 1;
+ while (*str && isspace (*str))
+ str++;
+ if (pval)
+ *pval = str;
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static int
+_directive_seq_get (int n, struct file_register *reg,
+ const char **pkey, const char **pval)
+{
+ char *p;
+ size_t len;
+
+ if (reg->directive[n] == NULL)
+ return 0;
+
+ p = strchr (reg->directive[n], ':');
+ len = p - reg->directive[n];
+ if (len + 1 > reg->tmpsize)
+ {
+ reg->tmpsize = len + 1;
+ reg->tmp = x2realloc (reg->tmp, &reg->tmpsize);
+ }
+ memcpy (reg->tmp, reg->directive[n], len);
+ reg->tmp[len] = 0;
+ *pkey = reg->tmp;
+ for (p++; *p && isspace (*p); p++)
+ ;
+ if (pval)
+ *pval = p;
+ return ++n;
+}
+
+int
+directive_first (struct file_register *reg,
+ const char **pkey, const char **pval)
+{
+ int n = 0;
+ return _directive_seq_get (n, reg, pkey, pval);
+}
+
+int
+directive_next (struct file_register *reg, int n,
+ const char **pkey, const char **pval)
+{
+ return _directive_seq_get (n, reg, pkey, pval);
+}
+
+int
+directive_pack_version (const char *val, unsigned *pversion)
+{
+ char *p;
+ unsigned v;
+
+ v = strtoul (val, &p, 10);
+ if (*p != '.')
+ return 1;
+ p++;
+ v *= 100;
+ v += strtoul (p, &p, 10);
+ if (*p && *p != '.')
+ return 1;
+ *pversion = v;
+ return 0;
+}
+
+int
+directive_version_in_range_p (struct file_register *reg,
+ unsigned from, unsigned to)
+{
+ const char *val;
+ int version;
+
+ if (directive_get_value (reg, "version", &val))
+ {
+ logmsg (LOG_ERR, "%s: missing `version' directive",
+ reg->file[file_directive].name);
+ return 0;
+ }
+
+ if (directive_pack_version (val, &version))
+ {
+ logmsg (LOG_ERR, "%s: unparsable version: %s",
+ reg->file[file_directive].name, val);
+ return 0;
+ }
+
+ if (from <= version && version <= to)
+ return 1;
+
+ logmsg (LOG_ERR, "%s: version %s is not in the allowed range",
+ reg->file[file_directive].name, val);
+ return 0;
+}
+
+enum directive
+ {
+ unknown_dir,
+ comment_dir,
+ directory_dir,
+ version_dir,
+ filename_dir,
+ rmsymlink_dir,
+ archive_dir,
+ symlink_dir
+ };
+
+struct directive_table
+{
+ const char *name;
+ enum directive dir;
+};
+
+static struct directive_table directive_table[] = {
+ { "comment", comment_dir },
+ { "directory", directory_dir },
+ { "version", version_dir },
+ { "filename", filename_dir },
+ { "symlink", symlink_dir },
+ { "rmsymlink", rmsymlink_dir },
+ { "archive", archive_dir },
+ { NULL }
+};
+
+static enum directive
+find_directive (const char *key)
+{
+ int i;
+
+ for (i = 0; directive_table[i].name; i++)
+ if (strcmp (directive_table[i].name, key) == 0)
+ return directive_table[i].dir;
+ return unknown_dir;
+}
+
+int
+verify_directive_format (struct file_register *reg)
+{
+ int n, dnum;
+ const char *key;
+
+ if (!directive_version_in_range_p (reg, MIN_DIRECTIVE_VERSION,
+ MAX_DIRECTIVE_VERSION))
+ return 1;
+
+ dnum = 0;
+ for (n = directive_first (reg, &key, NULL); n;
+ n = directive_next (reg, n, &key, NULL))
+ {
+ if (strcmp (key, "comment") == 0)
+ continue;
+ dnum++;
+ switch (dnum)
+ {
+ case 1:
+ if (strcmp (key, "version"))
+ {
+ logmsg (LOG_ERR, "%s:%d: expected `%s' but found `%s'",
+ reg->file[file_directive].name, n, "version", key);
+ return 1;
+ }
+ break;
+
+ case 2:
+ if (strcmp (key, "directory"))
+ {
+ logmsg (LOG_ERR, "%s:%d: expected `%s' but found `%s'",
+ reg->file[file_directive].name, n, "directory", key);
+ return 1;
+ }
+ break;
+
+ default:
+ if (find_directive (key) == unknown_dir)
+ {
+ logmsg (LOG_ERR, "%s:%d: unknown directive `%s'",
+ reg->file[file_directive].name, n, key);
+ return 1;
+ }
+ }
+ }
+
+ if (reg->file[file_dist].name && reg->file[file_signature].name)
+ {
+ const char *filename;
+ if (directive_get_value (reg, "filename", &filename))
+ {
+ logmsg (LOG_ERR, "%s: missing `filename' directive",
+ reg->file[file_directive].name);
+ return 1;
+ }
+ if (strcmp (filename, reg->file[file_dist].name))
+ {
+ logmsg (LOG_ERR, "%s: filename %s does not match actual name",
+ reg->file[file_dist].name, filename);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int
+process_directives (struct file_register *reg, struct directory_pair *dpair)
+{
+ int n;
+ const char *key, *val;
+ char *directory = NULL;
+
+ for (n = directive_first (reg, &key, &val); n;
+ n = directive_next (reg, n, &key, &val))
+ {
+ enum directive d = find_directive (key);
+ switch (d)
+ {
+ case unknown_dir:
+ /* should not happen */
+ abort ();
+
+ case comment_dir:
+ logmsg (LOG_NOTICE, "%s: COMMENT: %s",
+ reg->file[file_directive].name, val);
+ break;
+
+ case directory_dir:
+ directory = create_directory (dpair->dest_dir, val,
+ reg->file[file_dist].uid,
+ reg->gid);
+ if (!directory)
+ return 1;
+ break;
+
+ case filename_dir:
+ if (move_file (reg->file[file_dist].name, directory,
+ reg->file[file_dist].uid,
+ reg->gid)
+ || move_file (reg->file[file_signature].name, directory,
+ reg->file[file_dist].uid,
+ reg->gid))
+ return 1;
+ break;
+
+ case version_dir:
+ /* Already processed */
+ break;
+
+ case rmsymlink_dir:
+ case archive_dir:
+ case symlink_dir:
+ logmsg (LOG_CRIT, "%s: %s directive is not supported yet",
+ reg->file[file_directive].name, key);
+ }
+ }
+
+ free (directory);
+
+ if (!dry_run_mode && unlink (reg->file[file_directive].name))
+ {
+ logmsg (LOG_CRIT, "%s: cannot unlink directive file: %s",
+ reg->file[file_directive].name, strerror (errno));
+ }
+
+ return 0;
+}
diff --git a/src/diskio.c b/src/diskio.c
new file mode 100644
index 0000000..13694da
--- /dev/null
+++ b/src/diskio.c
@@ -0,0 +1,268 @@
+/* wydawca - FTP release synchronisation daemon
+ Copyright (C) 2007 Sergey Poznyakoff
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "wydawca.h"
+#if defined USE_SENDFILE
+# if defined __linux__ && defined HAVE_SYS_SENDFILE_H
+# include <sys/sendfile.h>
+# else
+# undef USE_SENDFILE
+# endif
+#endif
+
+char *
+concat_dir (const char *base, const char *name, size_t *pbaselen)
+{
+ size_t len = strlen (base);
+ size_t size;
+ char *dir;
+
+ while (len > 0 && base[len-1] == '/')
+ len--;
+
+ size = len + 1 + strlen (name);
+ dir = xmalloc (size + 1);
+ memcpy (dir, base, len);
+ dir[len++] = '/';
+ strcpy (dir + len, name);
+
+ if (pbaselen)
+ *pbaselen = len;
+ return dir;
+}
+
+int
+create_hierarchy (char *dir, size_t baselen, uid_t uid, gid_t gid)
+{
+ int rc;
+ struct stat st;
+ char *p;
+
+ if (stat (dir, &st) == 0)
+ {
+ if (!S_ISDIR (st.st_mode))
+ {
+ logmsg (LOG_ERR, "component %s is not a directory", dir);
+ return 1;
+ }
+ return 0;
+ }
+ else if (errno != ENOENT)
+ {
+ logmsg (LOG_ERR, "cannot stat file %s: %s", dir, strerror (errno));
+ return 1;
+ }
+
+ p = strrchr (dir, '/');
+ if (p)
+ {
+ if (p - dir + 1 < baselen)
+ {
+ logmsg (LOG_ERR, "base directory %s does not exist", dir);
+ return 1;
+ }
+ *p = 0;
+ }
+
+ rc = create_hierarchy (dir, baselen, uid, gid);
+ if (rc == 0)
+ {
+ if (p)
+ *p = '/';
+ if (mkdir (dir, MKDIR_PERMISSIONS))
+ {
+ logmsg (LOG_ERR, "cannot create directory %s: %s",
+ dir, strerror (errno));
+ rc = 1;
+ }
+ if (chown (dir, uid, gid))
+ {
+ logmsg (LOG_NOTICE, "cannot change ownership of %s: %s",
+ dir, strerror (errno));
+ }
+ }
+ return rc;
+}
+
+char *
+create_directory (const char *base, const char *name, uid_t uid, gid_t gid)
+{
+ size_t baselen;
+ char *dir = concat_dir (base, name, &baselen);
+
+ if (!dry_run_mode && create_hierarchy (dir, baselen, uid, gid))
+ {
+ free (dir);
+ dir = NULL;
+ }
+ return dir;
+}
+
+int
+copy_file (const char *file, const char *dst_file, uid_t uid, gid_t gid)
+{
+ int in_fd, out_fd;
+ struct stat st;
+ int rc = 1;
+
+ in_fd = open (file, O_RDONLY);
+
+ if (in_fd == -1)
+ {
+ logmsg (LOG_ERR, "cannot open source file %s for reading: %s",
+ file, strerror (errno));
+ return 1;
+ }
+
+ if (fstat (in_fd, &st))
+ {
+ logmsg (LOG_ERR, "cannot stat source file %s: %s",
+ file, strerror (errno));
+ close (in_fd);
+ return 1;
+ }
+
+ out_fd = creat (dst_file, CREAT_PERMISSIONS);
+ if (out_fd == -1)
+ {
+ logmsg (LOG_ERR, "cannot create destination file %s: %s",
+ file, strerror (errno));
+ close (in_fd);
+ return 1;
+ }
+
+#ifdef USE_SENDFILE
+ {
+ off_t offset = 0;
+ ssize_t count;
+
+ count = sendfile (out_fd, in_fd, &offset, st.st_size);
+ if (count == -1)
+ {
+ rc = 1;
+ logmsg (LOG_ERR, "copying %s to %s failed: %s",
+ file, dst_file, strerror (errno));
+ }
+ else if (count < st.st_size)
+ {
+ rc = 1;
+ logmsg (LOG_ERR, "copying %s to %s failed: short write",
+ file, dst_file);
+ unlink (dst_file);
+ }
+ else
+ rc = 0;
+ }
+#else
+ {
+ char *buf = NULL;
+ size_t bufsize;
+ size_t fsize = st.st_size;
+
+ for (bufsize = fsize; bufsize > 0 && (buf = malloc (bufsize)) == NULL;
+ bufsize /= 2)
+ ;
+ if (bufsize == 0)
+ xalloc_die ();
+
+ rc = 0;
+ while (fsize > 0)
+ {
+ size_t rest;
+ size_t rdbytes;
+
+ rest = fsize > bufsize ? bufsize : fsize;
+ rdbytes = read (in_fd, buf, rest);
+ if (rdbytes == -1)
+ {
+ logmsg (LOG_ERR, "unexpected error reading %s: %s",
+ file, strerror (errno));
+ unlink (dst_file);
+ rc = 1;
+ break;
+ }
+ rest = write (out_fd, buf, rdbytes);
+ if (rest == -1)
+ {
+ logmsg (LOG_ERR, "unexpected error writing to %s: %s",
+ dst_file, strerror (errno));
+ unlink (dst_file);
+ rc = 1;
+ break;
+ }
+ else if (rest != rdbytes)
+ {
+ logmsg (LOG_ERR, "short write on %s", dst_file);
+ unlink (dst_file);
+ rc = 1;
+ }
+ fsize -= rdbytes;
+ }
+ free (buf);
+ }
+#endif
+ close (in_fd);
+ close (out_fd);
+ return rc;
+}
+
+int
+do_move_file (const char *file, const char *dst_file, uid_t uid, gid_t gid)
+{
+ int rc = 0;
+
+ if (rename (file, dst_file))
+ {
+ if (errno == EXDEV)
+ {
+ if (copy_file (file, dst_file, uid, gid))
+ {
+ logmsg (LOG_CRIT, "cannot copy %s to %s: %s",
+ file, dst_file, strerror (errno));
+ rc = 1;
+ }
+ else if (unlink (file))
+ {
+ logmsg (LOG_ERR, "cannot unlink %s: %s",
+ file, strerror (errno));
+ }
+ }
+ else
+ {
+ logmsg (LOG_CRIT, "cannot move %s to %s: %s",
+ file, dst_file, strerror (errno));
+ rc = 1;
+ }
+ }
+ return rc;
+}
+
+int
+move_file (const char *file, const char *dst_dir, uid_t uid, gid_t gid)
+{
+ char *dst_file = concat_dir (dst_dir, file, NULL);
+ int rc = 0;
+
+ if (debug_level)
+ logmsg (LOG_DEBUG, "installing %s to %s", file, dst_dir);
+
+ if (!dry_run_mode)
+ rc = do_move_file (file, dst_file, uid, gid);
+
+ free (dst_file);
+ return rc;
+}
+
diff --git a/src/gpg.c b/src/gpg.c
index a722b4e..a327f4c 100644
--- a/src/gpg.c
+++ b/src/gpg.c
@@ -126,7 +126,7 @@ int
wydawca_gpg_homedir ()
{
if (homedir)
- return;
+ return 0;
homedir = xstrdup ("/tmp/wydawca-XXXXXX");
if (!mkdtemp (homedir))
@@ -139,6 +139,7 @@ wydawca_gpg_homedir ()
if (debug_level > 1)
logmsg (LOG_DEBUG, "GNUPG home directory: %s", homedir);
setenv ("GNUPGHOME", homedir, 1);
+ return 0;
}
/* FIXME: dpair currently unused */
@@ -164,34 +165,14 @@ verify_directive_signature (struct file_register *reg,
ec = gpgme_op_verify (ctx, directive_data, NULL, plain);
if (ec == GPG_ERR_NO_ERROR)
{
- size_t dcount, i;
- char *p;
-
- rc = 0;
-
size = gpgme_data_seek (plain, 0, SEEK_END);
gpgme_data_seek (plain, 0, SEEK_SET);
reg->blurb = xmalloc (size + 1);
gpgme_data_read (plain, reg->blurb, size);
reg->blurb[size] = 0;
gpgme_data_release (plain);
-
- dcount = 1;
- for (p = reg->blurb; *p; p++)
- if (*p == '\n')
- dcount++;
-
- reg->directive = xcalloc (dcount, sizeof reg->directive[0]);
- p = reg->blurb;
- for (i = 0; i < dcount; i++)
- {
- reg->directive[i] = p;
- p = strchr (p, '\n');
- if (!p)
- break;
- *p++ = 0;
- }
- reg->directive[i] = NULL;
+
+ rc = directive_parse (reg);
}
else
{
@@ -269,7 +250,6 @@ verify_detached_signature (struct file_register *reg,
struct directory_pair *dpair)
{
gpgme_engine_info_t info;
- const char *gpg_prog;
char *argv[5];
FILE *fp;
pid_t pid, npid;
@@ -331,9 +311,6 @@ verify_detached_signature (struct file_register *reg,
rc = WEXITSTATUS (status);
if (rc)
{
- size_t size = 0;
- char *buf = NULL;
-
logmsg (LOG_ERR, "bad detached signature for %s", reg->name);
log_output (LOG_ERR, argv[0], fp);
/* FIXME: email? */
diff --git a/src/process.c b/src/process.c
index afb985d..575874a 100644
--- a/src/process.c
+++ b/src/process.c
@@ -66,7 +66,7 @@ file_type_str (enum file_type type)
#define SUF_SIG ".sig"
#define SUF_DIR ".directive.asc"
-int
+void
parse_file_name (const char *name, struct file_info *finfo)
{
static struct suffix
diff --git a/src/sql.c b/src/sql.c
index 2ceb724..5e3bae5 100644
--- a/src/sql.c
+++ b/src/sql.c
@@ -82,17 +82,6 @@ sql_done_method (struct access_method *method)
return 0;
}
-/* Return the length of the string without trailing whitespace */
-static size_t
-trim_length (const char *str)
-{
- size_t len;
-
- for (len = strlen (str); len > 0 && isspace (str[len-1]); len--)
- ;
- return len;
-}
-
int
sql_run_method (struct access_method *method, const char *query)
{
diff --git a/src/triplet.c b/src/triplet.c
index 220a765..b2a64b7 100644
--- a/src/triplet.c
+++ b/src/triplet.c
@@ -122,7 +122,7 @@ static bool
triplet_processor (void *data, void *proc_data)
{
struct file_register *reg = data;
- const struct directory_pair *dpair = proc_data;
+ struct directory_pair *dpair = proc_data;
if (debug_level)
logmsg (LOG_DEBUG, "FILE %s, DIST=%s, SIG=%s, DIRECTIVE=%s",
@@ -136,7 +136,8 @@ triplet_processor (void *data, void *proc_data)
if (debug_level)
logmsg (LOG_DEBUG, "Processing triplet `%s'", reg->name);
if (verify_triplet (reg, dpair) == 0)
- /*FIXME install_triplet (reg, dpair)*/;
+ process_directives (reg, dpair);
+ /* FIXME: if only directive file exists? */
else
remove_triplet (reg);
}
@@ -147,9 +148,9 @@ triplet_processor (void *data, void *proc_data)
}
void
-enumerate_triplets (const struct directory_pair *dpair)
+enumerate_triplets (struct directory_pair *dpair)
{
if (debug_level)
logmsg (LOG_DEBUG, "Processing files for %s", dpair->dest_dir);
- hash_do_for_each (file_table, triplet_processor, (void*)dpair);
+ hash_do_for_each (file_table, triplet_processor, dpair);
}
diff --git a/src/verify.c b/src/verify.c
index 9a3aff8..a47eaee 100644
--- a/src/verify.c
+++ b/src/verify.c
@@ -17,6 +17,27 @@
#include "wydawca.h"
#include "sql.h"
+/* Return the length of the string without trailing whitespace */
+size_t
+trim_length (const char *str)
+{
+ size_t len;
+
+ for (len = strlen (str); len > 0 && isspace (str[len-1]); len--)
+ ;
+ return len;
+}
+
+/* Chop off any trailing whitespace. Return the length of the resulting string.
+ */
+size_t
+trim (char *str)
+{
+ size_t len = trim_length (str);
+ str[len] = 0;
+ return len;
+}
+
static size_t
quote_string (struct access_method *method, const char *input, char **poutput)
{
@@ -52,7 +73,7 @@ quote_string (struct access_method *method, const char *input, char **poutput)
return size;
}
-static char *
+char *
expand_param (const char *param, const char *user, const char *project,
struct access_method *method)
{
@@ -135,16 +156,74 @@ expand_param (const char *param, const char *user, const char *project,
return res;
}
+
+
+int
+check_access_rights (struct file_register *reg, struct directory_pair *dpair,
+ const char *user)
+{
+ struct access_method *method = &dpair->verify_method;
+ char *project;
+ const char *directory;
+ char *p;
+ int rc;
+ char *command;
+ const char *result;
+
+ if (directive_get_value (reg, "directory", &directory))
+ {
+ logmsg (LOG_ERR, "%s: missing `directory' directive",
+ reg->file[file_directive].name);
+ return 1;
+ }
+ p = strchr (directory, '/');
+ if (p)
+ {
+ size_t len = p - directory;
+ project = xmalloc (len + 1);
+ memcpy (project, directory, len);
+ project[len] = 0;
+ }
+ else
+ project = xstrdup (directory);
+
+ if (debug_level)
+ logmsg (LOG_DEBUG, "verifying access rights for user %s to project %s",
+ user, project);
+
+ command = expand_param (method->param[1], user, project, method);
+ rc = method_run (method, command);
+ free (command);
+ if (rc)
+ {
+ logmsg (LOG_ERR, "Cannot verify access rights for %s on %s",
+ user, project);
+ free (project);
+ return 1;
+ }
+
+ result = method_result (method);
+ if (strcmp (result, user))
+ {
+ logmsg (LOG_ERR, "%s: %s has no rights on %s",
+ reg->name, user, project);
+ free (project);
+ return 1;
+ }
+ free (project);
+
+ return 0;
+}
int
verify_triplet (struct file_register *reg, struct directory_pair *dpair)
{
struct passwd *pw = getpwuid (reg->file[file_dist].uid);
char *user_name;
- char *project_name;
char *command;
struct access_method *method = &dpair->gpg_key_method;
const char *pubkey;
+ int rc;
if (!pw)
{
@@ -154,13 +233,16 @@ verify_triplet (struct file_register *reg, struct directory_pair *dpair)
}
reg->gid = pw->pw_gid;
user_name = pw->pw_name;
+
command = expand_param (method->param[1], user_name, NULL, method);
- if (method_run (method, command))
+ rc = method_run (method, command);
+ free (command);
+ if (rc)
{
logmsg (LOG_ERR, "Cannot get PGP key for %s", user_name);
return 1;
}
-
+
pubkey = method_result (method);
if (pubkey[0] == 0)
{
@@ -184,6 +266,12 @@ verify_triplet (struct file_register *reg, struct directory_pair *dpair)
logmsg (LOG_DEBUG, "directive[%d] = %s", i, reg->directive[i]);
}
+ if (verify_directive_format (reg))
+ return 1;
+
+ if (check_access_rights (reg, dpair, user_name))
+ return 1;
+
if (verify_detached_signature (reg, dpair))
{
logmsg (LOG_ERR, "invalid detached signature for %s", reg->name);
diff --git a/src/wydawca.h b/src/wydawca.h
index b579206..7da2243 100644
--- a/src/wydawca.h
+++ b/src/wydawca.h
@@ -25,17 +25,24 @@
#include <getopt.h>
#include <errno.h>
#include <string.h>
+#include <ctype.h>
#include <pwd.h>
#include <grp.h>
#include <signal.h>
#include <limits.h>
#include <dirent.h>
#include <sys/stat.h>
+#include <fcntl.h>
#include "error.h"
#include "xalloc.h"
#include "progname.h"
#include "gsc.h"
+#define MIN_DIRECTIVE_VERSION 101
+#define MAX_DIRECTIVE_VERSION 101
+
+#define MKDIR_PERMISSIONS 0777
+#define CREAT_PERMISSIONS 0666
enum access_method_type
{
method_none,
@@ -92,6 +99,8 @@ struct file_register
struct file_info file[FILE_TYPE_COUNT];
char **directive;
char *blurb;
+ char *tmp;
+ size_t tmpsize;
};
void register_directory_pair (struct directory_pair *dpair);
@@ -105,11 +114,11 @@ extern char *syslog_tag;
extern int unlink_invalid_files;
extern time_t file_sweep_time;
-
+void logmsg (int prio, char *fmt, ...) GSC_PRINTFLIKE(2,3);
void scan_directories (void);
int test_dir (const char *name, int *ec);
void register_file (struct file_info *finfo);
-void enumerate_triplets (const struct directory_pair *);
+void enumerate_triplets (struct directory_pair *);
void parse_config (void);
@@ -120,8 +129,33 @@ const char *method_result (struct access_method *method);
void method_copy_result (struct access_method *method, const char *res,
size_t size);
+int verify_triplet (struct file_register *reg, struct directory_pair *dpair);
int verify_directive_signature (struct file_register *reg,
struct directory_pair *dpair,
const char *pubkey);
int verify_detached_signature (struct file_register *reg,
struct directory_pair *dpair);
+
+size_t trim_length (const char *str);
+size_t trim (char *str);
+
+int directive_parse (struct file_register *reg);
+int directive_get_value (struct file_register *reg, const char *key,
+ const char **pval);
+int directive_pack_version (const char *val, unsigned *pversion);
+int directive_version_in_range_p (struct file_register *reg,
+ unsigned from, unsigned to);
+int verify_directive_format (struct file_register *reg);
+
+
+int directive_first (struct file_register *reg,
+ const char **pkey, const char **pval);
+int directive_next (struct file_register *reg, int n,
+ const char **pkey, const char **pval);
+int process_directives (struct file_register *reg,
+ struct directory_pair *dpair);
+
+char *create_directory (const char *base, const char *name,
+ uid_t uid, gid_t gid);
+
+int move_file (const char *file, const char *dst_dir, uid_t uid, gid_t gid);

Return to:

Send suggestions and report system problems to the System administrator.