aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2009-02-26 00:50:24 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2009-02-26 00:50:24 +0200
commit81640ab2b9ad954d4952aed43a70d7874da1c463 (patch)
tree8160066cb7259357f17a40121f7ed7d0fff5701e /src
parent9ec721b2a3a023f6339fe3c910635e477e4a311f (diff)
downloadwydawca-81640ab2b9ad954d4952aed43a70d7874da1c463.tar.gz
wydawca-81640ab2b9ad954d4952aed43a70d7874da1c463.tar.bz2
Switch to non-privileged UID/GID before startup.
* src/userprivs.c: New file. * src/Makefile.am (wydawca_SOURCES): Add userprivs.c * src/config.c (cb_access_method_params): Add missing gl_list_iterator_free. (cb_user, cb_supp_groups): New callbacks. (wydawca_kw): New keywords: user and group. * src/wydawca.c (wydawca_uid, wydawca_gid) (wydawca_supp_groupc, wydawca_supp_groups): New variables. (wydawca_set_uid, wydawca_set_gid, wydawca_set_privs) (wydawca_set_triplet_privs, wydawca_set_root_privs): Remove. (main): --dry-run implies --cron. Switch to non-privileged UID/GID before startup. * src/wydawca.h (wydawca_uid, wydawca_gid) (wydawca_supp_groupc, wydawca_supp_groups): New declarations. * src/mail.c (do_notify): Duplicate admin_address, it gets freed in do_notify. * src/directive.c, src/diskio.c, src/lock.c, src/triplet.c: Update.
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am1
-rw-r--r--src/config.c82
-rw-r--r--src/directive.c2
-rw-r--r--src/diskio.c68
-rw-r--r--src/lock.c2
-rw-r--r--src/mail.c2
-rw-r--r--src/triplet.c4
-rw-r--r--src/userprivs.c118
-rw-r--r--src/wydawca.c90
-rw-r--r--src/wydawca.h14
10 files changed, 259 insertions, 124 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index c91669e..993ce0d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -33,12 +33,13 @@ wydawca_SOURCES=\
pidfile.c\
process.c\
sql.c\
sql.h\
tcpwrap.c\
triplet.c\
+ userprivs.c\
verify.c\
wydawca.c\
wydawca.h\
mail.h\
mail.c\
vtab.c\
diff --git a/src/config.c b/src/config.c
index b1f339f..b6e2533 100644
--- a/src/config.c
+++ b/src/config.c
@@ -975,12 +975,13 @@ cb_access_method_params (enum gconf_callback_command cmd,
if (assert_string_arg (locus, cmd, vp))
break;
meth->parmv[i] = xstrdup (vp->v.string);
}
+ gl_list_iterator_free (&itr);
meth->parmv[i] = NULL;
}
return 0;
}
static struct gconf_keyword access_method_kw[] = {
@@ -1221,12 +1222,88 @@ cb_spool (enum gconf_callback_command cmd,
gconf_error (locus, 0, _("invalid use of block statement"));
}
return 0;
}
+static int
+cb_user (enum gconf_callback_command cmd,
+ gconf_locus_t *locus,
+ void *varptr,
+ gconf_value_t *value,
+ void *cb_data)
+{
+ int rc;
+ struct passwd *pw;
+
+ if (assert_string_arg (locus, cmd, value))
+ return 1;
+
+ pw = getpwnam (value->v.string);
+ if (!pw)
+ {
+ gconf_error (locus, 0, _("no such user: %s"), value->v.string);
+ return 1;
+ }
+
+ wydawca_uid = pw->pw_uid;
+ wydawca_gid = pw->pw_gid;
+ return 0;
+}
+
+static int
+cb_supp_groups (enum gconf_callback_command cmd,
+ gconf_locus_t *locus,
+ void *varptr,
+ gconf_value_t *value,
+ void *cb_data)
+{
+ if (cmd != gconf_callback_set_value)
+ {
+ gconf_error (locus, 0, _("Unexpected block statement"));
+ return 1;
+ }
+ if (!value || value->type != GCONF_TYPE_LIST)
+ {
+ gconf_error (locus, 0, _("expected list value"));
+ return 1;
+ }
+
+ wydawca_supp_groupc = gl_list_size (value->v.list);
+ if (wydawca_supp_groupc == 0)
+ wydawca_supp_groups = NULL;
+ else
+ {
+ int i;
+ gl_list_iterator_t itr;
+ const void *p;
+
+ wydawca_supp_groups = xcalloc (wydawca_supp_groupc,
+ sizeof (wydawca_supp_groups[0]));
+ itr = gl_list_iterator (value->v.list);
+ for (i = 0; gl_list_iterator_next (&itr, &p, NULL); i++)
+ {
+ const gconf_value_t *vp = p;
+ struct group *grp;
+
+ if (assert_string_arg (locus, cmd, vp))
+ break;
+ grp = getgrnam (vp->v.string);
+ if (!grp)
+ {
+ gconf_error (locus, 0, _("no such group: %s"), value->v.string);
+ break;
+ }
+ wydawca_supp_groups[i] = grp->gr_gid;
+ }
+ gl_list_iterator_free (&itr);
+ }
+ return 0;
+}
+
+
static struct gconf_keyword wydawca_kw[] = {
{ "daemon", NULL, N_("Enable daemon mode"),
gconf_type_bool, &daemon_mode },
{ "foreground", NULL, N_("Start in foreground even in daemon mode"),
gconf_type_bool, &foreground },
@@ -1234,12 +1311,17 @@ static struct gconf_keyword wydawca_kw[] = {
gconf_type_bool, &single_process },
{ "wakeup-interval", N_("time"), N_("Set wake-up interval"),
gconf_type_string, &wakeup_interval, 0, cb_interval },
{ "pidfile", N_("file"), N_("Set pid file name"),
gconf_type_string, &pidfile },
+ { "user", N_("name"), N_("Run with UID and GID of this user"),
+ gconf_type_string, NULL, 0, cb_user },
+ { "group", NULL, N_("Retain these supplementary groups"),
+ gconf_type_string|GCONF_LIST, NULL, 0, cb_supp_groups },
+
{ "locking", NULL, N_("Enable or disable locking"),
gconf_type_bool, &enable_locking },
{ "lockdir", N_("dir"), N_("Set directory for lock files"),
gconf_type_string, &lockdir },
{ "lock-expire-time", N_("interval"), N_("Define lock expiration interval"),
gconf_type_string, &lock_expire_time, 0, cb_interval },
diff --git a/src/directive.c b/src/directive.c
index 2915fee..416095f 100644
--- a/src/directive.c
+++ b/src/directive.c
@@ -334,15 +334,13 @@ process_directives (struct file_triplet *trp, const struct spool *spool)
trp->file[file_directive].name, val);
return 1;
}
break;
case filename_dir:
- wydawca_set_root_privs ();
rc = verify_detached_signature (trp, spool);
- wydawca_set_triplet_privs (trp);
if (rc == 0)
{
if (move_file (trp, spool, file_dist, relative_dir)
|| move_file (trp, spool, file_signature, relative_dir))
return 1;
}
diff --git a/src/diskio.c b/src/diskio.c
index fbd1050..35ba71e 100644
--- a/src/diskio.c
+++ b/src/diskio.c
@@ -55,15 +55,15 @@ concat_dir (const char *base, const char *name, size_t *pbaselen)
if (pbaselen)
*pbaselen = len;
return dir;
}
/* Create the directory DIR, eventually creating all intermediate directories
- starting from DIR + BASELEN, with owner UID and GID. */
+ starting from DIR + BASELEN. */
int
-create_hierarchy (char *dir, size_t baselen, uid_t uid, gid_t gid)
+create_hierarchy (char *dir, size_t baselen)
{
int rc;
struct stat st;
char *p;
if (stat (dir, &st) == 0)
@@ -89,60 +89,51 @@ create_hierarchy (char *dir, size_t baselen, uid_t uid, gid_t gid)
logmsg (LOG_ERR, _("base directory %s does not exist"), dir);
return 1;
}
*p = 0;
}
- rc = create_hierarchy (dir, baselen, uid, gid);
+ rc = create_hierarchy (dir, baselen);
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;
}
/* Create a directory BASE/NAME (with eventual intermediate directories in
NAME). Use UID and GID as owner ids.
Do nothing if dry_run_mode is set. */
char *
-create_directory (const char *base, const char *name, uid_t uid, gid_t gid)
+create_directory (const char *base, const char *name)
{
size_t baselen;
char *dir = concat_dir (base, name, &baselen);
if (!dry_run_mode)
{
- int rc;
- wydawca_set_root_privs ();
- rc = create_hierarchy (dir, baselen, uid, gid);
- wydawca_set_privs (uid, gid);
- if (rc)
+ if (create_hierarchy (dir, baselen))
{
free (dir);
dir = NULL;
}
}
return dir;
}
-/* Copy FILE to DST_FILE, creating the latter with owner UID and GID. */
+/* Copy FILE to DST_FILE. */
int
-copy_file (const char *file, const char *dst_file, uid_t uid, gid_t gid)
+copy_file (const char *file, const char *dst_file)
{
int in_fd, out_fd;
struct stat st;
int rc;
char *buf;
size_t bufsize;
@@ -220,24 +211,23 @@ copy_file (const char *file, const char *dst_file, uid_t uid, gid_t gid)
if (rc)
unlink (dst_file);
return rc;
}
/* Move FILE to DST_FILE. If they reside on different devices, use copy_file
- + unlink.
- UID and GID give DST_FILE ownership. */
+ + unlink. */
int
-do_move_file (const char *file, const char *dst_file, uid_t uid, gid_t gid)
+do_move_file (const char *file, const char *dst_file)
{
int rc = 0;
if (rename (file, dst_file))
{
if (errno == EXDEV)
{
- if (copy_file (file, dst_file, uid, gid))
+ if (copy_file (file, dst_file))
{
logmsg (LOG_CRIT, _("cannot copy %s to %s: %s"),
file, dst_file, strerror (errno));
rc = 1;
}
else if (unlink (file))
@@ -296,29 +286,28 @@ tar_append_file (const char *archive, const char *file)
/* Backup a file to a directory.
Arguments:
DST_FILE - File nam to back up.
DST_DIR - Directory part of DST_FILE.
FILE - File part of DST_FILE; can contain subdirs.
ARCHIVE - Archive descriptor.
- UID, GID - Ownership
RELDIR - Directory part of FILE
Do nothing if dry_run_mode is set. */
int
backup_file (const char *dst_file, const char *dst_dir, const char *file,
- const struct archive_descr *archive, uid_t uid, gid_t gid,
+ const struct archive_descr *archive,
const char *reldir)
{
int rc = 0;
char *adir;
char *file_name;
if (archive->name[0] == '/')
- adir = create_directory (archive->name, reldir, uid, gid);
+ adir = create_directory (archive->name, reldir);
else
- adir = create_directory (dst_dir, archive->name, uid, gid);
+ adir = create_directory (dst_dir, archive->name);
if (!adir)
return 1;
file_name = concat_dir (adir, file, NULL);
if (access (file_name, F_OK) == 0)
{
@@ -344,13 +333,13 @@ backup_file (const char *dst_file, const char *dst_dir, const char *file,
if (debug_level)
logmsg (LOG_DEBUG,
_("backing up previous archive file `%s' to `%s'"),
file_name, archive_file_name);
if (!dry_run_mode)
{
- rc = do_move_file (file_name, archive_file_name, uid, gid);
+ rc = do_move_file (file_name, archive_file_name);
if (rc)
{
logmsg (LOG_ERR, _("backing `%s' up as `%s' failed: %s"),
file_name, archive_file_name, strerror (errno));
free (archive_file_name);
free (file_name);
@@ -363,13 +352,13 @@ backup_file (const char *dst_file, const char *dst_dir, const char *file,
}
if (debug_level)
logmsg (LOG_DEBUG, _("archiving `%s' to `%s'"), dst_file, file_name);
if (!dry_run_mode)
{
- rc = do_move_file (dst_file, file_name, uid, gid);
+ rc = do_move_file (dst_file, file_name);
if (rc)
logmsg (LOG_ERR, _("archiving `%s' as `%s' failed: %s"),
dst_file, file_name, strerror (errno));
}
free (file_name);
free (adir);
@@ -377,22 +366,22 @@ backup_file (const char *dst_file, const char *dst_dir, const char *file,
}
/* Select the appropriate backup type and backup a file. See backup_file
for the argument description. */
int
do_archive_file (const char *dst_file, const char *dst_dir, const char *file,
- const struct archive_descr *archive, uid_t uid, gid_t gid,
+ const struct archive_descr *archive,
const char *reldir)
{
switch (archive->type)
{
case archive_none:
break;
case archive_directory:
- return backup_file (dst_file, dst_dir, file, archive, uid, gid, reldir);
+ return backup_file (dst_file, dst_dir, file, archive, reldir);
case archive_tar:
if (tar_append_file (archive->name, dst_file))
return 1;
}
if (!dry_run_mode && unlink (dst_file))
@@ -412,31 +401,28 @@ do_archive_file (const char *dst_file, const char *dst_dir, const char *file,
int
dir_move_file (struct file_triplet *trp, const struct spool *spool,
enum file_type file_id, const char *reldir)
{
char *dst_file;
int rc = 0;
- char *dst_dir = create_directory (spool->dest_dir, reldir,
- TRIPLET_UID (trp), TRIPLET_GID (trp));
+ char *dst_dir = create_directory (spool->dest_dir, reldir);
if (!dst_dir)
return 1;
dst_file = concat_dir (dst_dir, trp->file[file_id].name, NULL);
if (debug_level)
logmsg (LOG_DEBUG, _("installing %s to %s"), trp->file[file_id].name,
dst_dir);
if (access (dst_file, F_OK) == 0)
rc = do_archive_file (dst_file, dst_dir, trp->file[file_id].name,
- &spool->archive,
- TRIPLET_UID (trp), TRIPLET_GID (trp), reldir);
+ &spool->archive, reldir);
if (!dry_run_mode && rc == 0)
- rc = do_move_file (trp->file[file_id].name, dst_file,
- TRIPLET_UID (trp), TRIPLET_GID (trp));
+ rc = do_move_file (trp->file[file_id].name, dst_file);
free (dst_file);
free (dst_dir);
if (rc == 0)
UPDATE_STATS (STAT_UPLOADS);
return rc;
@@ -450,14 +436,13 @@ int
archive_single_file (struct file_triplet *trp, const struct spool *spool,
const char *file_name, const char *reldir,
int noentok)
{
char *dst_file;
int rc = 0;
- char *dst_dir = create_directory (spool->dest_dir, reldir,
- TRIPLET_UID (trp), TRIPLET_GID (trp));
+ char *dst_dir = create_directory (spool->dest_dir, reldir);
if (!dst_dir)
return 1;
dst_file = safe_file_name (concat_dir (dst_dir, file_name, NULL));
if (!sub_dir_p (dst_file, spool->dest_dir))
@@ -471,13 +456,13 @@ archive_single_file (struct file_triplet *trp, const struct spool *spool,
if (access (dst_file, F_OK) == 0)
{
if (debug_level)
logmsg (LOG_DEBUG, _("archiving file `%s'"), dst_file);
rc = do_archive_file (dst_file, dst_dir, file_name, &spool->archive,
- TRIPLET_UID (trp), TRIPLET_GID (trp), reldir);
+ reldir);
if (rc == 0)
UPDATE_STATS (STAT_ARCHIVES);
}
else if (errno == ENOENT)
{
if (!noentok)
@@ -540,14 +525,13 @@ int
dir_symlink_file (struct file_triplet *trp, const struct spool *spool,
const char *reldir,
const char *wanted_src, const char *wanted_dst)
{
int rc = 0;
struct saved_cwd cwd;
- char *dst_dir = create_directory (spool->dest_dir, reldir,
- TRIPLET_UID (trp), TRIPLET_GID (trp));
+ char *dst_dir = create_directory (spool->dest_dir, reldir);
char *src, *dst;
if (!dst_dir)
return 1;
if (save_cwd (&cwd))
@@ -585,14 +569,13 @@ dir_symlink_file (struct file_triplet *trp, const struct spool *spool,
char *p = strrchr (dst, '/');
if (p > dst)
{
char *dir;
*p = 0;
- dir = create_directory (spool->dest_dir, dst,
- TRIPLET_UID (trp), TRIPLET_GID (trp));
+ dir = create_directory (spool->dest_dir, dst);
if (!dir)
rc = 1;
else
free (dir);
*p = '/';
}
@@ -700,14 +683,13 @@ int
dir_rmsymlink_file (struct file_triplet *trp, const struct spool *spool,
const char *reldir, const char *file_name)
{
char *dst_file;
int rc = 0;
char *signame;
- char *dst_dir = create_directory (spool->dest_dir, reldir,
- TRIPLET_UID (trp), TRIPLET_GID (trp));
+ char *dst_dir = create_directory (spool->dest_dir, reldir);
if (!dst_dir)
return 1;
dst_file = safe_file_name (concat_dir (dst_dir, file_name, NULL));
if (!sub_dir_p (dst_file, spool->dest_dir))
diff --git a/src/lock.c b/src/lock.c
index d94731c..3b8787d 100644
--- a/src/lock.c
+++ b/src/lock.c
@@ -230,10 +230,10 @@ void
wydawca_lock_init ()
{
if (enable_locking)
{
if (!lockdir)
lockdir = xstrdup (LOCALSTATEDIR "/lock/" PACKAGE);
- if (create_hierarchy (lockdir, 0, getuid (), getgid ()))
+ if (create_hierarchy (lockdir, 0))
exit (EX_OSFILE);
}
}
diff --git a/src/mail.c b/src/mail.c
index ea74b8c..ba77f49 100644
--- a/src/mail.c
+++ b/src/mail.c
@@ -332,13 +332,13 @@ do_notify (struct file_triplet *trp, enum notification_event ev,
{
mu_address_t rcpt = NULL;
char *errp;
switch (ntf->tgt)
{
case notify_admin:
- rcpt = admin_address;
+ rcpt = mu_address_dup (admin_address);
break;
case notify_user:
rcpt = get_recipient (trp->spool->access_method[user_data_method],
trp, &errp);
break;
diff --git a/src/triplet.c b/src/triplet.c
index 614e2b5..e060089 100644
--- a/src/triplet.c
+++ b/src/triplet.c
@@ -196,17 +196,13 @@ triplet_processor (void *data, void *proc_data)
switch (check_triplet_state (trp))
{
case triplet_directive:
case triplet_complete:
if (debug_level)
logmsg (LOG_DEBUG, _("processing triplet `%s'"), trp->name);
- if (wydawca_set_triplet_privs (trp) == 0)
- {
process_directives (trp, spool);
- wydawca_set_root_privs ();
- }
return true;
case triplet_incomplete:
if (debug_level)
logmsg (LOG_DEBUG, _("%s: incomplete triplet"), trp->name);
/* ignore unless expired (see below); */
diff --git a/src/userprivs.c b/src/userprivs.c
new file mode 100644
index 0000000..e6a18c8
--- /dev/null
+++ b/src/userprivs.c
@@ -0,0 +1,118 @@
+/* wydawca - automatic release submission daemon
+ Copyright (C) 2007, 2009 Sergey Poznyakoff
+
+ Wydawca 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.
+
+ Wydawca 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 wydawca. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "wydawca.h"
+
+int
+wydawca_userprivs (uid_t uid, gid_t gid, gid_t *grplist, size_t ngrp)
+{
+ int rc = 0;
+ size_t size = 1, j = 1;
+
+ if (uid == 0)
+ return 0;
+
+ /* Reset group permissions */
+ if (geteuid () == 0 && setgroups (ngrp, grplist))
+ {
+ logmsg (LOG_CRIT, "setgroups(%lu, %lu...): %s",
+ ngrp, grplist[0], 0, strerror (errno));
+ return rc;
+ }
+
+ /* Switch to the user's gid. On some OSes the effective gid must
+ be reset first */
+
+#if defined(HAVE_SETEGID)
+ if ((rc = setegid (gid)) < 0)
+ logmsg (LOG_CRIT, "setegid(%lu): %s", gid, strerror (errno));
+#elif defined(HAVE_SETREGID)
+ if ((rc = setregid (gid, gid)) < 0)
+ logmsg (LOG_CRIT, "setregid(%lu,%lu)d: %s",
+ (unsigned long) gid, (unsigned long) gid, strerror (errno));
+#elif defined(HAVE_SETRESGID)
+ if ((rc = setresgid (gid, gid, gid)) < 0)
+ logmsg (LOG_CRIT, "setresgid(%lu,%lu,%lu): %s",
+ (unsigned long) gid, (unsigned long) gid,
+ (unsigned long) gid,
+ strerror (errno));
+#endif
+
+ if (rc == 0 && gid != 0)
+ {
+ if ((rc = setgid (gid)) < 0 && getegid () != gid)
+ logmsg (LOG_CRIT, "setgid(%lu): %s",
+ (unsigned long) gid, strerror (errno));
+ if (rc == 0 && getegid () != gid)
+ {
+ logmsg (LOG_CRIT, _("cannot set effective gid to %lu"),
+ (unsigned long) gid);
+ rc = 1;
+ }
+ }
+
+ /* Now reset uid */
+ if (rc == 0 && uid != 0)
+ {
+ uid_t euid;
+
+ if (setuid (uid)
+ || geteuid () != uid
+ || (getuid () != uid
+ && (geteuid () == 0 || getuid () == 0)))
+ {
+
+#if defined(HAVE_SETREUID)
+ if (geteuid () != uid)
+ {
+ if (setreuid (uid, -1) < 0)
+ {
+ logmsg (LOG_CRIT, "setreuid(%lu,-1): %s",
+ (unsigned long) uid, strerror (errno));
+ rc = 1;
+ }
+ if (setuid (uid) < 0)
+ {
+ logmsg (LOG_CRIT, "setreuid(%lu,-1): %s",
+ (unsigned long) uid, strerror (errno));
+ rc = 1;
+ }
+ }
+ else
+#endif
+ {
+ logmsg (LOG_CRIT, "setuid(%lu): %s",
+ (unsigned long) uid, strerror (errno));
+ rc = 1;
+ }
+ }
+
+ euid = geteuid ();
+ if (uid != 0 && setuid (0) == 0)
+ {
+ logmsg (LOG_CRIT, _("seteuid(0) succeeded when it should not"));
+ rc = 1;
+ }
+ else if (uid != euid && setuid (euid) == 0)
+ {
+ logmsg (LOG_CRIT, _("cannot drop non-root setuid privileges"));
+ rc = 1;
+ }
+
+ }
+
+ return rc;
+}
diff --git a/src/wydawca.c b/src/wydawca.c
index 48c27e9..f02ac99 100644
--- a/src/wydawca.c
+++ b/src/wydawca.c
@@ -16,12 +16,16 @@
#include "wydawca.h"
#include "mail.h"
#include "argmatch.h"
#include "version-etc.h"
+uid_t wydawca_uid;
+gid_t wydawca_gid;
+size_t wydawca_supp_groupc;
+gid_t *wydawca_supp_groups;
char *conffile = SYSCONFDIR "/wydawca.rc" ;
int debug_level;
int dry_run_mode;
int log_to_stderr = -1; /* -1 means autodetect */
int log_facility = LOG_LOCAL1;
char *syslog_tag = "wydawca";
@@ -262,79 +266,12 @@ collect_uids (int argc, char **argv)
else
uidv[i] = pw->pw_uid;
}
}
-static int
-wydawca_set_uid (uid_t uid)
-{
- int rc;
-
- if (getuid () != 0)
- return 0;
-#if defined(HAVE_SETREUID)
- rc = setreuid (0, uid);
-#elif defined(HAVE_SETRESUID)
- rc = setresuid (-1, uid, -1);
-#elif defined(HAVE_SETEUID)
- rc = seteuid (uid);
-#else
-# error "No way to reset user privileges?"
-#endif
- if (rc < 0)
- logmsg (LOG_ERR, _("cannot switch to UID %d: %s (r=%d, e=%d)"),
- uid, strerror (errno), getuid (), geteuid ());
- return rc;
-}
-
-static int
-wydawca_set_gid (gid_t gid)
-{
- int rc;
-
- if (getuid () != 0)
- return 0;
-#if defined(HAVE_SETREGID)
- rc = setregid (0, gid);
-#elif defined(HAVE_SETRESGID)
- rc = setresgid (-1, gid, -1);
-#elif defined(HAVE_SETEGID)
- rc = setegid (gid);
-#else
-# error "No way to reset user privileges?"
-#endif
- if (rc < 0)
- logmsg (LOG_ERR, _("cannot switch to GID %d: %s (r=%d, e=%d)"),
- gid, strerror (errno), getgid (), getegid ());
- return rc;
-}
-
-int
-wydawca_set_privs (uid_t uid, gid_t gid)
-{
- if (wydawca_set_gid (gid))
- return -1;
- if (wydawca_set_uid (uid))
- return -1;
- return 0;
-}
-
-int
-wydawca_set_triplet_privs (struct file_triplet *trp)
-{
- return wydawca_set_privs (TRIPLET_UID (trp), TRIPLET_GID (trp));
-}
-
-int
-wydawca_set_root_privs ()
-{
- return wydawca_set_privs (0, 0);
-}
-
-
char **x_argv;
extern int reconfigure;
void
wydawca_daemon ()
{
@@ -374,12 +311,14 @@ main (int argc, char **argv)
if (gconf_parse (conffile))
exit (EX_CONFIG);
if (lint_mode)
exit (0);
+ if (dry_run_mode)
+ cron_option = 1;
if (cron_option)
daemon_mode = 0;
if (foreground_option >= 0)
foreground = foreground_option;
if (single_process_option >= 0)
single_process = single_process_option;
@@ -391,12 +330,28 @@ main (int argc, char **argv)
if (!log_to_stderr)
{
openlog (syslog_tag, LOG_PID, log_facility);
log_printer = syslog_printer;
}
+ if (getgid () == 0)
+ {
+ if (wydawca_uid == 0)
+ {
+ if (!force_startup)
+ {
+ logmsg (LOG_CRIT, _("won't run with root privileges"));
+ exit (EX_UNAVAILABLE);
+ }
+ }
+ else if (wydawca_userprivs (wydawca_uid, wydawca_gid,
+ wydawca_supp_groups,
+ wydawca_supp_groupc))
+ exit (EX_UNAVAILABLE);
+ }
+
mail_init ();
wydawca_lock_init ();
logmsg (LOG_NOTICE, _("wydawca (%s) started"), PACKAGE_STRING);
if (!daemon_mode)
@@ -411,13 +366,12 @@ main (int argc, char **argv)
mail_finish ();
if (reconfigure)
{
int i;
- wydawca_set_uid (0);
for (i = getdtablesize (); i > 2; i--)
close (i);
remove_pidfile ();
execv (x_argv[0], x_argv);
}
diff --git a/src/wydawca.h b/src/wydawca.h
index f786271..81e6509 100644
--- a/src/wydawca.h
+++ b/src/wydawca.h
@@ -300,12 +300,16 @@ void meta_escape (struct access_method *method, void *handle,
void meta_free (struct metadef *def);
void make_default_meta (struct metadef kwexp[5], const char *user,
const char *project);
/* Global variables */
+extern uid_t wydawca_uid;
+extern gid_t wydawca_gid;
+extern size_t wydawca_supp_groupc;
+extern gid_t *wydawca_supp_groups;
extern char *conffile; /* Configuration file name */
extern int debug_level; /* Debugging level */
extern int dry_run_mode; /* Dry run indicator */
extern int log_to_stderr; /* Log to stderr instead of the syslog */
extern int log_facility; /* Syslog facility to use if !log_to_stderr */
extern char *syslog_tag; /* Syslog tag */
@@ -352,14 +356,14 @@ void logstats (void);
char *safe_file_name (char *file_name);
char *safe_file_name_alloc (const char *file_name);
size_t trim_length (const char *str);
size_t trim (char *str);
void logmsg (int prio, char *fmt, ...) GSC_PRINTFLIKE(2,3);
int test_dir (const char *name, int *ec);
-char *create_directory (const char *base, const char *name,
- uid_t uid, gid_t gid);
+char *create_directory (const char *base, const char *name);
+int create_hierarchy (char *dir, size_t baselen);
void parse_config (void);
void log_output (int prio, const char *prog, FILE *fp);
enum exec_result
{
exec_success, /* Command executed and returned 0 */
@@ -425,15 +429,12 @@ int directive_next (struct file_triplet *trp, int n,
const char **pkey, const char **pval);
int process_directives (struct file_triplet *trp,
const struct spool *spool);
int enabled_spool_p (const struct spool *spool);
-int wydawca_set_privs (uid_t uid, gid_t gid);
-int wydawca_set_triplet_privs (struct file_triplet *trp);
-int wydawca_set_root_privs (void);
int parse_time_interval (const char *str, time_t *pint, const char **endp);
/* config.c */
@@ -535,6 +536,9 @@ void wydawca_unlock (const char *lockname);
void wydawca_lock_init (void);
/* tcpwrap.h */
extern struct gconf_keyword tcpwrapper_kw[];
int tcpwrap_access(int fd);
+
+/* userprivs.c */
+int wydawca_userprivs (uid_t uid, gid_t gid, gid_t *grplist, size_t ngrp);

Return to:

Send suggestions and report system problems to the System administrator.