aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
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.c6
-rw-r--r--src/userprivs.c118
-rw-r--r--src/wydawca.c90
-rw-r--r--src/wydawca.h14
10 files changed, 260 insertions, 125 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index c91669e..993ce0d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -36,6 +36,7 @@ wydawca_SOURCES=\
36 sql.h\ 36 sql.h\
37 tcpwrap.c\ 37 tcpwrap.c\
38 triplet.c\ 38 triplet.c\
39 userprivs.c\
39 verify.c\ 40 verify.c\
40 wydawca.c\ 41 wydawca.c\
41 wydawca.h\ 42 wydawca.h\
diff --git a/src/config.c b/src/config.c
index b1f339f..b6e2533 100644
--- a/src/config.c
+++ b/src/config.c
@@ -978,6 +978,7 @@ cb_access_method_params (enum gconf_callback_command cmd,
978 978
979 meth->parmv[i] = xstrdup (vp->v.string); 979 meth->parmv[i] = xstrdup (vp->v.string);
980 } 980 }
981 gl_list_iterator_free (&itr);
981 meth->parmv[i] = NULL; 982 meth->parmv[i] = NULL;
982 } 983 }
983 return 0; 984 return 0;
@@ -1224,6 +1225,82 @@ cb_spool (enum gconf_callback_command cmd,
1224} 1225}
1225 1226
1226 1227
1228static int
1229cb_user (enum gconf_callback_command cmd,
1230 gconf_locus_t *locus,
1231 void *varptr,
1232 gconf_value_t *value,
1233 void *cb_data)
1234{
1235 int rc;
1236 struct passwd *pw;
1237
1238 if (assert_string_arg (locus, cmd, value))
1239 return 1;
1240
1241 pw = getpwnam (value->v.string);
1242 if (!pw)
1243 {
1244 gconf_error (locus, 0, _("no such user: %s"), value->v.string);
1245 return 1;
1246 }
1247
1248 wydawca_uid = pw->pw_uid;
1249 wydawca_gid = pw->pw_gid;
1250 return 0;
1251}
1252
1253static int
1254cb_supp_groups (enum gconf_callback_command cmd,
1255 gconf_locus_t *locus,
1256 void *varptr,
1257 gconf_value_t *value,
1258 void *cb_data)
1259{
1260 if (cmd != gconf_callback_set_value)
1261 {
1262 gconf_error (locus, 0, _("Unexpected block statement"));
1263 return 1;
1264 }
1265 if (!value || value->type != GCONF_TYPE_LIST)
1266 {
1267 gconf_error (locus, 0, _("expected list value"));
1268 return 1;
1269 }
1270
1271 wydawca_supp_groupc = gl_list_size (value->v.list);
1272 if (wydawca_supp_groupc == 0)
1273 wydawca_supp_groups = NULL;
1274 else
1275 {
1276 int i;
1277 gl_list_iterator_t itr;
1278 const void *p;
1279
1280 wydawca_supp_groups = xcalloc (wydawca_supp_groupc,
1281 sizeof (wydawca_supp_groups[0]));
1282 itr = gl_list_iterator (value->v.list);
1283 for (i = 0; gl_list_iterator_next (&itr, &p, NULL); i++)
1284 {
1285 const gconf_value_t *vp = p;
1286 struct group *grp;
1287
1288 if (assert_string_arg (locus, cmd, vp))
1289 break;
1290 grp = getgrnam (vp->v.string);
1291 if (!grp)
1292 {
1293 gconf_error (locus, 0, _("no such group: %s"), value->v.string);
1294 break;
1295 }
1296 wydawca_supp_groups[i] = grp->gr_gid;
1297 }
1298 gl_list_iterator_free (&itr);
1299 }
1300 return 0;
1301}
1302
1303
1227 1304
1228static struct gconf_keyword wydawca_kw[] = { 1305static struct gconf_keyword wydawca_kw[] = {
1229 { "daemon", NULL, N_("Enable daemon mode"), 1306 { "daemon", NULL, N_("Enable daemon mode"),
@@ -1237,6 +1314,11 @@ static struct gconf_keyword wydawca_kw[] = {
1237 { "pidfile", N_("file"), N_("Set pid file name"), 1314 { "pidfile", N_("file"), N_("Set pid file name"),
1238 gconf_type_string, &pidfile }, 1315 gconf_type_string, &pidfile },
1239 1316
1317 { "user", N_("name"), N_("Run with UID and GID of this user"),
1318 gconf_type_string, NULL, 0, cb_user },
1319 { "group", NULL, N_("Retain these supplementary groups"),
1320 gconf_type_string|GCONF_LIST, NULL, 0, cb_supp_groups },
1321
1240 { "locking", NULL, N_("Enable or disable locking"), 1322 { "locking", NULL, N_("Enable or disable locking"),
1241 gconf_type_bool, &enable_locking }, 1323 gconf_type_bool, &enable_locking },
1242 { "lockdir", N_("dir"), N_("Set directory for lock files"), 1324 { "lockdir", N_("dir"), N_("Set directory for lock files"),
diff --git a/src/directive.c b/src/directive.c
index 2915fee..416095f 100644
--- a/src/directive.c
+++ b/src/directive.c
@@ -337,9 +337,7 @@ process_directives (struct file_triplet *trp, const struct spool *spool)
337 break; 337 break;
338 338
339 case filename_dir: 339 case filename_dir:
340 wydawca_set_root_privs ();
341 rc = verify_detached_signature (trp, spool); 340 rc = verify_detached_signature (trp, spool);
342 wydawca_set_triplet_privs (trp);
343 if (rc == 0) 341 if (rc == 0)
344 { 342 {
345 if (move_file (trp, spool, file_dist, relative_dir) 343 if (move_file (trp, spool, file_dist, relative_dir)
diff --git a/src/diskio.c b/src/diskio.c
index fbd1050..35ba71e 100644
--- a/src/diskio.c
+++ b/src/diskio.c
@@ -58,9 +58,9 @@ concat_dir (const char *base, const char *name, size_t *pbaselen)
58} 58}
59 59
60/* Create the directory DIR, eventually creating all intermediate directories 60/* Create the directory DIR, eventually creating all intermediate directories
61 starting from DIR + BASELEN, with owner UID and GID. */ 61 starting from DIR + BASELEN. */
62int 62int
63create_hierarchy (char *dir, size_t baselen, uid_t uid, gid_t gid) 63create_hierarchy (char *dir, size_t baselen)
64{ 64{
65 int rc; 65 int rc;
66 struct stat st; 66 struct stat st;
@@ -92,7 +92,7 @@ create_hierarchy (char *dir, size_t baselen, uid_t uid, gid_t gid)
92 *p = 0; 92 *p = 0;
93 } 93 }
94 94
95 rc = create_hierarchy (dir, baselen, uid, gid); 95 rc = create_hierarchy (dir, baselen);
96 if (rc == 0) 96 if (rc == 0)
97 { 97 {
98 if (p) 98 if (p)
@@ -103,11 +103,6 @@ create_hierarchy (char *dir, size_t baselen, uid_t uid, gid_t gid)
103 dir, strerror (errno)); 103 dir, strerror (errno));
104 rc = 1; 104 rc = 1;
105 } 105 }
106 if (chown (dir, uid, gid))
107 {
108 logmsg (LOG_NOTICE, _("cannot change ownership of %s: %s"),
109 dir, strerror (errno));
110 }
111 } 106 }
112 return rc; 107 return rc;
113} 108}
@@ -116,18 +111,14 @@ create_hierarchy (char *dir, size_t baselen, uid_t uid, gid_t gid)
116 NAME). Use UID and GID as owner ids. 111 NAME). Use UID and GID as owner ids.
117 Do nothing if dry_run_mode is set. */ 112 Do nothing if dry_run_mode is set. */
118char * 113char *
119create_directory (const char *base, const char *name, uid_t uid, gid_t gid) 114create_directory (const char *base, const char *name)
120{ 115{
121 size_t baselen; 116 size_t baselen;
122 char *dir = concat_dir (base, name, &baselen); 117 char *dir = concat_dir (base, name, &baselen);
123 118
124 if (!dry_run_mode) 119 if (!dry_run_mode)
125 { 120 {
126 int rc; 121 if (create_hierarchy (dir, baselen))
127 wydawca_set_root_privs ();
128 rc = create_hierarchy (dir, baselen, uid, gid);
129 wydawca_set_privs (uid, gid);
130 if (rc)
131 { 122 {
132 free (dir); 123 free (dir);
133 dir = NULL; 124 dir = NULL;
@@ -137,9 +128,9 @@ create_directory (const char *base, const char *name, uid_t uid, gid_t gid)
137} 128}
138 129
139 130
140/* Copy FILE to DST_FILE, creating the latter with owner UID and GID. */ 131/* Copy FILE to DST_FILE. */
141int 132int
142copy_file (const char *file, const char *dst_file, uid_t uid, gid_t gid) 133copy_file (const char *file, const char *dst_file)
143{ 134{
144 int in_fd, out_fd; 135 int in_fd, out_fd;
145 struct stat st; 136 struct stat st;
@@ -223,10 +214,9 @@ copy_file (const char *file, const char *dst_file, uid_t uid, gid_t gid)
223} 214}
224 215
225/* Move FILE to DST_FILE. If they reside on different devices, use copy_file 216/* Move FILE to DST_FILE. If they reside on different devices, use copy_file
226 + unlink. 217 + unlink. */
227 UID and GID give DST_FILE ownership. */
228int 218int
229do_move_file (const char *file, const char *dst_file, uid_t uid, gid_t gid) 219do_move_file (const char *file, const char *dst_file)
230{ 220{
231 int rc = 0; 221 int rc = 0;
232 222
@@ -234,7 +224,7 @@ do_move_file (const char *file, const char *dst_file, uid_t uid, gid_t gid)
234 { 224 {
235 if (errno == EXDEV) 225 if (errno == EXDEV)
236 { 226 {
237 if (copy_file (file, dst_file, uid, gid)) 227 if (copy_file (file, dst_file))
238 { 228 {
239 logmsg (LOG_CRIT, _("cannot copy %s to %s: %s"), 229 logmsg (LOG_CRIT, _("cannot copy %s to %s: %s"),
240 file, dst_file, strerror (errno)); 230 file, dst_file, strerror (errno));
@@ -299,13 +289,12 @@ tar_append_file (const char *archive, const char *file)
299 DST_DIR - Directory part of DST_FILE. 289 DST_DIR - Directory part of DST_FILE.
300 FILE - File part of DST_FILE; can contain subdirs. 290 FILE - File part of DST_FILE; can contain subdirs.
301 ARCHIVE - Archive descriptor. 291 ARCHIVE - Archive descriptor.
302 UID, GID - Ownership
303 RELDIR - Directory part of FILE 292 RELDIR - Directory part of FILE
304 293
305 Do nothing if dry_run_mode is set. */ 294 Do nothing if dry_run_mode is set. */
306int 295int
307backup_file (const char *dst_file, const char *dst_dir, const char *file, 296backup_file (const char *dst_file, const char *dst_dir, const char *file,
308 const struct archive_descr *archive, uid_t uid, gid_t gid, 297 const struct archive_descr *archive,
309 const char *reldir) 298 const char *reldir)
310{ 299{
311 int rc = 0; 300 int rc = 0;
@@ -313,9 +302,9 @@ backup_file (const char *dst_file, const char *dst_dir, const char *file,
313 char *file_name; 302 char *file_name;
314 303
315 if (archive->name[0] == '/') 304 if (archive->name[0] == '/')
316 adir = create_directory (archive->name, reldir, uid, gid); 305 adir = create_directory (archive->name, reldir);
317 else 306 else
318 adir = create_directory (dst_dir, archive->name, uid, gid); 307 adir = create_directory (dst_dir, archive->name);
319 if (!adir) 308 if (!adir)
320 return 1; 309 return 1;
321 310
@@ -347,7 +336,7 @@ backup_file (const char *dst_file, const char *dst_dir, const char *file,
347 file_name, archive_file_name); 336 file_name, archive_file_name);
348 if (!dry_run_mode) 337 if (!dry_run_mode)
349 { 338 {
350 rc = do_move_file (file_name, archive_file_name, uid, gid); 339 rc = do_move_file (file_name, archive_file_name);
351 if (rc) 340 if (rc)
352 { 341 {
353 logmsg (LOG_ERR, _("backing `%s' up as `%s' failed: %s"), 342 logmsg (LOG_ERR, _("backing `%s' up as `%s' failed: %s"),
@@ -366,7 +355,7 @@ backup_file (const char *dst_file, const char *dst_dir, const char *file,
366 logmsg (LOG_DEBUG, _("archiving `%s' to `%s'"), dst_file, file_name); 355 logmsg (LOG_DEBUG, _("archiving `%s' to `%s'"), dst_file, file_name);
367 if (!dry_run_mode) 356 if (!dry_run_mode)
368 { 357 {
369 rc = do_move_file (dst_file, file_name, uid, gid); 358 rc = do_move_file (dst_file, file_name);
370 if (rc) 359 if (rc)
371 logmsg (LOG_ERR, _("archiving `%s' as `%s' failed: %s"), 360 logmsg (LOG_ERR, _("archiving `%s' as `%s' failed: %s"),
372 dst_file, file_name, strerror (errno)); 361 dst_file, file_name, strerror (errno));
@@ -380,7 +369,7 @@ backup_file (const char *dst_file, const char *dst_dir, const char *file,
380 for the argument description. */ 369 for the argument description. */
381int 370int
382do_archive_file (const char *dst_file, const char *dst_dir, const char *file, 371do_archive_file (const char *dst_file, const char *dst_dir, const char *file,
383 const struct archive_descr *archive, uid_t uid, gid_t gid, 372 const struct archive_descr *archive,
384 const char *reldir) 373 const char *reldir)
385{ 374{
386 switch (archive->type) 375 switch (archive->type)
@@ -389,7 +378,7 @@ do_archive_file (const char *dst_file, const char *dst_dir, const char *file,
389 break; 378 break;
390 379
391 case archive_directory: 380 case archive_directory:
392 return backup_file (dst_file, dst_dir, file, archive, uid, gid, reldir); 381 return backup_file (dst_file, dst_dir, file, archive, reldir);
393 382
394 case archive_tar: 383 case archive_tar:
395 if (tar_append_file (archive->name, dst_file)) 384 if (tar_append_file (archive->name, dst_file))
@@ -415,8 +404,7 @@ dir_move_file (struct file_triplet *trp, const struct spool *spool,
415{ 404{
416 char *dst_file; 405 char *dst_file;
417 int rc = 0; 406 int rc = 0;
418 char *dst_dir = create_directory (spool->dest_dir, reldir, 407 char *dst_dir = create_directory (spool->dest_dir, reldir);
419 TRIPLET_UID (trp), TRIPLET_GID (trp));
420 408
421 if (!dst_dir) 409 if (!dst_dir)
422 return 1; 410 return 1;
@@ -428,12 +416,10 @@ dir_move_file (struct file_triplet *trp, const struct spool *spool,
428 416
429 if (access (dst_file, F_OK) == 0) 417 if (access (dst_file, F_OK) == 0)
430 rc = do_archive_file (dst_file, dst_dir, trp->file[file_id].name, 418 rc = do_archive_file (dst_file, dst_dir, trp->file[file_id].name,
431 &spool->archive, 419 &spool->archive, reldir);
432 TRIPLET_UID (trp), TRIPLET_GID (trp), reldir);
433 420
434 if (!dry_run_mode && rc == 0) 421 if (!dry_run_mode && rc == 0)
435 rc = do_move_file (trp->file[file_id].name, dst_file, 422 rc = do_move_file (trp->file[file_id].name, dst_file);
436 TRIPLET_UID (trp), TRIPLET_GID (trp));
437 423
438 free (dst_file); 424 free (dst_file);
439 free (dst_dir); 425 free (dst_dir);
@@ -453,8 +439,7 @@ archive_single_file (struct file_triplet *trp, const struct spool *spool,
453{ 439{
454 char *dst_file; 440 char *dst_file;
455 int rc = 0; 441 int rc = 0;
456 char *dst_dir = create_directory (spool->dest_dir, reldir, 442 char *dst_dir = create_directory (spool->dest_dir, reldir);
457 TRIPLET_UID (trp), TRIPLET_GID (trp));
458 443
459 if (!dst_dir) 444 if (!dst_dir)
460 return 1; 445 return 1;
@@ -474,7 +459,7 @@ archive_single_file (struct file_triplet *trp, const struct spool *spool,
474 if (debug_level) 459 if (debug_level)
475 logmsg (LOG_DEBUG, _("archiving file `%s'"), dst_file); 460 logmsg (LOG_DEBUG, _("archiving file `%s'"), dst_file);
476 rc = do_archive_file (dst_file, dst_dir, file_name, &spool->archive, 461 rc = do_archive_file (dst_file, dst_dir, file_name, &spool->archive,
477 TRIPLET_UID (trp), TRIPLET_GID (trp), reldir); 462 reldir);
478 if (rc == 0) 463 if (rc == 0)
479 UPDATE_STATS (STAT_ARCHIVES); 464 UPDATE_STATS (STAT_ARCHIVES);
480 } 465 }
@@ -543,8 +528,7 @@ dir_symlink_file (struct file_triplet *trp, const struct spool *spool,
543{ 528{
544 int rc = 0; 529 int rc = 0;
545 struct saved_cwd cwd; 530 struct saved_cwd cwd;
546 char *dst_dir = create_directory (spool->dest_dir, reldir, 531 char *dst_dir = create_directory (spool->dest_dir, reldir);
547 TRIPLET_UID (trp), TRIPLET_GID (trp));
548 char *src, *dst; 532 char *src, *dst;
549 533
550 if (!dst_dir) 534 if (!dst_dir)
@@ -588,8 +572,7 @@ dir_symlink_file (struct file_triplet *trp, const struct spool *spool,
588 char *dir; 572 char *dir;
589 573
590 *p = 0; 574 *p = 0;
591 dir = create_directory (spool->dest_dir, dst, 575 dir = create_directory (spool->dest_dir, dst);
592 TRIPLET_UID (trp), TRIPLET_GID (trp));
593 if (!dir) 576 if (!dir)
594 rc = 1; 577 rc = 1;
595 else 578 else
@@ -703,8 +686,7 @@ dir_rmsymlink_file (struct file_triplet *trp, const struct spool *spool,
703 char *dst_file; 686 char *dst_file;
704 int rc = 0; 687 int rc = 0;
705 char *signame; 688 char *signame;
706 char *dst_dir = create_directory (spool->dest_dir, reldir, 689 char *dst_dir = create_directory (spool->dest_dir, reldir);
707 TRIPLET_UID (trp), TRIPLET_GID (trp));
708 690
709 if (!dst_dir) 691 if (!dst_dir)
710 return 1; 692 return 1;
diff --git a/src/lock.c b/src/lock.c
index d94731c..3b8787d 100644
--- a/src/lock.c
+++ b/src/lock.c
@@ -233,7 +233,7 @@ wydawca_lock_init ()
233 { 233 {
234 if (!lockdir) 234 if (!lockdir)
235 lockdir = xstrdup (LOCALSTATEDIR "/lock/" PACKAGE); 235 lockdir = xstrdup (LOCALSTATEDIR "/lock/" PACKAGE);
236 if (create_hierarchy (lockdir, 0, getuid (), getgid ())) 236 if (create_hierarchy (lockdir, 0))
237 exit (EX_OSFILE); 237 exit (EX_OSFILE);
238 } 238 }
239} 239}
diff --git a/src/mail.c b/src/mail.c
index ea74b8c..ba77f49 100644
--- a/src/mail.c
+++ b/src/mail.c
@@ -335,7 +335,7 @@ do_notify (struct file_triplet *trp, enum notification_event ev,
335 switch (ntf->tgt) 335 switch (ntf->tgt)
336 { 336 {
337 case notify_admin: 337 case notify_admin:
338 rcpt = admin_address; 338 rcpt = mu_address_dup (admin_address);
339 break; 339 break;
340 340
341 case notify_user: 341 case notify_user:
diff --git a/src/triplet.c b/src/triplet.c
index 614e2b5..e060089 100644
--- a/src/triplet.c
+++ b/src/triplet.c
@@ -199,11 +199,7 @@ triplet_processor (void *data, void *proc_data)
199 case triplet_complete: 199 case triplet_complete:
200 if (debug_level) 200 if (debug_level)
201 logmsg (LOG_DEBUG, _("processing triplet `%s'"), trp->name); 201 logmsg (LOG_DEBUG, _("processing triplet `%s'"), trp->name);
202 if (wydawca_set_triplet_privs (trp) == 0) 202 process_directives (trp, spool);
203 {
204 process_directives (trp, spool);
205 wydawca_set_root_privs ();
206 }
207 return true; 203 return true;
208 204
209 case triplet_incomplete: 205 case triplet_incomplete:
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 @@
1/* wydawca - automatic release submission daemon
2 Copyright (C) 2007, 2009 Sergey Poznyakoff
3
4 Wydawca is free software; you can redistribute it and/or modify it
5 under the terms of the GNU General Public License as published by the
6 Free Software Foundation; either version 3 of the License, or (at your
7 option) any later version.
8
9 Wydawca is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License along
15 with wydawca. If not, see <http://www.gnu.org/licenses/>. */
16
17#include "wydawca.h"
18
19int
20wydawca_userprivs (uid_t uid, gid_t gid, gid_t *grplist, size_t ngrp)
21{
22 int rc = 0;
23 size_t size = 1, j = 1;
24
25 if (uid == 0)
26 return 0;
27
28 /* Reset group permissions */
29 if (geteuid () == 0 && setgroups (ngrp, grplist))
30 {
31 logmsg (LOG_CRIT, "setgroups(%lu, %lu...): %s",
32 ngrp, grplist[0], 0, strerror (errno));
33 return rc;
34 }
35
36 /* Switch to the user's gid. On some OSes the effective gid must
37 be reset first */
38
39#if defined(HAVE_SETEGID)
40 if ((rc = setegid (gid)) < 0)
41 logmsg (LOG_CRIT, "setegid(%lu): %s", gid, strerror (errno));
42#elif defined(HAVE_SETREGID)
43 if ((rc = setregid (gid, gid)) < 0)
44 logmsg (LOG_CRIT, "setregid(%lu,%lu)d: %s",
45 (unsigned long) gid, (unsigned long) gid, strerror (errno));
46#elif defined(HAVE_SETRESGID)
47 if ((rc = setresgid (gid, gid, gid)) < 0)
48 logmsg (LOG_CRIT, "setresgid(%lu,%lu,%lu): %s",
49 (unsigned long) gid, (unsigned long) gid,
50 (unsigned long) gid,
51 strerror (errno));
52#endif
53
54 if (rc == 0 && gid != 0)
55 {
56 if ((rc = setgid (gid)) < 0 && getegid () != gid)
57 logmsg (LOG_CRIT, "setgid(%lu): %s",
58 (unsigned long) gid, strerror (errno));
59 if (rc == 0 && getegid () != gid)
60 {
61 logmsg (LOG_CRIT, _("cannot set effective gid to %lu"),
62 (unsigned long) gid);
63 rc = 1;
64 }
65 }
66
67 /* Now reset uid */
68 if (rc == 0 && uid != 0)
69 {
70 uid_t euid;
71
72 if (setuid (uid)
73 || geteuid () != uid
74 || (getuid () != uid
75 && (geteuid () == 0 || getuid () == 0)))
76 {
77
78#if defined(HAVE_SETREUID)
79 if (geteuid () != uid)
80 {
81 if (setreuid (uid, -1) < 0)
82 {
83 logmsg (LOG_CRIT, "setreuid(%lu,-1): %s",
84 (unsigned long) uid, strerror (errno));
85 rc = 1;
86 }
87 if (setuid (uid) < 0)
88 {
89 logmsg (LOG_CRIT, "setreuid(%lu,-1): %s",
90 (unsigned long) uid, strerror (errno));
91 rc = 1;
92 }
93 }
94 else
95#endif
96 {
97 logmsg (LOG_CRIT, "setuid(%lu): %s",
98 (unsigned long) uid, strerror (errno));
99 rc = 1;
100 }
101 }
102
103 euid = geteuid ();
104 if (uid != 0 && setuid (0) == 0)
105 {
106 logmsg (LOG_CRIT, _("seteuid(0) succeeded when it should not"));
107 rc = 1;
108 }
109 else if (uid != euid && setuid (euid) == 0)
110 {
111 logmsg (LOG_CRIT, _("cannot drop non-root setuid privileges"));
112 rc = 1;
113 }
114
115 }
116
117 return rc;
118}
diff --git a/src/wydawca.c b/src/wydawca.c
index 48c27e9..f02ac99 100644
--- a/src/wydawca.c
+++ b/src/wydawca.c
@@ -19,6 +19,10 @@
19#include "argmatch.h" 19#include "argmatch.h"
20#include "version-etc.h" 20#include "version-etc.h"
21 21
22uid_t wydawca_uid;
23gid_t wydawca_gid;
24size_t wydawca_supp_groupc;
25gid_t *wydawca_supp_groups;
22char *conffile = SYSCONFDIR "/wydawca.rc" ; 26char *conffile = SYSCONFDIR "/wydawca.rc" ;
23int debug_level; 27int debug_level;
24int dry_run_mode; 28int dry_run_mode;
@@ -265,73 +269,6 @@ collect_uids (int argc, char **argv)
265} 269}
266 270
267 271
268static int
269wydawca_set_uid (uid_t uid)
270{
271 int rc;
272
273 if (getuid () != 0)
274 return 0;
275#if defined(HAVE_SETREUID)
276 rc = setreuid (0, uid);
277#elif defined(HAVE_SETRESUID)
278 rc = setresuid (-1, uid, -1);
279#elif defined(HAVE_SETEUID)
280 rc = seteuid (uid);
281#else
282# error "No way to reset user privileges?"
283#endif
284 if (rc < 0)
285 logmsg (LOG_ERR, _("cannot switch to UID %d: %s (r=%d, e=%d)"),
286 uid, strerror (errno), getuid (), geteuid ());
287 return rc;
288}
289
290static int
291wydawca_set_gid (gid_t gid)
292{
293 int rc;
294
295 if (getuid () != 0)
296 return 0;
297#if defined(HAVE_SETREGID)
298 rc = setregid (0, gid);
299#elif defined(HAVE_SETRESGID)
300 rc = setresgid (-1, gid, -1);
301#elif defined(HAVE_SETEGID)
302 rc = setegid (gid);
303#else
304# error "No way to reset user privileges?"
305#endif
306 if (rc < 0)
307 logmsg (LOG_ERR, _("cannot switch to GID %d: %s (r=%d, e=%d)"),
308 gid, strerror (errno), getgid (), getegid ());
309 return rc;
310}
311
312int
313wydawca_set_privs (uid_t uid, gid_t gid)
314{
315 if (wydawca_set_gid (gid))
316 return -1;
317 if (wydawca_set_uid (uid))
318 return -1;
319 return 0;
320}
321
322int
323wydawca_set_triplet_privs (struct file_triplet *trp)
324{
325 return wydawca_set_privs (TRIPLET_UID (trp), TRIPLET_GID (trp));
326}
327
328int
329wydawca_set_root_privs ()
330{
331 return wydawca_set_privs (0, 0);
332}
333
334
335char **x_argv; 272char **x_argv;
336extern int reconfigure; 273extern int reconfigure;
337 274
@@ -377,6 +314,8 @@ main (int argc, char **argv)
377 if (lint_mode) 314 if (lint_mode)
378 exit (0); 315 exit (0);
379 316
317 if (dry_run_mode)
318 cron_option = 1;
380 if (cron_option) 319 if (cron_option)
381 daemon_mode = 0; 320 daemon_mode = 0;
382 if (foreground_option >= 0) 321 if (foreground_option >= 0)
@@ -394,6 +333,22 @@ main (int argc, char **argv)
394 log_printer = syslog_printer; 333 log_printer = syslog_printer;
395 } 334 }
396 335
336 if (getgid () == 0)
337 {
338 if (wydawca_uid == 0)
339 {
340 if (!force_startup)
341 {
342 logmsg (LOG_CRIT, _("won't run with root privileges"));
343 exit (EX_UNAVAILABLE);
344 }
345 }
346 else if (wydawca_userprivs (wydawca_uid, wydawca_gid,
347 wydawca_supp_groups,
348 wydawca_supp_groupc))
349 exit (EX_UNAVAILABLE);
350 }
351
397 mail_init (); 352 mail_init ();
398 wydawca_lock_init (); 353 wydawca_lock_init ();
399 354
@@ -414,7 +369,6 @@ main (int argc, char **argv)
414 if (reconfigure) 369 if (reconfigure)
415 { 370 {
416 int i; 371 int i;
417 wydawca_set_uid (0);
418 for (i = getdtablesize (); i > 2; i--) 372 for (i = getdtablesize (); i > 2; i--)
419 close (i); 373 close (i);
420 remove_pidfile (); 374 remove_pidfile ();
diff --git a/src/wydawca.h b/src/wydawca.h
index f786271..81e6509 100644
--- a/src/wydawca.h
+++ b/src/wydawca.h
@@ -303,6 +303,10 @@ void make_default_meta (struct metadef kwexp[5], const char *user,
303 303
304 304
305/* Global variables */ 305/* Global variables */
306extern uid_t wydawca_uid;
307extern gid_t wydawca_gid;
308extern size_t wydawca_supp_groupc;
309extern gid_t *wydawca_supp_groups;
306extern char *conffile; /* Configuration file name */ 310extern char *conffile; /* Configuration file name */
307extern int debug_level; /* Debugging level */ 311extern int debug_level; /* Debugging level */
308extern int dry_run_mode; /* Dry run indicator */ 312extern int dry_run_mode; /* Dry run indicator */
@@ -355,8 +359,8 @@ size_t trim_length (const char *str);
355size_t trim (char *str); 359size_t trim (char *str);
356void logmsg (int prio, char *fmt, ...) GSC_PRINTFLIKE(2,3); 360void logmsg (int prio, char *fmt, ...) GSC_PRINTFLIKE(2,3);
357int test_dir (const char *name, int *ec); 361int test_dir (const char *name, int *ec);
358char *create_directory (const char *base, const char *name, 362char *create_directory (const char *base, const char *name);
359 uid_t uid, gid_t gid); 363int create_hierarchy (char *dir, size_t baselen);
360void parse_config (void); 364void parse_config (void);
361void log_output (int prio, const char *prog, FILE *fp); 365void log_output (int prio, const char *prog, FILE *fp);
362 366
@@ -428,9 +432,6 @@ int process_directives (struct file_triplet *trp,
428 432
429int enabled_spool_p (const struct spool *spool); 433int enabled_spool_p (const struct spool *spool);
430 434
431int wydawca_set_privs (uid_t uid, gid_t gid);
432int wydawca_set_triplet_privs (struct file_triplet *trp);
433int wydawca_set_root_privs (void);
434 435
435 436
436int parse_time_interval (const char *str, time_t *pint, const char **endp); 437int parse_time_interval (const char *str, time_t *pint, const char **endp);
@@ -538,3 +539,6 @@ void wydawca_lock_init (void);
538/* tcpwrap.h */ 539/* tcpwrap.h */
539extern struct gconf_keyword tcpwrapper_kw[]; 540extern struct gconf_keyword tcpwrapper_kw[];
540int tcpwrap_access(int fd); 541int tcpwrap_access(int fd);
542
543/* userprivs.c */
544int 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.