1 /* GNU Mailutils -- a suite of utilities for electronic mail
2    Copyright (C) 2007-2021 Free Software Foundation, Inc.
3 
4    This library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 3 of the License, or (at your option) any later version.
8 
9    This library 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 GNU
12    Lesser General Public License for more details.
13 
14    You should have received a copy of the GNU Lesser General
15    Public License along with this library; If not, see
16    <http://www.gnu.org/licenses/>.  */
17 
18 #ifdef HAVE_CONFIG_H
19 #include <config.h>
20 #endif
21 #include <sys/time.h>
22 #include <sys/types.h>
23 #include <sys/socket.h>
24 #include <sys/stat.h>
25 #include <netinet/in.h>
26 #include <sys/un.h>
27 #include <arpa/inet.h>
28 #include <unistd.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <mailutils/acl.h>
32 #include <mailutils/server.h>
33 #include <mailutils/debug.h>
34 #include <mailutils/diag.h>
35 #include <mailutils/errno.h>
36 #include <mailutils/nls.h>
37 #include <mailutils/sockaddr.h>
38 #include <mailutils/stream.h>
39 #include <mailutils/stdstream.h>
40 #include <mailutils/filter.h>
41 #include <mailutils/syslog.h>
42 
43 struct _mu_ip_server
44 {
45   char *ident;
46   struct mu_sockaddr *addr;
47   int fd;
48   int type;
49   mu_acl_t acl;
50   mu_ip_server_conn_fp f_conn;
51   mu_ip_server_intr_fp f_intr;
52   mu_ip_server_free_fp f_free;
53   void *data;
54   union
55   {
56     struct
57     {
58       int backlog;
59     } tcp_data;
60     struct
61     {
62       char *buf;
63       size_t bufsize;
64       ssize_t rdsize;
65     } udp_data;
66   } v;
67 };
68 
69 #define IDENTSTR(s) ((s)->ident ? (s)->ident : "default")
70 
71 int
mu_ip_server_create(mu_ip_server_t * psrv,struct mu_sockaddr * addr,int type)72 mu_ip_server_create (mu_ip_server_t *psrv, struct mu_sockaddr *addr, int type)
73 {
74   struct _mu_ip_server *srv;
75 
76   switch (type)
77     {
78     case MU_IP_UDP:
79     case MU_IP_TCP:
80       break;
81 
82     default:
83       return EINVAL;
84     }
85 
86   srv = calloc (1, sizeof *srv);
87   if (!srv)
88     return ENOMEM;
89   srv->addr = addr;
90   srv->type = type;
91   srv->fd = -1;
92   switch (type)
93     {
94     case MU_IP_UDP:
95       srv->v.udp_data.bufsize = 4096;
96       break;
97 
98     case MU_IP_TCP:
99       srv->v.tcp_data.backlog = 4;
100     }
101 
102   *psrv = srv;
103   return 0;
104 }
105 
106 int
mu_ip_server_destroy(mu_ip_server_t * psrv)107 mu_ip_server_destroy (mu_ip_server_t *psrv)
108 {
109   mu_ip_server_t srv;
110   if (!psrv)
111     return EINVAL;
112   srv = *psrv;
113   if (!srv)
114     return 0;
115   if (srv->f_free)
116     srv->f_free (srv->data);
117   close (srv->fd);
118   mu_sockaddr_free (srv->addr);
119   free (srv->ident);
120   if (srv->type == MU_IP_UDP && srv->v.udp_data.buf)
121     free (srv->v.udp_data.buf);
122   free (srv);
123   *psrv = NULL;
124   return 0;
125 }
126 
127 int
mu_ip_server_get_type(mu_ip_server_t srv,int * ptype)128 mu_ip_server_get_type (mu_ip_server_t srv, int *ptype)
129 {
130   if (!srv)
131     return EINVAL;
132   *ptype = srv->type;
133   return 0;
134 }
135 
136 int
mu_tcp_server_set_backlog(mu_ip_server_t srv,int backlog)137 mu_tcp_server_set_backlog (mu_ip_server_t srv, int backlog)
138 {
139   if (!srv || srv->type != MU_IP_TCP)
140     return EINVAL;
141   srv->v.tcp_data.backlog = backlog;
142   return 0;
143 }
144 
145 int
mu_udp_server_get_bufsize(mu_ip_server_t srv,size_t * psize)146 mu_udp_server_get_bufsize (mu_ip_server_t srv, size_t *psize)
147 {
148   if (!srv || srv->type != MU_IP_UDP)
149     return EINVAL;
150   *psize = srv->v.udp_data.bufsize;
151   return 0;
152 }
153 
154 int
mu_udp_server_set_bufsize(mu_ip_server_t srv,size_t size)155 mu_udp_server_set_bufsize (mu_ip_server_t srv, size_t size)
156 {
157   if (!srv || srv->type != MU_IP_UDP)
158     return EINVAL;
159   srv->v.udp_data.bufsize = size;
160   if (srv->v.udp_data.buf)
161     {
162       char *p = realloc (srv->v.udp_data.buf, size);
163       if (!p)
164 	return ENOMEM;
165       srv->v.udp_data.buf = p;
166     }
167   return 0;
168 }
169 
170 int
mu_ip_server_set_ident(mu_ip_server_t srv,const char * ident)171 mu_ip_server_set_ident (mu_ip_server_t srv, const char *ident)
172 {
173   if (!srv)
174     return EINVAL;
175   if (srv->ident)
176     free (srv->ident);
177   srv->ident = strdup (ident);
178   if (!srv->ident)
179     return ENOMEM;
180   return 0;
181 }
182 
183 int
mu_ip_server_set_acl(mu_ip_server_t srv,mu_acl_t acl)184 mu_ip_server_set_acl (mu_ip_server_t srv, mu_acl_t acl)
185 {
186   if (!srv)
187     return EINVAL;
188   srv->acl = acl;
189   return 0;
190 }
191 
192 int
mu_ip_server_set_conn(mu_ip_server_t srv,mu_ip_server_conn_fp conn)193 mu_ip_server_set_conn (mu_ip_server_t srv, mu_ip_server_conn_fp conn)
194 {
195   if (!srv)
196     return EINVAL;
197   srv->f_conn = conn;
198   return 0;
199 }
200 
201 int
mu_ip_server_set_intr(mu_ip_server_t srv,mu_ip_server_intr_fp intr)202 mu_ip_server_set_intr (mu_ip_server_t srv, mu_ip_server_intr_fp intr)
203 {
204   if (!srv)
205     return EINVAL;
206   srv->f_intr = intr;
207   return 0;
208 }
209 
210 int
mu_ip_server_set_data(mu_ip_server_t srv,void * data,mu_ip_server_free_fp free)211 mu_ip_server_set_data (mu_ip_server_t srv,
212 			void *data, mu_ip_server_free_fp free)
213 {
214   if (!srv)
215     return EINVAL;
216   srv->data = data;
217   srv->f_free = free;
218   return 0;
219 }
220 
221 void *
mu_ip_server_get_data(mu_ip_server_t tcpsrv)222 mu_ip_server_get_data (mu_ip_server_t tcpsrv)
223 {
224   return tcpsrv->data;
225 }
226 
227 int
mu_address_family_to_domain(int family)228 mu_address_family_to_domain (int family)
229 {
230   switch (family)
231     {
232     case AF_UNIX:
233       return PF_UNIX;
234 
235     case AF_INET:
236       return PF_INET;
237 
238 #ifdef MAILUTILS_IPV6
239     case AF_INET6:
240       return PF_INET6;
241 #endif
242 
243     default:
244       abort ();
245     }
246 }
247 
248 int
mu_ip_server_open(mu_ip_server_t srv)249 mu_ip_server_open (mu_ip_server_t srv)
250 {
251   int fd;
252 
253   if (!srv || srv->fd != -1)
254     return EINVAL;
255 
256   mu_debug (MU_DEBCAT_SERVER, MU_DEBUG_TRACE0,
257 	    ("opening server \"%s\" %s", IDENTSTR (srv),
258 	     mu_sockaddr_str (srv->addr)));
259 
260   fd = socket (mu_address_family_to_domain (srv->addr->addr->sa_family),
261 	       ((srv->type == MU_IP_UDP) ? SOCK_DGRAM : SOCK_STREAM), 0);
262   if (fd == -1)
263     {
264       mu_debug (MU_DEBCAT_SERVER, MU_DEBUG_ERROR,
265 		("%s: socket: %s", IDENTSTR (srv), mu_strerror (errno)));
266       return errno;
267     }
268 
269   switch (srv->addr->addr->sa_family)
270     {
271     case AF_UNIX:
272       {
273 	struct stat st;
274 	struct sockaddr_un *s_un = (struct sockaddr_un *) srv->addr;
275 
276 	if (stat (s_un->sun_path, &st))
277 	  {
278 	    if (errno != ENOENT)
279 	      {
280 		mu_debug (MU_DEBCAT_SERVER, MU_DEBUG_ERROR,
281 			  ("%s: file %s exists but cannot be stat'd: %s",
282 			   IDENTSTR (srv),
283 			   s_un->sun_path,
284 			   mu_strerror (errno)));
285 		return EAGAIN;
286 	      }
287 	  }
288 	else if (!S_ISSOCK (st.st_mode))
289 	  {
290 	    mu_debug (MU_DEBCAT_SERVER, MU_DEBUG_ERROR,
291 		      ("%s: file %s is not a socket",
292 		       IDENTSTR (srv), s_un->sun_path));
293 	    return EAGAIN;
294 	  }
295 	else if (unlink (s_un->sun_path))
296 	  {
297             mu_debug (MU_DEBCAT_SERVER,  MU_DEBUG_ERROR,
298 		      ("%s: cannot unlink file %s: %s",
299 		       IDENTSTR (srv), s_un->sun_path, mu_strerror (errno)));
300 	    return EAGAIN;
301 	  }
302       }
303       break;
304 
305     default:
306       {
307 	int t;
308 
309 	t = 1;
310 	setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &t, sizeof (t));
311       }
312     }
313 
314   if (bind (fd, srv->addr->addr, srv->addr->addrlen) == -1)
315     {
316       mu_debug (MU_DEBCAT_SERVER, MU_DEBUG_ERROR,
317 		("%s: bind: %s", IDENTSTR (srv), mu_strerror (errno)));
318       close (fd);
319       return errno;
320     }
321 
322   if (srv->type == MU_IP_TCP)
323     {
324       if (listen (fd, srv->v.tcp_data.backlog) == -1)
325 	{
326 	  mu_debug (MU_DEBCAT_SERVER, MU_DEBUG_ERROR,
327 		    ("%s: listen: %s", IDENTSTR (srv), mu_strerror (errno)));
328 	  close (fd);
329 	  return errno;
330 	}
331     }
332 
333   srv->fd = fd;
334   return 0;
335 }
336 
337 int
mu_ip_server_shutdown(mu_ip_server_t srv)338 mu_ip_server_shutdown (mu_ip_server_t srv)
339 {
340   if (!srv || srv->fd != -1)
341     return EINVAL;
342   mu_debug (MU_DEBCAT_SERVER, MU_DEBUG_TRACE0,
343 	    ("closing server \"%s\" %s", IDENTSTR (srv),
344 	     mu_sockaddr_str (srv->addr)));
345   close (srv->fd);
346   return 0;
347 }
348 
349 int
mu_ip_tcp_accept(mu_ip_server_t srv,void * call_data)350 mu_ip_tcp_accept (mu_ip_server_t srv, void *call_data)
351 {
352   int rc;
353   int connfd;
354   union
355   {
356     struct sockaddr sa;
357     struct sockaddr_in s_in;
358     struct sockaddr_un s_un;
359 #ifdef MAILUTILS_IPV6
360     struct sockaddr_in6 s_in6;
361 #endif
362   } client;
363 
364   socklen_t size = sizeof (client);
365 
366   if (!srv || srv->fd == -1 || srv->type == MU_IP_UDP)
367     return EINVAL;
368 
369   connfd = accept (srv->fd, &client.sa, &size);
370   if (connfd == -1)
371     {
372       int ec = errno;
373       switch (ec)
374         {
375 	case EINTR:
376 	  if (srv->f_intr && srv->f_intr (srv->data, call_data))
377 	    break;
378 	  /* fall through */
379 	case EAGAIN:
380 	case ECONNABORTED:
381 	  ec = 0;
382 	}
383       return ec;
384     }
385 
386   if (srv->acl)
387     {
388       mu_acl_result_t res;
389       int rc;
390 
391       rc = mu_acl_check_sockaddr (srv->acl, &client.sa, size, &res);
392       if (rc)
393 	mu_debug (MU_DEBCAT_SERVER, MU_DEBUG_ERROR,
394 		  ("%s: mu_acl_check_sockaddr: %s",
395 		   IDENTSTR (srv), strerror (rc)));
396       if (res == mu_acl_result_deny)
397 	{
398 	  char *p = mu_sys_sockaddr_to_astr (&client.sa, size);
399 	  mu_diag_output (MU_DIAG_INFO, "Denying connection from %s", p);
400 	  free (p);
401 
402 	  close (connfd);
403 	  return 0;
404 	}
405     }
406   rc = srv->f_conn (connfd, &client.sa, size, srv->data, call_data, srv);
407   close (connfd);
408   return rc;
409 }
410 
411 int
mu_ip_udp_accept(mu_ip_server_t srv,void * call_data)412 mu_ip_udp_accept (mu_ip_server_t srv, void *call_data)
413 {
414   int rc;
415   union
416   {
417     struct sockaddr sa;
418     struct sockaddr_in s_in;
419     struct sockaddr_un s_un;
420 #ifdef MAILUTILS_IPV6
421     struct sockaddr_in6 s_in6;
422 #endif
423   } client;
424   fd_set rdset;
425 
426   socklen_t salen = sizeof (client);
427   ssize_t size;
428 
429   if (!srv->v.udp_data.buf)
430     {
431       srv->v.udp_data.buf = malloc (srv->v.udp_data.bufsize);
432       if (!srv->v.udp_data.buf)
433 	return ENOMEM;
434     }
435 
436   FD_ZERO (&rdset);
437   FD_SET (srv->fd, &rdset);
438   for (;;)
439     {
440       rc = select (srv->fd + 1, &rdset, NULL, NULL, NULL);
441       if (rc == -1)
442 	{
443 	  if (errno == EINTR)
444 	    {
445 	      if (srv->f_intr && srv->f_intr (srv->data, call_data))
446 		break;
447 	      else
448 		continue;
449 	    }
450 	}
451       else
452 	break;
453     }
454 
455   if (rc == -1)
456     return errno;
457 
458   size = recvfrom (srv->fd, srv->v.udp_data.buf, srv->v.udp_data.bufsize,
459 		   0, &client.sa, &salen);
460   if (size < 0)
461     {
462       mu_debug (MU_DEBCAT_SERVER, MU_DEBUG_ERROR,
463 		("%s: recvfrom: %s",
464 		 IDENTSTR (srv), strerror (errno)));
465       return MU_ERR_FAILURE;
466     }
467   srv->v.udp_data.rdsize = size;
468 
469   if (srv->acl)
470     {
471       mu_acl_result_t res;
472       int rc;
473 
474       rc = mu_acl_check_sockaddr (srv->acl, &client.sa, size, &res);
475       if (rc)
476 	mu_debug (MU_DEBCAT_SERVER, MU_DEBUG_ERROR,
477 		  ("%s: mu_acl_check_sockaddr: %s\n",
478 		   IDENTSTR (srv), strerror (rc)));
479       if (res == mu_acl_result_deny)
480 	{
481 	  char *p = mu_sys_sockaddr_to_astr (&client.sa, salen);
482 	  mu_diag_output (MU_DIAG_INFO, "Denying connection from %s", p);
483 	  free (p);
484 	  return 0;
485 	}
486     }
487   rc = srv->f_conn (-1, &client.sa, size, srv->data, call_data, srv);
488   return rc;
489 }
490 
491 static int
set_strerr_flt(void)492 set_strerr_flt (void)
493 {
494   mu_stream_t flt, trans[2];
495   int rc;
496 
497   if (!mu_log_session_id)
498     return ENOSYS;
499 
500   rc = mu_stream_ioctl (mu_strerr, MU_IOCTL_TOPSTREAM, MU_IOCTL_OP_GET, trans);
501   if (rc == 0)
502     {
503       char *sid;
504       char *argv[] = { "inline-comment", NULL, "-S", NULL };
505 
506       rc = mu_sid (&sid);
507       if (rc)
508 	{
509 	  mu_diag_funcall (MU_DIAG_ERR, "mu_sid", NULL, rc);
510 	  return 0;
511 	}
512 
513       argv[1] = sid;
514       rc = mu_filter_create_args (&flt, trans[0], "inline-comment", 3,
515 				  (const char **)argv,
516 				  MU_FILTER_ENCODE, MU_STREAM_WRITE);
517       free (sid);
518       mu_stream_unref (trans[0]);
519       if (rc == 0)
520 	{
521 	  mu_stream_set_buffer (flt, mu_buffer_line, 0);
522 	  trans[0] = flt;
523 	  trans[1] = NULL;
524 	  rc = mu_stream_ioctl (mu_strerr, MU_IOCTL_TOPSTREAM,
525 				MU_IOCTL_OP_SET, trans);
526 	  mu_stream_unref (trans[0]);
527 	  if (rc)
528 	    mu_error (_("%s failed: %s"), "MU_IOCTL_SET_STREAM",
529 		      mu_stream_strerror (mu_strerr, rc));
530 	}
531       else
532 	mu_error (_("cannot create log filter stream: %s"), mu_strerror (rc));
533     }
534   else
535     {
536       mu_error (_("%s failed: %s"), "MU_IOCTL_GET_STREAM",
537 		mu_stream_strerror (mu_strerr, rc));
538     }
539   return rc;
540 }
541 
542 static void
clr_strerr_flt(void)543 clr_strerr_flt (void)
544 {
545   mu_stream_t flt, trans[2];
546   int rc;
547 
548   rc = mu_stream_ioctl (mu_strerr, MU_IOCTL_TOPSTREAM, MU_IOCTL_OP_GET, trans);
549   if (rc == 0)
550     {
551       flt = trans[0];
552 
553       rc = mu_stream_ioctl (flt, MU_IOCTL_TOPSTREAM, MU_IOCTL_OP_GET, trans);
554       if (rc == 0)
555 	{
556 	  mu_stream_unref (trans[0]);
557 	  rc = mu_stream_ioctl (mu_strerr, MU_IOCTL_TOPSTREAM,
558 				MU_IOCTL_OP_SET, trans);
559 	  if (rc == 0)
560 	    mu_stream_unref (flt);
561 	}
562     }
563 }
564 
565 int
mu_ip_server_accept(mu_ip_server_t srv,void * call_data)566 mu_ip_server_accept (mu_ip_server_t srv, void *call_data)
567 {
568   int rc;
569   int flt;
570 
571   if (!srv || srv->fd == -1)
572     return EINVAL;
573 
574   flt = set_strerr_flt ();
575 
576   switch (srv->type)
577     {
578     case MU_IP_UDP:
579       rc = mu_ip_udp_accept (srv, call_data);
580       break;
581 
582     case MU_IP_TCP:
583       rc = mu_ip_tcp_accept (srv, call_data);
584     }
585 
586   if (rc)
587     {
588       mu_error (_("socket error on \"%s\": %s"), IDENTSTR (srv),
589                 mu_strerror (rc));
590       mu_ip_server_shutdown (srv);
591     }
592   if (flt == 0)
593     clr_strerr_flt ();
594   return rc;
595 }
596 
597 int
mu_ip_server_get_fd(mu_ip_server_t srv)598 mu_ip_server_get_fd (mu_ip_server_t srv)
599 {
600   return srv->fd;
601 }
602 
603 int
mu_udp_server_get_rdata(mu_ip_server_t srv,char ** pbuf,size_t * pbufsize)604 mu_udp_server_get_rdata (mu_ip_server_t srv, char **pbuf, size_t *pbufsize)
605 {
606   if (!srv || srv->type != MU_IP_UDP)
607     return EINVAL;
608   *pbuf = srv->v.udp_data.buf;
609   *pbufsize = srv->v.udp_data.rdsize;
610   return 0;
611 }
612 
613 int
mu_ip_server_get_sockaddr(mu_ip_server_t srv,struct mu_sockaddr ** psa)614 mu_ip_server_get_sockaddr (mu_ip_server_t srv, struct mu_sockaddr **psa)
615 {
616   if (!srv || !psa)
617     return EINVAL;
618   return mu_sockaddr_copy (psa, srv->addr);
619 }
620 
621 const char *
mu_ip_server_addrstr(mu_ip_server_t srv)622 mu_ip_server_addrstr (mu_ip_server_t srv)
623 {
624   return mu_sockaddr_str (srv->addr);
625 }
626 
627