1 /*
2  * (c) Copyright 1992 by Panagiotis Tsirigotis
3  * (c) Sections Copyright 1998-2001 by Rob Braun
4  * All rights reserved.  The file named COPYRIGHT specifies the terms
5  * and conditions for redistribution.
6  */
7 
8 
9 #include "config.h"
10 #include <sys/types.h>
11 #include <sys/socket.h>
12 #include <netinet/in.h>
13 #include <arpa/inet.h>
14 #include <errno.h>
15 #include <time.h>
16 #include <syslog.h>
17 #include <stdlib.h>
18 #include <unistd.h>
19 #ifdef HAVE_NETDB_H
20 #include <netdb.h>
21 #endif
22 
23 #include "str.h"
24 #include "pset.h"
25 #include "sio.h"
26 #include "builtins.h"
27 #include "msg.h"
28 #include "connection.h"
29 #include "server.h"
30 #include "service.h"
31 #include "sconf.h"
32 #include "main.h"
33 #include "util.h"
34 #include "xconfig.h"
35 #include "state.h"
36 #include "libportable.h"
37 #include "signals.h"
38 #include "nvlists.h"
39 #include "child.h"
40 #include "access.h"
41 
42 #define BUFFER_SIZE               1024
43 
44 static void stream_echo(const struct server *) ;
45 static void dgram_echo(const struct server *) ;
46 static void stream_discard(const struct server *) ;
47 static void dgram_discard(const struct server *) ;
48 static void stream_time(const struct server *) ;
49 static void dgram_time(const struct server *) ;
50 static void stream_daytime(const struct server *) ;
51 static void dgram_daytime(const struct server *) ;
52 static void stream_chargen(const struct server *) ;
53 static void dgram_chargen(const struct server *) ;
54 static void tcpmux_handler(const struct server *) ;
55 
56 /*
57  * SG - This is the call sequence to get to a built-in service
58  *
59  *   main_loop                  main.c
60  *    svc_request                  service.c
61  *     svc_handle -- aka svc_handler_func -- aka svc_generic_handler   service.c
62  *      server_run                      server.c
63  *       server_internal               server.c
64  *      SC_INTERNAL               service.h
65  *       BUILTIN_INVOKE               sc_conf.h
66  *        sc_builtin -- index into builtin_services   builtins.c
67  */
68 
69 static const struct builtin_service builtin_services[] =
70    {
71       { "echo",      SOCK_STREAM,   { stream_echo,     FORK    } },
72       { "echo",      SOCK_DGRAM,    { dgram_echo,      NO_FORK } },
73       { "discard",   SOCK_STREAM,   { stream_discard,  FORK    } },
74       { "discard",   SOCK_DGRAM,    { dgram_discard,   NO_FORK } },
75       { "time",      SOCK_STREAM,   { stream_time,     NO_FORK } },
76       { "time",      SOCK_DGRAM,    { dgram_time,      NO_FORK } },
77       { "daytime",   SOCK_STREAM,   { stream_daytime,  NO_FORK } },
78       { "daytime",   SOCK_DGRAM,    { dgram_daytime,   NO_FORK } },
79       { "chargen",   SOCK_STREAM,   { stream_chargen,  FORK    } },
80       { "chargen",   SOCK_DGRAM,    { dgram_chargen,   NO_FORK } },
81       { "sensor",    SOCK_STREAM,   { stream_discard,  NO_FORK } },
82       { "sensor",    SOCK_DGRAM,    { dgram_discard,   NO_FORK } },
83       { "tcpmux",    SOCK_STREAM,   { tcpmux_handler,  FORK    } },
84       { NULL,        0,             { NULL,            0       } }
85    } ;
86 
87 
builtin_find(const char * service_name,int type)88 const builtin_s *builtin_find( const char *service_name, int type )
89 {
90    const builtin_s   *bsp ;
91    const char        *func = "builtin_find" ;
92 
93    if ( (bsp = builtin_lookup( builtin_services, service_name, type )) )
94       return( bsp ) ;
95    else
96    {
97 	const char *type_name;
98    	const struct name_value *sock_type = nv_find_name( socket_types, type );
99 	if (sock_type == NULL)
100 		type_name = "Unknown socket type";
101 	else
102 		type_name = sock_type->name;
103 	msg( LOG_ERR, func, "No such internal service: %s/%s - DISABLING",
104 			service_name, type_name ) ;
105 	return( NULL ) ;
106    }
107 }
108 
109 
builtin_lookup(const struct builtin_service services[],const char * service_name,int type)110 const builtin_s *builtin_lookup( const struct builtin_service services[],
111                            const char *service_name,
112                            int type )
113 {
114    const struct builtin_service *bsp ;
115 
116    for ( bsp = services ; bsp->bs_name != NULL ; bsp++ )
117       if ( EQ( bsp->bs_name, service_name ) && bsp->bs_socket_type == type )
118          return( &bsp->bs_handle ) ;
119    return( NULL ) ;
120 }
121 
122 
123 /*
124  * The rest of this file contains the functions that implement the
125  * builtin services
126  */
127 
128 
stream_echo(const struct server * serp)129 static void stream_echo( const struct server *serp )
130 {
131    char   buf[ BUFFER_SIZE ] ;
132    ssize_t    cc ;
133    int    descriptor = SERVER_FD( serp ) ;
134    struct service *svc = SERVER_SERVICE( serp ) ;;
135 
136    if( SVC_WAITS( svc ) ) {
137       descriptor = accept(descriptor, NULL, NULL);
138       if ( descriptor == -1 ) {
139          if ((errno == EMFILE) || (errno == ENFILE))
140             cps_service_stop(svc, "no available descriptors");
141          return;
142       }
143    }
144 
145    close_all_svc_descriptors();
146 
147    for ( ;; )
148    {
149       cc = read( descriptor, buf, sizeof( buf ) ) ;
150       if ( cc == 0 )
151          break ;
152       if ( cc == (ssize_t)-1 ) {
153          if ( errno == EINTR )
154             continue ;
155          else
156             break ;
157       }
158 
159       if ( write_buf( descriptor, buf, cc ) == FAILED )
160          break ;
161    }
162    if( SVC_WAITS( svc ) ) /* Service forks, so close it */
163       Sclose(descriptor);
164 }
165 
dgram_echo(const struct server * serp)166 static void dgram_echo( const struct server *serp )
167 {
168    char            buf[ DATAGRAM_SIZE ] ;
169    union xsockaddr lsin;
170    ssize_t             cc ;
171    socklen_t       sin_len = 0;
172    int             descriptor = SERVER_FD( serp ) ;
173 
174    if( SC_IPV4( SVC_CONF( SERVER_SERVICE( serp ) ) ) )
175       sin_len = sizeof( struct sockaddr_in );
176    else if( SC_IPV6( SVC_CONF( SERVER_SERVICE( serp ) ) ) )
177       sin_len = sizeof( struct sockaddr_in6 );
178 
179    cc = recvfrom( descriptor, buf, sizeof( buf ), 0, (struct sockaddr *)( &lsin ), &sin_len ) ;
180    if ( cc != (ssize_t)-1 ) {
181       (void) sendto( descriptor, buf, (size_t)cc, 0, SA( &lsin ), sizeof( lsin ) ) ;
182    }
183 }
184 
stream_discard(const struct server * serp)185 static void stream_discard( const struct server *serp )
186 {
187    char  buf[ BUFFER_SIZE ] ;
188    ssize_t   cc ;
189    int    descriptor = SERVER_FD( serp ) ;
190    struct service *svc = SERVER_SERVICE( serp ) ;;
191 
192    if( SVC_WAITS( svc ) ) {
193       descriptor = accept(descriptor, NULL, NULL);
194       if ( descriptor == -1 ) {
195          if ((errno == EMFILE) || (errno == ENFILE))
196             cps_service_stop(svc, "no available descriptors");
197          return;
198       }
199    }
200 
201    close_all_svc_descriptors();
202 
203    for ( ;; )
204    {
205       cc = read( descriptor, buf, sizeof( buf ) ) ;
206       if ( (cc == 0) || ((cc == (ssize_t)-1) && (errno != EINTR)) )
207          break ;
208    }
209    if( SVC_WAITS( svc ) ) /* Service forks, so close it */
210       Sclose(descriptor);
211 }
212 
213 
dgram_discard(const struct server * serp)214 static void dgram_discard( const struct server *serp )
215 {
216    char buf[ 1 ] ;
217 
218    (void) recv( SERVER_FD( serp ), buf, sizeof( buf ), 0 ) ;
219 }
220 
221 
222 /*
223  * Generate the current time using the SMTP format:
224  *      02 FEB 1991 12:31:42 MST
225  *
226  * The result is placed in buf.
227  * buflen is a value-result parameter. It indicates the size of
228  * buf and on exit it has the length of the string placed in buf.
229  */
daytime_protocol(char * buf,unsigned int * buflen)230 static void daytime_protocol( char *buf, unsigned int *buflen )
231 {
232    static const char *month_name[] =
233       {
234          "JAN", "FEB", "MAR", "APR", "MAY", "JUN",
235          "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"
236       } ;
237    time_t      now ;
238    struct tm   *tmp ;
239    int         size = *buflen ;
240 #ifdef HAVE_STRFTIME
241    int      cc ;
242 #endif
243 
244    (void) time( &now ) ;
245    tmp = localtime( &now ) ;
246 #ifndef HAVE_STRFTIME
247    strx_print( buflen, buf, size,
248       "%02d %s %d %02d:%02d:%02d %s\r\n",
249          tmp->tm_mday, month_name[ tmp->tm_mon ], 1900 + tmp->tm_year,
250             tmp->tm_hour, tmp->tm_min, tmp->tm_sec, tmp->tm_zone ) ;
251 #else
252    cc = strx_nprint( buf, size,
253       "%02d %s %d %02d:%02d:%02d",
254          tmp->tm_mday, month_name[ tmp->tm_mon ], 1900 + tmp->tm_year,
255             tmp->tm_hour, tmp->tm_min, tmp->tm_sec ) ;
256    if ( cc >= 0 ) {
257       *buflen = cc ;
258       size -= cc ;
259       cc = strftime( &buf[ *buflen ], (size_t)size, " %Z\r\n", tmp ) ;
260       *buflen += cc ;
261    }
262 #endif
263 }
264 
265 
stream_daytime(const struct server * serp)266 static void stream_daytime( const struct server *serp )
267 {
268    char  time_buf[ BUFFER_SIZE ] ;
269    unsigned int buflen = sizeof( time_buf ) ;
270    int    descriptor = SERVER_FD( serp ) ;
271    struct service *svc = SERVER_SERVICE( serp ) ;;
272 
273    if( SVC_WAITS( svc ) ) {
274       descriptor = accept(descriptor, NULL, NULL);
275       if ( descriptor == -1 ) {
276          if ((errno == EMFILE) || (errno == ENFILE))
277             cps_service_stop(svc, "no available descriptors");
278          return;
279       }
280    }
281    daytime_protocol( time_buf, &buflen ) ;
282    (void) write_buf( descriptor, time_buf, (int)buflen ) ;
283    Sclose(descriptor);
284 }
285 
286 
dgram_daytime(const struct server * serp)287 static void dgram_daytime( const struct server *serp )
288 {
289    char            time_buf[ BUFFER_SIZE ] ;
290    union xsockaddr lsin ;
291    socklen_t       sin_len     = 0 ;
292    unsigned int    buflen      = sizeof( time_buf ) ;
293    int             descriptor  = SERVER_FD( serp ) ;
294    ssize_t         val;
295 
296    if ( SC_IPV4( SVC_CONF( SERVER_SERVICE( serp ) ) ) )
297       sin_len = sizeof( struct sockaddr_in );
298    else if ( SC_IPV6( SVC_CONF( SERVER_SERVICE( serp ) ) ) )
299       sin_len = sizeof( struct sockaddr_in6 );
300 
301    val = recvfrom( descriptor, time_buf, sizeof( time_buf ), 0,
302             (struct sockaddr *)( &lsin ), &sin_len );
303    if ( val == (ssize_t)-1 )
304       return ;
305 
306    daytime_protocol( time_buf, &buflen ) ;
307 
308    (void) sendto( descriptor, time_buf, buflen, 0, SA(&lsin), sizeof( lsin ) ) ;
309 }
310 
311 
312 #define TIME_OFFSET         2208988800UL
313 
314 /*
315  * We always report the time as 32 bits in network-byte-order
316  */
time_protocol(unsigned char * timep)317 static void time_protocol( unsigned char *timep )
318 {
319    time_t now ;
320    unsigned long base1900;
321 
322    (void) time( &now ) ;
323    base1900 = (unsigned long)now + TIME_OFFSET ;
324    timep[0] = base1900 >> 24;
325    timep[1] = base1900 >> 16;
326    timep[2] = base1900 >> 8;
327    timep[3] = base1900;
328 
329 }
330 
331 
stream_time(const struct server * serp)332 static void stream_time( const struct server *serp )
333 {
334    unsigned char time_buf[4];
335    int descriptor = SERVER_FD( serp );
336    struct service *svc = SERVER_SERVICE( serp );
337 
338    if( SVC_WAITS( svc ) ) {
339       descriptor = accept(descriptor, NULL, NULL);
340       if ( descriptor == -1 ) {
341          if ((errno == EMFILE) || (errno == ENFILE))
342             cps_service_stop(svc, "no available descriptors");
343          return;
344       }
345    }
346 
347    time_protocol( time_buf ) ;
348    (void) write_buf( descriptor, (char *) time_buf, 4 ) ;
349 
350    Sclose(descriptor);
351 }
352 
353 
dgram_time(const struct server * serp)354 static void dgram_time( const struct server *serp )
355 {
356    char     buf[ 1 ] ;
357    unsigned char time_buf[4];
358    union xsockaddr lsin ;
359    socklen_t       sin_len = 0 ;
360    int             fd      = SERVER_FD( serp ) ;
361    ssize_t         val;
362 
363    if ( SC_IPV4( SVC_CONF( SERVER_SERVICE( serp ) ) ) )
364       sin_len = sizeof( struct sockaddr_in );
365    else if ( SC_IPV6( SVC_CONF( SERVER_SERVICE( serp ) ) ) )
366       sin_len = sizeof( struct sockaddr_in6 );
367 
368    val = recvfrom( fd, buf, sizeof( buf ), 0, (struct sockaddr *)( &lsin ), &sin_len );
369    if ( val == (ssize_t)-1 )
370       return ;
371 
372    time_protocol( time_buf ) ;
373    (void) sendto( fd, (char *) time_buf, 4, 0, SA( &lsin ), sin_len ) ;
374 }
375 
376 
377 #define ASCII_PRINTABLE_CHARS     94
378 #define LINE_LENGTH               72
379 
380 #define RING_BUF_SIZE             ASCII_PRINTABLE_CHARS + LINE_LENGTH
381 
382 static char *ring_buf = NULL ;
383 static char *ring ;
384 
385 
386 #define ASCII_START          ( ' ' + 1 )
387 #define ASCII_END            126
388 
389 #define min( a, b )          ((a)<(b) ? (a) : (b))
390 
generate_line(char * buf,unsigned int len)391 static char *generate_line( char *buf, unsigned int len )
392 {
393    unsigned int line_len = min( LINE_LENGTH, len-2 ) ;
394 
395    if ( len < 2 )       /* If len < 2, min will be wrong */
396       return( NULL ) ;
397 
398    /* This never gets freed.  That's ok, because the reference to it is
399     * always kept for future reference.
400     */
401    if ( (ring_buf == NULL) && ((ring_buf = malloc(RING_BUF_SIZE)) == NULL) )
402       return(NULL);
403 
404    if ( ring == NULL )
405    {
406       char ch ;
407       char *p ;
408 
409       for ( p = ring_buf, ch = ASCII_START ;
410             p <= &ring_buf[ RING_BUF_SIZE - 1 ] ; p++ )
411       {
412          *p = ch++ ;
413          if ( ch == ASCII_END )
414             ch = ASCII_START ;
415       }
416       ring = ring_buf ;
417    }
418    (void) memcpy( buf, ring, line_len ) ;
419    buf[ line_len   ] = '\r' ;
420    buf[ line_len+1 ] = '\n' ;
421 
422    ring++ ;
423    if ( &ring_buf[ RING_BUF_SIZE - 1 ] - ring + 1 < LINE_LENGTH )
424       ring = ring_buf ;
425    return( buf ) ;
426 }
427 
428 
stream_chargen(const struct server * serp)429 static void stream_chargen( const struct server *serp )
430 {
431    char   line_buf[ LINE_LENGTH+2 ] ;
432    int    descriptor = SERVER_FD( serp ) ;
433    struct service *svc = SERVER_SERVICE( serp );
434 
435    if( SVC_WAITS( svc ) ) {
436       descriptor = accept(descriptor, NULL, NULL);
437       if ( descriptor == -1 ) {
438          if ((errno == EMFILE) || (errno == ENFILE))
439             cps_service_stop(svc, "no available descriptors");
440          return;
441       }
442    }
443 
444    (void) shutdown( descriptor, 0 ) ;
445    close_all_svc_descriptors();
446 
447    for ( ;; )
448    {
449       if ( generate_line( line_buf, sizeof( line_buf ) ) == NULL )
450          break ;
451       if ( write_buf( descriptor, line_buf, sizeof( line_buf ) ) == FAILED )
452          break ;
453    }
454    if( SVC_WAITS( svc ) ) /* Service forks, so close it */
455       Sclose(descriptor);
456 }
457 
458 
dgram_chargen(const struct server * serp)459 static void dgram_chargen( const struct server *serp )
460 {
461    char            buf[ BUFFER_SIZE ] ;
462    char            *p ;
463    unsigned int    len ;
464    union xsockaddr lsin ;
465    socklen_t       sin_len = 0 ;
466    int             fd      = SERVER_FD( serp ) ;
467    unsigned int    left    = sizeof( buf ) ;
468    ssize_t         val;
469 
470    if ( SC_IPV4( SVC_CONF( SERVER_SERVICE( serp ) ) ) )
471       sin_len = sizeof( struct sockaddr_in );
472    else if ( SC_IPV6( SVC_CONF( SERVER_SERVICE( serp ) ) ) )
473       sin_len = sizeof( struct sockaddr_in6 );
474 
475    val = recvfrom( fd, buf, (size_t)sizeof( buf ), 0, (struct sockaddr *)( &lsin ), &sin_len );
476    if ( val == (ssize_t)-1 )
477       return ;
478 
479 #if BUFFER_SIZE < LINE_LENGTH+2
480    bad_variable = 1 ;      /* this will cause a compilation error */
481 #endif
482 
483    for ( p = buf ; left > 2 ; left -= len, p += len )
484    {
485       len = min( LINE_LENGTH+2, left ) ;
486       if ( generate_line( p, len ) == NULL )
487          break ;
488    }
489    (void) sendto( fd, buf, (size_t)(p-buf), 0, SA( &lsin ), sin_len ) ;
490 }
491 
492 
493 /*  Handle a request for a tcpmux service.
494  *  It's helpful to remember here that we are now a child of the original
495  *  xinetd process. We were forked to keep the parent from blocking
496  *  when we try to read the service name off'n the socket connection.
497  *  Serp still points to an actual tcpmux 'server', or at least the
498  *  service pointer of serp is valid.
499  */
500 
tcpmux_handler(const struct server * serp)501 static void tcpmux_handler( const struct server *serp )
502 {
503    char      svc_name[ BUFFER_SIZE ] ;
504    int       cc ;
505    int       descriptor = SERVER_FD( serp ) ;
506    const     struct service *svc = SERVER_SERVICE( serp ) ;
507    unsigned  u;
508    struct    service *sp = NULL;
509    struct    server server, *nserp;
510    struct    service_config *scp = NULL;
511 
512    close_all_svc_descriptors();
513 
514    /*  Read in the name of the service in the format "svc_name\r\n".
515     *
516     *  XXX: should loop on partial reads (could probably use Sread() if
517     *  it wasn't thrown out of xinetd source code a few revisions back).
518     */
519    do
520    {
521       cc = read( descriptor, svc_name, sizeof( svc_name ) ) ;
522    } while (cc == -1 && errno == EINTR);
523 
524    if ( cc <= 0 )
525    {
526       msg(LOG_ERR, "tcpmux_handler", "read failed");
527       exit(0);
528    }
529 
530    if ( ( cc <= 2 ) ||
531         ( ( svc_name[cc - 1] != '\n' ) || ( svc_name[cc - 2] != '\r' ) ) )
532    {
533       if ( debug.on )
534          msg(LOG_DEBUG, "tcpmux_handler", "Invalid service name format.");
535 
536       exit(0);
537    }
538 
539    svc_name[cc - 2] = '\0';  /*  Remove \r\n for compare */
540 
541    if ( debug.on )
542    {
543       msg(LOG_DEBUG, "tcpmux_handler", "Input (%d bytes) %s as service name.",
544           cc, svc_name);
545    }
546 
547    /*  Search the services for the a match on name.
548     */
549 
550    for ( u = 0 ; u < pset_count( SERVICES( ps ) ) ; u++ )
551    {
552       sp = SP( pset_pointer( SERVICES( ps ), u ) ) ;
553 
554       if ( strcasecmp( svc_name, SC_NAME( SVC_CONF( sp ) ) ) == 0 )
555       {
556          /*  Found the pointer. Validate its type.
557           */
558          scp = SVC_CONF( sp );
559 
560          if ( ! SVC_IS_MUXCLIENT( sp ) && ! SVC_IS_MUXPLUSCLIENT( sp ) )
561          {
562             if ( debug.on )
563             {
564                msg(LOG_DEBUG, "tcpmux_handler", "Non-tcpmux service name: %s.",
565                    svc_name);
566             }
567             continue;
568          }
569 
570          /*  Send the accept string if we're a PLUS (+) client.
571           */
572 
573          if ( SVC_IS_MUXPLUSCLIENT( sp ) )
574          {
575             if ( Swrite( descriptor, TCPMUX_ACK, sizeof( TCPMUX_ACK ) ) !=
576                  sizeof( TCPMUX_ACK ) )
577             {
578                 msg(LOG_ERR, "tcpmux_handler", "Ack write failed for %s.",
579 		    svc_name);
580                 exit(0);
581             }
582          }
583          break;  /*  Time to get on with the service */
584       }
585       continue;  /*  Keep looking */
586    }
587 
588    if ( u >= pset_count( SERVICES( ps ) ) )
589    {
590       if ( debug.on )
591       {
592          msg(LOG_DEBUG, "tcpmux_handler", "Service name %s not found.",
593              svc_name);
594       }
595 
596       /*  If a service was not found, we should say so. */
597       if ( Swrite( descriptor, TCPMUX_NOT_FOUND, sizeof( TCPMUX_NOT_FOUND ) ) !=
598            sizeof ( TCPMUX_NOT_FOUND ) )
599       {
600          msg(LOG_ERR, "tcpmux_handler", "Not found write failed for %s.",
601              svc_name);
602          exit(0);
603       }
604 
605       /*  Flush and exit, nothing to do */
606       Sflush( descriptor );
607       Sclose( descriptor );
608       exit(0);
609    }
610 
611    if( SVC_WAITS( svc ) ) /* Service forks, so close it */
612       Sclose(descriptor);
613 
614    server.svr_sp = sp;
615    server.svr_conn = SERVER_CONNECTION(serp);
616    nserp = server_alloc(&server);
617    if( SC_IS_INTERNAL( scp ) ) {
618       SC_INTERNAL(scp, nserp);
619    } else {
620       child_process(nserp);
621    }
622 }
623 
624