1 /*
2    daemon.c
3 
4    This file is part of GNU Anubis.
5    Copyright (C) 2001-2014 The Anubis Team.
6 
7    GNU Anubis is free software; you can redistribute it and/or modify it
8    under the terms of the GNU General Public License as published by the
9    Free Software Foundation; either version 3 of the License, or (at your
10    option) any later version.
11 
12    GNU Anubis is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License along
18    with GNU Anubis.  If not, see <http://www.gnu.org/licenses/>.
19 */
20 
21 #include "headers.h"
22 #include "extern.h"
23 
24 /* TCP wrappers */
25 #ifdef USE_LIBWRAP
26 # include <tcpd.h>
27 int deny_severity = LOG_INFO;
28 int allow_severity = LOG_INFO;
29 #endif /* USE_LIBWRAP */
30 
31 char *log_tag = "anubis";
32 int log_facility = LOG_MAIL;
33 
34 /************
35   DAEMONIZE
36 *************/
37 
38 void
daemonize(void)39 daemonize (void)
40 {
41   signal (SIGHUP, SIG_IGN);
42 #ifdef HAVE_DAEMON
43   if (daemon (0, 0) == -1)
44     anubis_error (EXIT_FAILURE, errno, _("daemon() failed"));
45 #else
46   chdir ("/");
47   umask (0);
48   switch (fork ())
49     {
50     case -1:			/* fork() failed */
51       anubis_error (EXIT_FAILURE, errno, _("Cannot fork."));
52       break;
53     case 0:			/* child process */
54       break;
55     default:			/* parent process */
56       quit (0);
57     }
58   if (setsid () == -1)
59     anubis_error (EXIT_FAILURE, errno, _("setsid() failed"));
60 
61   close (0);
62   close (1);
63   close (2);
64 #endif /* HAVE_DAEMON */
65 
66   topt &= ~T_FOREGROUND;
67   topt |= T_DAEMON;
68 
69   openlog (log_tag, LOG_PID, log_facility);
70   info (NORMAL, _("%s daemon startup succeeded."), version);
71   write_pid_file ();
72   return;
73 }
74 
75 char *
format_exit_status(char * buffer,size_t buflen,int status)76 format_exit_status (char *buffer, size_t buflen, int status)
77 {
78   if (WIFEXITED(status))
79     {
80       if (WEXITSTATUS(status) == 0)
81 	snprintf(buffer, buflen, _("Exited successfully"));
82       else
83 	snprintf(buffer, buflen, _("Failed with status %d"),
84 		 WEXITSTATUS(status));
85     }
86   else if (WIFSIGNALED(status))
87     snprintf(buffer, buflen,
88 	     _("Terminated on signal %d"), WTERMSIG(status));
89   else if (WIFSTOPPED(status))
90     snprintf(buffer, buflen,
91 	     _("Stopped on signal %d"), WSTOPSIG(status));
92 #ifdef WCOREDUMP
93   else if (WCOREDUMP(status))
94     snprintf(buffer, buflen, _("Dumped core"));
95 #endif
96   else
97     snprintf(buffer, buflen, _("Terminated"));
98   return buffer;
99 }
100 
101 static void
report_process_status(size_t count,pid_t pid,int status)102 report_process_status (size_t count, pid_t pid, int status)
103 {
104   char buffer[LINEBUFFER];
105 
106   count--;
107   info (VERBOSE,
108 	ngettext
109 	("Child [%lu] finished. %s. %d client left.",
110 	 "Child [%lu] finished. %s. %d clients left.",
111 	 count),
112 	(unsigned long) pid,
113 	format_exit_status (buffer, sizeof buffer, status), count);
114 }
115 
116 static void
subprocess_report_status(size_t count,pid_t pid,int status)117 subprocess_report_status (size_t count, pid_t pid, int status)
118 {
119   char buffer[LINEBUFFER];
120 
121   info (VERBOSE, _("Local program [%lu] finished. %s"),
122 	(unsigned long) pid,
123 	format_exit_status (buffer, sizeof buffer, status));
124 }
125 
126 /************************************
127  If a service is not available,
128  then close a transmission channel.
129 *************************************/
130 
131 void
service_unavailable(NET_STREAM * sd_client)132 service_unavailable (NET_STREAM * sd_client)
133 {
134   char buf[LINEBUFFER + 1];
135 
136   snprintf (buf, LINEBUFFER,
137 	    "421 %s Service not available, closing transmission channel."
138 	    CRLF, (topt & T_LOCAL_MTA) ? "localhost" : session.mta);
139 
140   swrite (SERVER, *sd_client, buf);
141   stream_close (*sd_client);
142   stream_destroy (sd_client);
143   return;
144 }
145 
146 /*************************
147  Set an unprivileged user
148  (if possible).
149 **************************/
150 
151 void
set_unprivileged_user(void)152 set_unprivileged_user (void)
153 {
154   if (topt & T_USER_NOTPRIVIL)
155     {
156       if (check_username (session.notprivileged)) {
157 	anubis_changeowner (session.notprivileged);
158 	assign_string (&session.clientname, session.notprivileged);
159       }
160       else
161 	anubis_error (EXIT_FAILURE, 0,
162 		      _("WARNING: An unprivileged user cannot be resolved. Verify your settings!"));
163     }
164   else
165     {
166       if (check_username (DEFAULT_UNPRIVILEGED_USER)) {
167 	anubis_changeowner (DEFAULT_UNPRIVILEGED_USER);
168 	assign_string (&session.clientname, DEFAULT_UNPRIVILEGED_USER);
169       }
170       else
171 	info (NORMAL,
172 	      _("WARNING: An unprivileged user has not been specified!"));
173     }
174   return;
175 }
176 
177 int
anubis_child_main(struct sockaddr_in * addr)178 anubis_child_main (struct sockaddr_in *addr)
179 {
180   int rc;
181 
182   proclist_init ();
183   switch (anubis_mode)
184     {
185     case anubis_transparent:
186       rc = anubis_transparent_mode (addr);
187       break;
188 
189 #ifdef WITH_GSASL
190     case anubis_authenticate:
191       rc = anubis_authenticate_mode (addr);
192       break;
193 #endif /* WITH_GSASL */
194 
195     case anubis_proxy:
196       rc = anubis_proxy_mode (addr);
197       break;
198 
199     default:
200       abort();
201     }
202   proclist_cleanup (subprocess_report_status);
203   net_close_stream (&remote_client);
204   return rc;
205 }
206 
207 /**************
208   DAEMON loop
209 ***************/
210 
211 void
loop(int sd_bind)212 loop (int sd_bind)
213 {
214   struct sockaddr_in addr;
215   pid_t childpid = 0;
216   socklen_t addrlen;
217 #ifdef USE_LIBWRAP
218   struct request_info req;
219 #endif /* USE_LIBWRAP */
220 
221   addrlen = sizeof (addr);
222 
223   proclist_init ();
224 
225   info (VERBOSE, _("GNU Anubis is running..."));
226 
227   for (;;)
228     {
229       int fd;
230       size_t count;
231 
232       fd = accept (sd_bind, (struct sockaddr *) &addr, &addrlen);
233       count = proclist_cleanup (report_process_status);
234 
235       if (fd < 0)
236 	{
237 	  if (errno == EINTR)
238 	    continue;
239 	  else
240 	    {
241 	      anubis_error (0, errno, _("accept() failed"));
242 	      continue;
243 	    }
244 	}
245 
246       /* Create the TCP stream */
247       net_create_stream (&remote_client, fd);
248       remote_server = NULL;
249 
250       /*
251          Check the TCP wrappers settings.
252        */
253 
254 #ifdef USE_LIBWRAP
255       request_init (&req, RQ_DAEMON, "anubis", RQ_FILE, fd, 0);
256       fromhost (&req);
257       if (hosts_access (&req) == 0)
258 	{
259 	  info (NORMAL,
260 		_("TCP wrappers: connection from %s:%u rejected."),
261 		inet_ntoa (addr.sin_addr), ntohs (addr.sin_port));
262 	  service_unavailable (&remote_client);
263 	  continue;
264 	}
265 #endif /* USE_LIBWRAP */
266 
267       /*
268          Read the system configuration file (SUPERVISOR).
269        */
270 
271       if (!(topt & T_NORC))
272 	{
273 	  open_rcfile (CF_SUPERVISOR);
274 	  process_rcfile (CF_SUPERVISOR);
275 	}
276 
277       if (count >= MAXCLIENTS)
278 	{
279 	  info (NORMAL,
280 		_("Too many clients. Connection from %s:%u rejected."),
281 		inet_ntoa (addr.sin_addr), ntohs (addr.sin_port));
282 	  service_unavailable (&remote_client);
283 	}
284       else
285 	{
286 	  info (NORMAL, _("Connection from %s:%u"),
287 		inet_ntoa (addr.sin_addr), ntohs (addr.sin_port));
288 
289 	  childpid = fork ();
290 	  if (childpid == -1)
291 	    anubis_error (0, errno, _("daemon: cannot fork"));
292 	  else if (childpid == 0)
293 	    {			/* a child process */
294 	      /* FIXME */
295 	      signal (SIGCHLD, SIG_IGN);
296 	      quit (anubis_child_main (&addr));
297 	    }
298 	  else /* master process */
299 	    proclist_register (childpid);
300 
301 	  net_close_stream (&remote_client);
302 	}
303     }
304   return;
305 }
306 
307 /********************************************
308  Run an outgoing mail processor on standard
309  input and output as described in RFC 821.
310 *********************************************/
311 
312 static int
_stdio_write(void * sd,const char * data,size_t size,size_t * nbytes)313 _stdio_write (void *sd, const char *data, size_t size, size_t * nbytes)
314 {
315   int rc;
316   int fd = (int) sd;
317 
318   if (fd == 0)
319     fd = 1;
320   rc = write (fd, data, size);
321   if (rc > 0)
322     {
323       *nbytes = rc;
324       return 0;
325     }
326   return errno;
327 }
328 
329 static int
_stdio_read(void * sd,char * data,size_t size,size_t * nbytes)330 _stdio_read (void *sd, char *data, size_t size, size_t * nbytes)
331 {
332   int n;
333   int fd = (int) sd;
334   fd_set rds;
335 
336   errno = 0;
337   FD_ZERO (&rds);
338   FD_SET (fd, &rds);
339   do
340     n = select (fd + 1, &rds, NULL, NULL, NULL);
341   while (n < 0 && errno == EINTR);
342   if (n > 0)
343     {
344       n = read (fd, data, size);
345       if (n >= 0)
346 	*nbytes = n;
347       else
348 	return errno;
349     }
350   return 0;
351 }
352 
353 static const char *
_stdio_strerror(void * ignored_data,int rc)354 _stdio_strerror (void *ignored_data, int rc)
355 {
356   return strerror (rc);
357 }
358 
359 void
create_stdio_stream(NET_STREAM * s)360 create_stdio_stream (NET_STREAM *s)
361 {
362   net_create_stream (s, 0);
363   stream_set_read (*s, _stdio_read);
364   stream_set_write (*s, _stdio_write);
365   stream_set_strerror (*s, _stdio_strerror);
366 }
367 
368 void
stdinout(void)369 stdinout (void)
370 {
371   topt &= ~T_SSL;
372   topt |= T_FOREGROUND;
373   topt |= T_SMTP_ERROR_CODES;
374 
375   proclist_init ();
376 
377   anubis_getlogin (&session.clientname);
378   auth_tunnel ();		/* session.clientname = session.supervisor */
379 
380   ASSERT_MTA_CONFIG ();
381 
382   create_stdio_stream (&remote_client);
383 
384   alarm (300);
385   if (topt & T_LOCAL_MTA)
386     remote_server = make_local_connection (session.execpath, session.execargs);
387   else
388     remote_server = make_remote_connection (session.mta, session.mta_port);
389   alarm (0);
390 
391   if (remote_server == NULL)
392     {
393       service_unavailable (&remote_client);
394       free_mem ();
395       return;
396     }
397   stream_set_read (remote_server, _stdio_read);
398   stream_set_write (remote_server, _stdio_write);
399   stream_set_strerror (remote_server, _stdio_strerror);
400 
401   smtp_session_transparent ();
402   proclist_cleanup (subprocess_report_status);
403 
404   net_close_stream (&remote_server);
405   free_mem ();
406   return;
407 }
408 
409 /* EOF */
410