diff options
-rw-r--r-- | src/Makefile.am | 18 | ||||
-rw-r--r-- | src/directive.c | 342 | ||||
-rw-r--r-- | src/diskio.c | 268 | ||||
-rw-r--r-- | src/gpg.c | 31 | ||||
-rw-r--r-- | src/process.c | 2 | ||||
-rw-r--r-- | src/sql.c | 11 | ||||
-rw-r--r-- | src/triplet.c | 9 | ||||
-rw-r--r-- | src/verify.c | 96 | ||||
-rw-r--r-- | src/wydawca.h | 38 |
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, ®->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; +} + @@ -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 @@ -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); |