ph10 2006/02/07 14:05:17 GMT
Modified files:
exim-doc/doc-txt ChangeLog
exim-src/src child.c
exim-src/src/routers queryprogram.c
exim-test/confs 5204
exim-test/log 0433
exim-test/scripts/5200-queryprogram 5204
exim-test/stderr 0433 5204
exim-test/stdout 5204
Log:
Improve queryprogram behaviour when not running as root.
Revision Changes Path
1.284 +14 -0 exim/exim-doc/doc-txt/ChangeLog
1.8 +40 -17 exim/exim-src/src/child.c
1.8 +21 -2 exim/exim-src/src/routers/queryprogram.c
1.2 +4 -1 exim/exim-test/confs/5204
1.2 +3 -3 exim/exim-test/log/0433
1.2 +7 -1 exim/exim-test/scripts/5200-queryprogram/5204
1.2 +6 -6 exim/exim-test/stderr/0433
1.2 +53 -8 exim/exim-test/stderr/5204
1.2 +13 -0 exim/exim-test/stdout/5204
Index: ChangeLog
===================================================================
RCS file: /home/cvs/exim/exim-doc/doc-txt/ChangeLog,v
retrieving revision 1.283
retrieving revision 1.284
diff -u -r1.283 -r1.284
--- ChangeLog 3 Feb 2006 15:26:54 -0000 1.283
+++ ChangeLog 7 Feb 2006 14:05:17 -0000 1.284
@@ -1,4 +1,4 @@
-$Cambridge: exim/exim-doc/doc-txt/ChangeLog,v 1.283 2006/02/03 15:26:54 ph10 Exp $
+$Cambridge: exim/exim-doc/doc-txt/ChangeLog,v 1.284 2006/02/07 14:05:17 ph10 Exp $
Change log file for Exim from version 4.21
-------------------------------------------
@@ -71,6 +71,20 @@
compiled. In many other places in Exim, IPv6 addresses are always
recognized, so I have changed this. It also means that IPv4 domain
literals of the form [IPV4:n.n.n.n] are now always recognized.
+
+PH/14 When a uid/gid is specified for the queryprogram router, it cannot be
+ used if the router is not running as root, for example, when verifying at
+ ACL time, or when using -bh. The debugging output from this situation was
+ non-existent - all you got was a failure to exec. I have made two
+ changes:
+
+ (a) Failures to set uid/gid, the current directory, or a process leader
+ in a subprocess such as that created by queryprogram now generate
+ suitable debugging ouput when -d is set.
+
+ (b) The queryprogram router detects when it is not running as root,
+ outputs suitable debugging information if -d is set, and then runs
+ the subprocess without attempting to change uid/gid.
Exim version 4.60
Index: child.c
===================================================================
RCS file: /home/cvs/exim/exim-src/src/child.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- child.c 7 Feb 2006 11:19:00 -0000 1.7
+++ child.c 7 Feb 2006 14:05:17 -0000 1.8
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/child.c,v 1.7 2006/02/07 11:19:00 ph10 Exp $ */
+/* $Cambridge: exim/exim-src/src/child.c,v 1.8 2006/02/07 14:05:17 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -292,14 +292,48 @@
oldsignal = signal(SIGCHLD, SIG_DFL);
pid = fork();
-/* The child process becomes a process group leader if requested, and then
-organizes the pipes. Any unexpected failure is signalled with EX_EXECFAILED;
-these are all "should never occur" failures, except perhaps for exec failing
-because the command doesn't exist. */
+/* Handle the child process. First, set the required environment. We must do
+this before messing with the pipes, in order to be able to write debugging
+output when things go wrong. */
if (pid == 0)
{
- if (make_leader && setpgid(0,0) < 0) goto CHILD_FAILED;
+ signal(SIGUSR1, SIG_IGN);
+
+ if (newgid != NULL && setgid(*newgid) < 0)
+ {
+ DEBUG(D_any) debug_printf("failed to set gid=%ld in subprocess: %s\n",
+ (long int)(*newgid), strerror(errno));
+ goto CHILD_FAILED;
+ }
+
+ if (newuid != NULL && setuid(*newuid) < 0)
+ {
+ DEBUG(D_any) debug_printf("failed to set uid=%ld in subprocess: %s\n",
+ (long int)(*newuid), strerror(errno));
+ goto CHILD_FAILED;
+ }
+
+ (void)umask(newumask);
+
+ if (wd != NULL && Uchdir(wd) < 0)
+ {
+ DEBUG(D_any) debug_printf("failed to chdir to %s: %s\n", wd,
+ strerror(errno));
+ goto CHILD_FAILED;
+ }
+
+ /* Becomes a process group leader if requested, and then organize the pipes.
+ Any unexpected failure is signalled with EX_EXECFAILED; these are all "should
+ never occur" failures, except for exec failing because the command doesn't
+ exist. */
+
+ if (make_leader && setpgid(0,0) < 0)
+ {
+ DEBUG(D_any) debug_printf("failed to set group leader in subprocess: %s\n",
+ strerror(errno));
+ goto CHILD_FAILED;
+ }
(void)close(inpfd[pipe_write]);
force_fd(inpfd[pipe_read], 0);
@@ -310,17 +344,6 @@
(void)close(2);
(void)dup2(1, 2);
- /* Set the required environment. */
-
- signal(SIGUSR1, SIG_IGN);
- if (newgid != NULL && setgid(*newgid) < 0) goto CHILD_FAILED;
- if (newuid != NULL && setuid(*newuid) < 0) goto CHILD_FAILED;
- (void)umask(newumask);
-
- /* Set the working directory if required */
-
- if (wd != NULL && Uchdir(wd) < 0) goto CHILD_FAILED;
-
/* Now do the exec */
if (envp == NULL) execv(CS argv[0], (char *const *)argv);
@@ -328,7 +351,7 @@
/* Failed to execv. Signal this failure using EX_EXECFAILED. We are
losing the actual errno we got back, because there is no way to return
- this. */
+ this information. */
CHILD_FAILED:
_exit(EX_EXECFAILED); /* Note: must be _exit(), NOT exit() */
Index: queryprogram.c
===================================================================
RCS file: /home/cvs/exim/exim-src/src/routers/queryprogram.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- queryprogram.c 7 Feb 2006 11:19:02 -0000 1.7
+++ queryprogram.c 7 Feb 2006 14:05:17 -0000 1.8
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/routers/queryprogram.c,v 1.7 2006/02/07 11:19:02 ph10 Exp $ */
+/* $Cambridge: exim/exim-src/src/routers/queryprogram.c,v 1.8 2006/02/07 14:05:17 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -198,8 +198,12 @@
(queryprogram_router_options_block *)(rblock->options_block);
uschar *current_directory = ob->current_directory;
ugid_block ugid;
+uid_t curr_uid = getuid();
+gid_t curr_gid = getgid();
uid_t uid = ob->cmd_uid;
gid_t gid = ob->cmd_gid;
+uid_t *puid = &uid;
+gid_t *pgid = &gid;
DEBUG(D_route) debug_printf("%s router called for %s: domain = %s\n",
rblock->name, addr->address, addr->domain);
@@ -250,9 +254,24 @@
}
}
-DEBUG(D_route) debug_printf("uid=%ld gid=%ld current_directory=%s\n",
+DEBUG(D_route) debug_printf("requires uid=%ld gid=%ld current_directory=%s\n",
(long int)uid, (long int)gid, current_directory);
+/* If we are not running as root, we will not be able to change uid/gid. */
+
+if (curr_uid != root_uid && (uid != curr_uid || gid != curr_gid))
+ {
+ DEBUG(D_route)
+ {
+ debug_printf("not running as root: cannot change uid/gid\n");
+ debug_printf("subprocess will run with uid=%ld gid=%ld\n",
+ (long int)curr_uid, (long int)curr_gid);
+ }
+ puid = pgid = NULL;
+ }
+
+/* Set up the command to run */
+
if (!transport_set_up_command(&argvptr, /* anchor for arg list */
ob->command, /* raw command */
TRUE, /* expand the arguments */
@@ -266,7 +285,7 @@
/* Create the child process, making it a group leader. */
-pid = child_open_uid(argvptr, NULL, 0077, &uid, &gid, &fd_in, &fd_out,
+pid = child_open_uid(argvptr, NULL, 0077, puid, pgid, &fd_in, &fd_out,
current_directory, TRUE);
if (pid < 0)
Index: 5204
===================================================================
RCS file: /home/cvs/exim/exim-test/confs/5204,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- 5204 7 Feb 2006 10:34:26 -0000 1.1
+++ 5204 7 Feb 2006 14:05:17 -0000 1.2
@@ -1,5 +1,7 @@
# Exim test configuration 5204
+COMMAND_USER=EXIMUSER
+
exim_path = EXIM_PATH
host_lookup_order = bydns
primary_hostname = myhost.test.ex
@@ -11,6 +13,7 @@
# ----- Main settings -----
+acl_smtp_rcpt = accept verify = recipient
domainlist local_domains = test.ex
# ----- Routers -----
@@ -27,7 +30,7 @@
caseful_local_part
command = /bin/echo \
"${if match{$local_part}{^\"([^\"]*)\"(.*)\\$}{$1$2}{$local_part}}"
- command_user = EXIMUSER
+ command_user = COMMAND_USER
domains = ! +local_domains
no_more
transport = smtp
Index: 0433
===================================================================
RCS file: /home/cvs/exim/exim-test/log/0433,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- 0433 7 Feb 2006 10:34:46 -0000 1.1
+++ 0433 7 Feb 2006 14:05:17 -0000 1.2
@@ -1,6 +1,6 @@
1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
-1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225 port 1226 (IPv4)
+1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225 port 1226
1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on [127.0.0.1]:1228 port 1225 (IPv4) port 1226 (IPv4)
-1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225 port 1226 (IPv4) [127.0.0.1]:1228
+1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225 port 1226 [127.0.0.1]:1228
1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on [127.0.0.1]:1228 port 1227 (IPv4)
-1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225 port 1226 (IPv4)
+1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225 port 1226
Index: 5204
===================================================================
RCS file: /home/cvs/exim/exim-test/scripts/5200-queryprogram/5204,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- 5204 7 Feb 2006 10:54:50 -0000 1.1
+++ 5204 7 Feb 2006 14:05:17 -0000 1.2
@@ -1,4 +1,4 @@
-# queryprogram
+# queryprogram general tests
1
exim -bt '"ACCEPT hosts=localhost lookup=byname"@???'
****
@@ -25,4 +25,10 @@
****
exim -odi '"FAIL cannot route this one (FAIL)"@???'
Test message
+****
+exim -DCOMMAND_USER=CALLER -d-all+route -bh V4NET.2.3.4
+ehlo some.name
+mail from:<x@y>
+rcpt to:<"FAIL cannot route this one (FAIL)"@???>
+quit
****
Index: 0433
===================================================================
RCS file: /home/cvs/exim/exim-test/stderr/0433,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- 0433 7 Feb 2006 10:47:31 -0000 1.1
+++ 0433 7 Feb 2006 14:05:17 -0000 1.2
@@ -27,8 +27,8 @@
changed uid/gid: running as a daemon
uid=EXIM_UID gid=EXIM_GID pid=pppp
LOG: MAIN
- exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225 port 1226 (IPv4)
-set_process_info: pppp daemon: no queue runs, listening for SMTP on port 1225 port 1226 (IPv4)
+ exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225 port 1226
+set_process_info: pppp daemon: no queue runs, listening for SMTP on port 1225 port 1226
daemon running with uid=EXIM_UID gid=EXIM_GID euid=EXIM_UID egid=EXIM_GID
Listening...
Exim version x.yz ....
@@ -61,8 +61,8 @@
changed uid/gid: running as a daemon
uid=EXIM_UID gid=EXIM_GID pid=pppp
LOG: MAIN
- exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225 port 1226 (IPv4) [127.0.0.1]:1228
-set_process_info: pppp daemon: no queue runs, listening for SMTP on port 1225 port 1226 (IPv4) [127.0.0.1]:1228
+ exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225 port 1226 [127.0.0.1]:1228
+set_process_info: pppp daemon: no queue runs, listening for SMTP on port 1225 port 1226 [127.0.0.1]:1228
daemon running with uid=EXIM_UID gid=EXIM_GID euid=EXIM_UID egid=EXIM_GID
Listening...
Exim version x.yz ....
@@ -97,7 +97,7 @@
changed uid/gid: running as a daemon
uid=EXIM_UID gid=EXIM_GID pid=pppp
LOG: MAIN
- exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225 port 1226 (IPv4)
-set_process_info: pppp daemon: no queue runs, listening for SMTP on port 1225 port 1226 (IPv4)
+ exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225 port 1226
+set_process_info: pppp daemon: no queue runs, listening for SMTP on port 1225 port 1226
daemon running with uid=EXIM_UID gid=EXIM_GID euid=EXIM_UID egid=EXIM_GID
Listening...
Index: 5204
===================================================================
RCS file: /home/cvs/exim/exim-test/stderr/5204,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- 5204 7 Feb 2006 10:47:31 -0000 1.1
+++ 5204 7 Feb 2006 14:05:17 -0000 1.2
@@ -14,7 +14,7 @@
checking domains
calling q router
q router called for "DECLINE cannot route this one (DECLINE)"@???: domain = some.host
-uid=EXIM_UID gid=EXIM_GID current_directory=/
+requires uid=EXIM_UID gid=EXIM_GID current_directory=/
command wrote: DECLINE cannot route this one (DECLINE)
q router declined for "DECLINE cannot route this one (DECLINE)"@???
"more" is false: skipping remaining routers
@@ -34,7 +34,7 @@
checking domains
calling q router
q router called for "FAIL cannot route this one (FAIL)"@???: domain = some.host
-uid=EXIM_UID gid=EXIM_GID current_directory=/
+requires uid=EXIM_UID gid=EXIM_GID current_directory=/
command wrote: FAIL cannot route this one (FAIL)
q router forced address failure
>>>>>>>>>>>>>>>> Exim pid=pppp terminating with rc=2 >>>>>>>>>>>>>>>>
@@ -52,7 +52,7 @@
checking domains
calling q router
q router called for "ERROR cannot route this one (ERROR)"@???: domain = some.host
-uid=EXIM_UID gid=EXIM_GID current_directory=/
+requires uid=EXIM_UID gid=EXIM_GID current_directory=/
command wrote: ERROR cannot route this one (ERROR)
LOG: PANIC
q router: bad command yield: ERROR cannot route this one (ERROR)
@@ -73,7 +73,7 @@
checking domains
calling q router
q router called for "DEFER cannot route this one (DEFER)"@???: domain = some.host
-uid=EXIM_UID gid=EXIM_GID current_directory=/
+requires uid=EXIM_UID gid=EXIM_GID current_directory=/
command wrote: DEFER cannot route this one (DEFER)
q router: defer for "DEFER cannot route this one (DEFER)"@???
message: cannot route this one (DEFER)
@@ -92,7 +92,7 @@
checking domains
calling q router
q router called for "ACCEPT transport = other_smtp hosts=ten-1.test.ex"@???: domain = some.host
-uid=EXIM_UID gid=EXIM_GID current_directory=/
+requires uid=EXIM_UID gid=EXIM_GID current_directory=/
command wrote: ACCEPT transport = other_smtp hosts=ten-1.test.ex
finding IP address for ten-1.test.ex
doing DNS lookup
@@ -119,7 +119,7 @@
checking domains
calling q router
q router called for PASS@???: domain = some.host
-uid=EXIM_UID gid=EXIM_GID current_directory=/
+requires uid=EXIM_UID gid=EXIM_GID current_directory=/
command wrote: PASS
q router passed for PASS@???
--------> s router <--------
@@ -158,7 +158,7 @@
checking domains
calling q router
q router called for "FREEZE cannot route this one (FREEZE)"@???: domain = some.host
-uid=EXIM_UID gid=EXIM_GID current_directory=/
+requires uid=EXIM_UID gid=EXIM_GID current_directory=/
command wrote: FREEZE cannot route this one (FREEZE)
q router: defer for "FREEZE cannot route this one (FREEZE)"@???
message: cannot route this one (FREEZE)
@@ -177,7 +177,7 @@
checking domains
calling q router
q router called for "REDIRECT postmaster@???: domain = some.host
-uid=EXIM_UID gid=EXIM_GID current_directory=/
+requires uid=EXIM_UID gid=EXIM_GID current_directory=/
command wrote: REDIRECT postmaster@???
rda_interpret (string): postmaster@???
expanded: postmaster@???
@@ -216,4 +216,49 @@
routed by pm router
envelope to: postmaster@???
transport: null
+>>>>>>>>>>>>>>>> Exim pid=pppp terminating with rc=0 >>>>>>>>>>>>>>>>
+Exim version x.yz ....
+configuration file is TESTSUITE/test-config
+admin user
+host in hosts_connection_nolog? no (option unset)
+LOG: smtp_connection MAIN
+ SMTP connection from [V4NET.2.3.4]
+host in host_lookup? no (option unset)
+host in host_reject_connection? no (option unset)
+host in sender_unqualified_hosts? no (option unset)
+host in recipient_unqualified_hosts? no (option unset)
+host in helo_verify_hosts? no (option unset)
+host in helo_try_verify_hosts? no (option unset)
+host in helo_accept_junk_hosts? no (option unset)
+some.name in helo_lookup_domains? no (end of list)
+host in pipelining_advertise_hosts? yes (matched "*")
+processing "accept"
+check verify = recipient
+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+routing "FAIL cannot route this one (FAIL)"@???
+--------> b router <--------
+local_part=fail cannot route this one (fail) domain=some.host
+checking senders
+y in ""? no (end of list)
+x@y in ":"? no (end of list)
+b router skipped: senders mismatch
+--------> q router <--------
+local_part=FAIL cannot route this one (FAIL) domain=some.host
+checking domains
+some.host in "test.ex"? no (end of list)
+some.host in "! +local_domains"? yes (end of list)
+calling q router
+q router called for "FAIL cannot route this one (FAIL)"@???: domain = some.host
+requires uid=CALLER_UID gid=CALLER_GID current_directory=/
+not running as root: cannot change uid/gid
+subprocess will run with uid=EXIM_UID gid=EXIM_GID
+command wrote: FAIL cannot route this one (FAIL)
+q router forced address failure
+----------- end verify ------------
+accept: condition test failed
+end of inline ACL: implicit DENY
+LOG: MAIN REJECT
+ H=(some.name) [V4NET.2.3.4] F=<x@y> rejected RCPT <"FAIL cannot route this one (FAIL)"@???>: cannot route this one (FAIL)
+LOG: smtp_connection MAIN
+ SMTP connection from (some.name) [V4NET.2.3.4] closed by QUIT
>>>>>>>>>>>>>>>> Exim pid=pppp terminating with rc=0 >>>>>>>>>>>>>>>>
Index: 5204
===================================================================
RCS file: /home/cvs/exim/exim-test/stdout/5204,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- 5204 7 Feb 2006 10:47:37 -0000 1.1
+++ 5204 7 Feb 2006 14:05:17 -0000 1.2
@@ -19,3 +19,16 @@
postmaster@???
<-- "REDIRECT postmaster@???
router = pm, transport = null
+
+**** SMTP testing session as if from host V4NET.2.3.4
+**** but without any ident (RFC 1413) callback.
+**** This is not for real!
+
+220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+250-myhost.test.ex Hello some.name [V4NET.2.3.4]
+250-SIZE 52428800
+250-PIPELINING
+250 HELP
+250 OK
+550 cannot route this one (FAIL)
+221 myhost.test.ex closing connection